Skip to content

Commit ab44399

Browse files
samitolvanenmasahir0y
authored andcommitted
gendwarfksyms: Add symtypes output
Add support for producing genksyms-style symtypes files. Process die_map to find the longest expansions for each type, and use symtypes references in type definitions. The basic file format is similar to genksyms, with two notable exceptions: 1. Type names with spaces (common with Rust) in references are wrapped in single quotes. E.g.: s#'core::result::Result<u8, core::num::error::ParseIntError>' 2. The actual type definition is the simple parsed DWARF format we output with --dump-dies, not the preprocessed C-style format genksyms produces. Signed-off-by: Sami Tolvanen <samitolvanen@google.com> Reviewed-by: Petr Pavlu <petr.pavlu@suse.com> Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
1 parent d2ffdc1 commit ab44399

7 files changed

Lines changed: 429 additions & 3 deletions

File tree

scripts/gendwarfksyms/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ gendwarfksyms-objs += cache.o
66
gendwarfksyms-objs += die.o
77
gendwarfksyms-objs += dwarf.o
88
gendwarfksyms-objs += symbols.o
9+
gendwarfksyms-objs += types.o
910

1011
HOSTLDLIBS_gendwarfksyms := -ldw -lelf

scripts/gendwarfksyms/die.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static inline unsigned int die_hash(uintptr_t addr, enum die_state state)
2222
static void init_die(struct die *cd)
2323
{
2424
cd->state = DIE_INCOMPLETE;
25+
cd->mapped = false;
2526
cd->fqn = NULL;
2627
cd->tag = -1;
2728
cd->addr = 0;
@@ -83,6 +84,16 @@ static void reset_die(struct die *cd)
8384
init_die(cd);
8485
}
8586

87+
void die_map_for_each(die_map_callback_t func, void *arg)
88+
{
89+
struct hlist_node *tmp;
90+
struct die *cd;
91+
92+
hash_for_each_safe(die_map, cd, tmp, hash) {
93+
func(cd, arg);
94+
}
95+
}
96+
8697
void die_map_free(void)
8798
{
8899
struct hlist_node *tmp;

scripts/gendwarfksyms/dwarf.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ static void process_symbol(struct state *state, Dwarf_Die *die,
745745
{
746746
debug("%s", state->sym->name);
747747
check(process_func(state, NULL, die));
748+
state->sym->state = SYMBOL_MAPPED;
748749
if (dump_dies)
749750
fputs("\n", stderr);
750751
}

scripts/gendwarfksyms/gendwarfksyms.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ int debug;
2121
int dump_dies;
2222
/* Print debugging information about die_map changes */
2323
int dump_die_map;
24+
/* Print out type strings (i.e. type_map) */
25+
int dump_types;
26+
/* Write a symtypes file */
27+
int symtypes;
28+
static const char *symtypes_file;
2429

2530
static void usage(void)
2631
{
@@ -29,6 +34,8 @@ static void usage(void)
2934
" -d, --debug Print debugging information\n"
3035
" --dump-dies Dump DWARF DIE contents\n"
3136
" --dump-die-map Print debugging information about die_map changes\n"
37+
" --dump-types Dump type strings\n"
38+
" -T, --symtypes file Write a symtypes file\n"
3239
" -h, --help Print this message\n"
3340
"\n",
3441
stderr);
@@ -41,6 +48,7 @@ static int process_module(Dwfl_Module *mod, void **userdata, const char *name,
4148
Dwarf_Die cudie;
4249
Dwarf_CU *cu = NULL;
4350
Dwarf *dbg;
51+
FILE *symfile = arg;
4452
int res;
4553

4654
debug("%s", name);
@@ -60,6 +68,10 @@ static int process_module(Dwfl_Module *mod, void **userdata, const char *name,
6068
process_cu(&cudie);
6169
} while (cu);
6270

71+
/*
72+
* Use die_map to expand type strings and write them to `symfile`.
73+
*/
74+
generate_symtypes(symfile);
6375
die_map_free();
6476

6577
return DWARF_CB_OK;
@@ -72,24 +84,31 @@ static const Dwfl_Callbacks callbacks = {
7284

7385
int main(int argc, char **argv)
7486
{
87+
FILE *symfile = NULL;
7588
unsigned int n;
7689
int opt;
7790

7891
static const struct option opts[] = {
7992
{ "debug", 0, NULL, 'd' },
8093
{ "dump-dies", 0, &dump_dies, 1 },
8194
{ "dump-die-map", 0, &dump_die_map, 1 },
95+
{ "dump-types", 0, &dump_types, 1 },
96+
{ "symtypes", 1, NULL, 'T' },
8297
{ "help", 0, NULL, 'h' },
8398
{ 0, 0, NULL, 0 }
8499
};
85100

86-
while ((opt = getopt_long(argc, argv, "dh", opts, NULL)) != EOF) {
101+
while ((opt = getopt_long(argc, argv, "dT:h", opts, NULL)) != EOF) {
87102
switch (opt) {
88103
case 0:
89104
break;
90105
case 'd':
91106
debug = 1;
92107
break;
108+
case 'T':
109+
symtypes = 1;
110+
symtypes_file = optarg;
111+
break;
93112
case 'h':
94113
usage();
95114
return 0;
@@ -109,6 +128,13 @@ int main(int argc, char **argv)
109128

110129
symbol_read_exports(stdin);
111130

131+
if (symtypes_file) {
132+
symfile = fopen(symtypes_file, "w");
133+
if (!symfile)
134+
error("fopen failed for '%s': %s", symtypes_file,
135+
strerror(errno));
136+
}
137+
112138
for (n = optind; n < argc; n++) {
113139
Dwfl *dwfl;
114140
int fd;
@@ -131,12 +157,15 @@ int main(int argc, char **argv)
131157

132158
dwfl_report_end(dwfl, NULL, NULL);
133159

134-
if (dwfl_getmodules(dwfl, &process_module, NULL, 0))
160+
if (dwfl_getmodules(dwfl, &process_module, symfile, 0))
135161
error("dwfl_getmodules failed for '%s'", argv[n]);
136162

137163
dwfl_end(dwfl);
138164
}
139165

166+
if (symfile)
167+
check(fclose(symfile));
168+
140169
symbol_free();
141170

142171
return 0;

scripts/gendwarfksyms/gendwarfksyms.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
extern int debug;
2323
extern int dump_dies;
2424
extern int dump_die_map;
25+
extern int dump_types;
26+
extern int symtypes;
2527

2628
/*
2729
* Output helpers
@@ -90,6 +92,11 @@ static inline unsigned int addr_hash(uintptr_t addr)
9092
return hash_ptr((const void *)addr);
9193
}
9294

95+
enum symbol_state {
96+
SYMBOL_UNPROCESSED,
97+
SYMBOL_MAPPED,
98+
};
99+
93100
struct symbol_addr {
94101
uint32_t section;
95102
Elf64_Addr address;
@@ -100,6 +107,8 @@ struct symbol {
100107
struct symbol_addr addr;
101108
struct hlist_node addr_hash;
102109
struct hlist_node name_hash;
110+
enum symbol_state state;
111+
uintptr_t die_addr;
103112
};
104113

105114
typedef void (*symbol_callback_t)(struct symbol *, void *arg);
@@ -154,17 +163,21 @@ static inline const char *die_state_name(enum die_state state)
154163

155164
struct die {
156165
enum die_state state;
166+
bool mapped;
157167
char *fqn;
158168
int tag;
159169
uintptr_t addr;
160170
struct list_head fragments;
161171
struct hlist_node hash;
162172
};
163173

174+
typedef void (*die_map_callback_t)(struct die *, void *arg);
175+
164176
int __die_map_get(uintptr_t addr, enum die_state state, struct die **res);
165177
struct die *die_map_get(Dwarf_Die *die, enum die_state state);
166178
void die_map_add_string(struct die *pd, const char *str);
167179
void die_map_add_linebreak(struct die *pd, int linebreak);
180+
void die_map_for_each(die_map_callback_t func, void *arg);
168181
void die_map_add_die(struct die *pd, struct die *child);
169182
void die_map_free(void);
170183

@@ -235,4 +248,10 @@ int process_die_container(struct state *state, struct die *cache,
235248

236249
void process_cu(Dwarf_Die *cudie);
237250

251+
/*
252+
* types.c
253+
*/
254+
255+
void generate_symtypes(FILE *file);
256+
238257
#endif /* __GENDWARFKSYMS_H */

scripts/gendwarfksyms/symbols.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ void symbol_read_exports(FILE *file)
9292
sym = xcalloc(1, sizeof(struct symbol));
9393
sym->name = name;
9494
sym->addr.section = SHN_UNDEF;
95+
sym->state = SYMBOL_UNPROCESSED;
9596

9697
hash_add(symbol_names, &sym->name_hash, hash_str(sym->name));
9798
++nsym;
@@ -107,7 +108,8 @@ static void get_symbol(struct symbol *sym, void *arg)
107108
{
108109
struct symbol **res = arg;
109110

110-
*res = sym;
111+
if (sym->state == SYMBOL_UNPROCESSED)
112+
*res = sym;
111113
}
112114

113115
struct symbol *symbol_get(const char *name)

0 commit comments

Comments
 (0)