66#define _GNU_SOURCE
77#include <inttypes.h>
88#include <stdio.h>
9+ #include <zlib.h>
910
1011#include "gendwarfksyms.h"
1112
@@ -178,6 +179,33 @@ static void type_map_free(void)
178179 hash_init (type_map );
179180}
180181
182+ /*
183+ * CRC for a type, with an optional fully expanded type string for
184+ * debugging.
185+ */
186+ struct version {
187+ struct type_expansion type ;
188+ unsigned long crc ;
189+ };
190+
191+ static void version_init (struct version * version )
192+ {
193+ version -> crc = crc32 (0 , NULL , 0 );
194+ type_expansion_init (& version -> type );
195+ }
196+
197+ static void version_free (struct version * version )
198+ {
199+ type_expansion_free (& version -> type );
200+ }
201+
202+ static void version_add (struct version * version , const char * s )
203+ {
204+ version -> crc = crc32 (version -> crc , (void * )s , strlen (s ));
205+ if (dump_versions )
206+ type_expansion_append (& version -> type , s , NULL );
207+ }
208+
181209/*
182210 * Type reference format: <prefix>#<name>, where prefix:
183211 * s -> structure
@@ -187,6 +215,12 @@ static void type_map_free(void)
187215 *
188216 * Names with spaces are additionally wrapped in single quotes.
189217 */
218+ static inline bool is_type_prefix (const char * s )
219+ {
220+ return (s [0 ] == 's' || s [0 ] == 'u' || s [0 ] == 'e' || s [0 ] == 't' ) &&
221+ s [1 ] == '#' ;
222+ }
223+
190224static char get_type_prefix (int tag )
191225{
192226 switch (tag ) {
@@ -214,6 +248,8 @@ static char *get_type_name(struct die *cache)
214248 warn ("found incomplete cache entry: %p" , cache );
215249 return NULL ;
216250 }
251+ if (cache -> state == DIE_SYMBOL )
252+ return NULL ;
217253 if (!cache -> fqn || !* cache -> fqn )
218254 return NULL ;
219255
@@ -231,6 +267,39 @@ static char *get_type_name(struct die *cache)
231267 return name ;
232268}
233269
270+ static void __calculate_version (struct version * version , struct list_head * list )
271+ {
272+ struct type_list_entry * entry ;
273+ struct type_expansion * e ;
274+
275+ /* Calculate a CRC over an expanded type string */
276+ list_for_each_entry (entry , list , list ) {
277+ if (is_type_prefix (entry -> str )) {
278+ check (type_map_get (entry -> str , & e ));
279+
280+ /*
281+ * It's sufficient to expand each type reference just
282+ * once to detect changes.
283+ */
284+ if (cache_was_expanded (& expansion_cache , e )) {
285+ version_add (version , entry -> str );
286+ } else {
287+ cache_mark_expanded (& expansion_cache , e );
288+ __calculate_version (version , & e -> expanded );
289+ }
290+ } else {
291+ version_add (version , entry -> str );
292+ }
293+ }
294+ }
295+
296+ static void calculate_version (struct version * version , struct list_head * list )
297+ {
298+ version_init (version );
299+ __calculate_version (version , list );
300+ cache_free (& expansion_cache );
301+ }
302+
234303static void __type_expand (struct die * cache , struct type_expansion * type ,
235304 bool recursive );
236305
@@ -337,7 +406,49 @@ static void expand_type(struct die *cache, void *arg)
337406 free (name );
338407}
339408
340- void generate_symtypes (FILE * file )
409+ static void expand_symbol (struct symbol * sym , void * arg )
410+ {
411+ struct type_expansion type ;
412+ struct version version ;
413+ struct die * cache ;
414+
415+ /*
416+ * No need to expand again unless we want a symtypes file entry
417+ * for the symbol. Note that this means `sym` has the same address
418+ * as another symbol that was already processed.
419+ */
420+ if (!symtypes && sym -> state == SYMBOL_PROCESSED )
421+ return ;
422+
423+ if (__die_map_get (sym -> die_addr , DIE_SYMBOL , & cache ))
424+ return ; /* We'll warn about missing CRCs later. */
425+
426+ type_expand (cache , & type , false);
427+
428+ /* If the symbol already has a version, don't calculate it again. */
429+ if (sym -> state != SYMBOL_PROCESSED ) {
430+ calculate_version (& version , & type .expanded );
431+ symbol_set_crc (sym , version .crc );
432+ debug ("%s = %lx" , sym -> name , version .crc );
433+
434+ if (dump_versions ) {
435+ checkp (fputs (sym -> name , stderr ));
436+ checkp (fputs (" " , stderr ));
437+ type_list_write (& version .type .expanded , stderr );
438+ checkp (fputs ("\n" , stderr ));
439+ }
440+
441+ version_free (& version );
442+ }
443+
444+ /* These aren't needed in type_map unless we want a symtypes file. */
445+ if (symtypes )
446+ type_map_add (sym -> name , & type );
447+
448+ type_expansion_free (& type );
449+ }
450+
451+ void generate_symtypes_and_versions (FILE * file )
341452{
342453 cache_init (& expansion_cache );
343454
@@ -355,7 +466,14 @@ void generate_symtypes(FILE *file)
355466 die_map_for_each (expand_type , NULL );
356467
357468 /*
358- * 2. If a symtypes file is requested, write type_map contents to
469+ * 2. For each exported symbol, expand the die_map type, and use
470+ * type_map expansions to calculate a symbol version from the
471+ * fully expanded type string.
472+ */
473+ symbol_for_each (expand_symbol , NULL );
474+
475+ /*
476+ * 3. If a symtypes file is requested, write type_map contents to
359477 * the file.
360478 */
361479 type_map_write (file );
0 commit comments