Skip to content

Commit 6a70751

Browse files
committed
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>
1 parent 46dc55b commit 6a70751

File tree

7 files changed

+517
-10
lines changed

7 files changed

+517
-10
lines changed

scripts/gendwarfksyms/Makefile

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

910
HOST_EXTRACFLAGS := -I $(srctree)/tools/include
1011
HOSTLDLIBS_gendwarfksyms := -ldw -lelf

scripts/gendwarfksyms/die.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ static void reset_die(struct die *cd)
8585
cd->list = NULL;
8686
}
8787

88+
int die_map_for_each(die_map_callback_t func, void *arg)
89+
{
90+
struct die *cd;
91+
struct hlist_node *tmp;
92+
int i;
93+
94+
hash_for_each_safe(die_map, i, tmp, cd, hash) {
95+
check(func(cd, arg));
96+
}
97+
98+
return 0;
99+
}
100+
88101
void die_map_free(void)
89102
{
90103
struct hlist_node *tmp;

scripts/gendwarfksyms/dwarf.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ static bool is_export_symbol(struct state *state, Dwarf_Die *die)
6060
if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin))
6161
source = &origin;
6262

63-
state->sym = symbol_get(get_name(die));
63+
state->sym = symbol_get_unprocessed(get_name(die));
6464

6565
/* Look up using the origin name if there are no matches. */
6666
if (!state->sym && source != die)
67-
state->sym = symbol_get(get_name(source));
67+
state->sym = symbol_get_unprocessed(get_name(source));
6868

6969
state->die = *source;
7070
return !!state->sym;
@@ -384,6 +384,7 @@ static int process_subroutine_type(struct state *state, struct die *cache,
384384
return check(__process_subroutine_type(state, cache, die,
385385
"subroutine_type"));
386386
}
387+
387388
static int process_variant_type(struct state *state, struct die *cache,
388389
Dwarf_Die *die)
389390
{
@@ -695,14 +696,16 @@ static int process_type(struct state *state, struct die *parent, Dwarf_Die *die)
695696
static int process_subprogram(struct state *state, Dwarf_Die *die)
696697
{
697698
check(__process_subroutine_type(state, NULL, die, "subprogram"));
698-
return check(process(state, NULL, ";\n"));
699+
state->sym->state = MAPPED;
700+
return 0;
699701
}
700702

701703
static int process_variable(struct state *state, Dwarf_Die *die)
702704
{
703705
check(process(state, NULL, "variable "));
704706
check(process_type_attr(state, NULL, die));
705-
return check(process(state, NULL, ";\n"));
707+
state->sym->state = MAPPED;
708+
return 0;
706709
}
707710

708711
static int process_symbol_ptr(struct state *state, Dwarf_Die *die)
@@ -757,6 +760,9 @@ static int process_exported_symbols(struct state *state, struct die *cache,
757760
else
758761
check(process_variable(state, &state->die));
759762

763+
if (dump_dies)
764+
fputs("\n", stderr);
765+
760766
cache_clear_expanded(&state->expansion_cache);
761767
return 0;
762768
default:

scripts/gendwarfksyms/gendwarfksyms.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ bool debug;
2020
bool dump_dies;
2121
/* Print out inline debugging information about die_map changes */
2222
bool dump_die_map;
23+
/* Print out type_map contents */
24+
bool dump_types;
25+
/* Produce a symtypes file */
26+
bool symtypes;
27+
static const char *symtypes_file;
2328

2429
static const struct {
2530
const char *arg;
@@ -29,6 +34,8 @@ static const struct {
2934
{ "--debug", &debug, NULL },
3035
{ "--dump-dies", &dump_dies, NULL },
3136
{ "--dump-die-map", &dump_die_map, NULL },
37+
{ "--dump-types", &dump_types, NULL },
38+
{ "--symtypes", &symtypes, &symtypes_file },
3239
};
3340

3441
static int usage(void)
@@ -79,6 +86,7 @@ static int process_modules(Dwfl_Module *mod, void **userdata, const char *name,
7986
Dwarf_Die cudie;
8087
Dwarf_CU *cu = NULL;
8188
Dwarf *dbg;
89+
FILE *symfile = arg;
8290
int res;
8391

8492
debug("%s", name);
@@ -100,6 +108,10 @@ static int process_modules(Dwfl_Module *mod, void **userdata, const char *name,
100108
check(process_module(mod, dbg, &cudie));
101109
} while (cu);
102110

111+
/*
112+
* Use die_map to expand type strings and write them to `symfile`.
113+
*/
114+
check(generate_symtypes(symfile));
103115
die_map_free();
104116

105117
return DWARF_CB_OK;
@@ -112,6 +124,7 @@ static const Dwfl_Callbacks callbacks = {
112124

113125
int main(int argc, const char **argv)
114126
{
127+
FILE *symfile = NULL;
115128
unsigned int n;
116129

117130
if (parse_options(argc, argv) < 0)
@@ -122,6 +135,16 @@ int main(int argc, const char **argv)
122135

123136
check(symbol_read_exports(stdin));
124137

138+
if (symtypes_file) {
139+
symfile = fopen(symtypes_file, "w+");
140+
141+
if (!symfile) {
142+
error("fopen failed for '%s': %s", symtypes_file,
143+
strerror(errno));
144+
return -1;
145+
}
146+
}
147+
125148
for (n = 0; n < object_count; n++) {
126149
Dwfl *dwfl;
127150
int fd;
@@ -151,7 +174,7 @@ int main(int argc, const char **argv)
151174

152175
dwfl_report_end(dwfl, NULL, NULL);
153176

154-
if (dwfl_getmodules(dwfl, &process_modules, NULL, 0)) {
177+
if (dwfl_getmodules(dwfl, &process_modules, symfile, 0)) {
155178
error("dwfl_getmodules failed for '%s'",
156179
object_files[n]);
157180
return -1;
@@ -161,5 +184,8 @@ int main(int argc, const char **argv)
161184
close(fd);
162185
}
163186

187+
if (symfile)
188+
fclose(symfile);
189+
164190
return 0;
165191
}

scripts/gendwarfksyms/gendwarfksyms.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
extern bool debug;
2323
extern bool dump_dies;
2424
extern bool dump_die_map;
25+
extern bool dump_types;
26+
extern bool symtypes;
2527

2628
#define MAX_INPUT_FILES 128
2729

@@ -89,6 +91,12 @@ extern bool dump_die_map;
8991
#define SYMBOL_PTR_PREFIX "__gendwarfksyms_ptr_"
9092
#define SYMBOL_PTR_PREFIX_LEN (sizeof(SYMBOL_PTR_PREFIX) - 1)
9193

94+
/* See dwarf.c:is_declaration */
95+
#define SYMBOL_DECLONLY_PREFIX "__gendwarfksyms_declonly_"
96+
#define SYMBOL_DECLONLY_PREFIX_LEN (sizeof(SYMBOL_DECLONLY_PREFIX) - 1)
97+
98+
enum symbol_state { UNPROCESSED, MAPPED };
99+
92100
struct symbol_addr {
93101
uint32_t section;
94102
Elf64_Addr address;
@@ -109,12 +117,14 @@ struct symbol {
109117
struct symbol_addr addr;
110118
struct hlist_node addr_hash;
111119
struct hlist_node name_hash;
120+
enum symbol_state state;
121+
uintptr_t die_addr;
112122
};
113123

114124
extern bool is_symbol_ptr(const char *name);
115125
extern int symbol_read_exports(FILE *file);
116126
extern int symbol_read_symtab(int fd);
117-
extern struct symbol *symbol_get(const char *name);
127+
extern struct symbol *symbol_get_unprocessed(const char *name);
118128

119129
/*
120130
* die.c
@@ -157,12 +167,15 @@ struct die {
157167
struct hlist_node hash;
158168
};
159169

170+
typedef int (*die_map_callback_t)(struct die *, void *arg);
171+
160172
extern int __die_map_get(uintptr_t addr, enum die_state state,
161173
struct die **res);
162174
extern int die_map_get(Dwarf_Die *die, enum die_state state, struct die **res);
163175
extern int die_map_add_string(struct die *pd, const char *str);
164176
extern int die_map_add_linebreak(struct die *pd, int linebreak);
165177
extern int die_map_add_die(struct die *pd, struct die *child);
178+
extern int die_map_for_each(die_map_callback_t func, void *arg);
166179
extern void die_map_free(void);
167180

168181
/*
@@ -222,4 +235,10 @@ extern int process_die_container(struct state *state, struct die *cache,
222235

223236
extern int process_module(Dwfl_Module *mod, Dwarf *dbg, Dwarf_Die *cudie);
224237

238+
/*
239+
* types.c
240+
*/
241+
242+
extern int generate_symtypes(FILE *file);
243+
225244
#endif /* __GENDWARFKSYMS_H */

scripts/gendwarfksyms/symbols.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ int symbol_read_exports(FILE *file)
117117

118118
sym->name = name;
119119
sym->addr.section = SHN_UNDEF;
120+
sym->state = UNPROCESSED;
120121
name = NULL;
121122

122123
hash_add(symbol_names, &sym->name_hash, name_hash(sym->name));
@@ -132,19 +133,21 @@ int symbol_read_exports(FILE *file)
132133
return 0;
133134
}
134135

135-
static int get_symbol(struct symbol *sym, void *arg)
136+
static int get_unprocessed(struct symbol *sym, void *arg)
136137
{
137138
struct symbol **res = arg;
138139

139-
*res = sym;
140+
if (sym->state == UNPROCESSED)
141+
*res = sym;
142+
140143
return 0;
141144
}
142145

143-
struct symbol *symbol_get(const char *name)
146+
struct symbol *symbol_get_unprocessed(const char *name)
144147
{
145148
struct symbol *sym = NULL;
146149

147-
for_each(name, false, get_symbol, &sym);
150+
for_each(name, false, get_unprocessed, &sym);
148151
return sym;
149152
}
150153

0 commit comments

Comments
 (0)