1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Copyright (C) 2024 Google LLC
4 */
5
6 #include <dwarf.h>
7 #include <elfutils/libdw.h>
8 #include <elfutils/libdwfl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11
12 #include <hash.h>
13 #include <hashtable.h>
14 #include <xalloc.h>
15
16 #ifndef __GENDWARFKSYMS_H
17 #define __GENDWARFKSYMS_H
18
19 /*
20 * Options -- in gendwarfksyms.c
21 */
22 extern int debug;
23 extern int dump_dies;
24 extern int dump_die_map;
25 extern int dump_types;
26 extern int dump_versions;
27 extern int stable;
28 extern int symtypes;
29
30 /*
31 * Output helpers
32 */
33 #define __PREFIX "gendwarfksyms: "
34 #define __println(prefix, format, ...) \
35 fprintf(stderr, prefix __PREFIX "%s: " format "\n", __func__, \
36 ##__VA_ARGS__)
37
38 #define debug(format, ...) \
39 do { \
40 if (debug) \
41 __println("", format, ##__VA_ARGS__); \
42 } while (0)
43
44 #define warn(format, ...) __println("warning: ", format, ##__VA_ARGS__)
45 #define error(format, ...) \
46 do { \
47 __println("error: ", format, ##__VA_ARGS__); \
48 exit(1); \
49 } while (0)
50
51 #define __die_debug(color, format, ...) \
52 do { \
53 if (dump_dies && dump_die_map) \
54 fprintf(stderr, \
55 "\033[" #color "m<" format ">\033[39m", \
56 __VA_ARGS__); \
57 } while (0)
58
59 #define die_debug_r(format, ...) __die_debug(91, format, __VA_ARGS__)
60 #define die_debug_g(format, ...) __die_debug(92, format, __VA_ARGS__)
61 #define die_debug_b(format, ...) __die_debug(94, format, __VA_ARGS__)
62
63 /*
64 * Error handling helpers
65 */
66 #define __check(expr, test) \
67 ({ \
68 int __res = expr; \
69 if (test) \
70 error("`%s` failed: %d", #expr, __res); \
71 __res; \
72 })
73
74 /* Error == non-zero values */
75 #define check(expr) __check(expr, __res)
76 /* Error == negative values */
77 #define checkp(expr) __check(expr, __res < 0)
78
79 /* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */
80 #define DW_TAG_enumerator_type DW_TAG_enumerator
81 #define DW_TAG_formal_parameter_type DW_TAG_formal_parameter
82 #define DW_TAG_member_type DW_TAG_member
83 #define DW_TAG_template_type_parameter_type DW_TAG_template_type_parameter
84 #define DW_TAG_typedef_type DW_TAG_typedef
85 #define DW_TAG_variant_part_type DW_TAG_variant_part
86 #define DW_TAG_variant_type DW_TAG_variant
87
88 /*
89 * symbols.c
90 */
91
92 /* See symbols.c:is_symbol_ptr */
93 #define SYMBOL_PTR_PREFIX "__gendwarfksyms_ptr_"
94 #define SYMBOL_PTR_PREFIX_LEN (sizeof(SYMBOL_PTR_PREFIX) - 1)
95
addr_hash(uintptr_t addr)96 static inline unsigned int addr_hash(uintptr_t addr)
97 {
98 return hash_ptr((const void *)addr);
99 }
100
101 enum symbol_state {
102 SYMBOL_UNPROCESSED,
103 SYMBOL_MAPPED,
104 SYMBOL_PROCESSED
105 };
106
107 struct symbol_addr {
108 uint32_t section;
109 Elf64_Addr address;
110 };
111
112 struct symbol {
113 const char *name;
114 struct symbol_addr addr;
115 struct hlist_node addr_hash;
116 struct hlist_node name_hash;
117 enum symbol_state state;
118 uintptr_t die_addr;
119 uintptr_t ptr_die_addr;
120 unsigned long crc;
121 };
122
123 typedef void (*symbol_callback_t)(struct symbol *, void *arg);
124
125 bool is_symbol_ptr(const char *name);
126 void symbol_read_exports(FILE *file);
127 void symbol_read_symtab(int fd);
128 struct symbol *symbol_get(const char *name);
129 void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr);
130 void symbol_set_die(struct symbol *sym, Dwarf_Die *die);
131 void symbol_set_crc(struct symbol *sym, unsigned long crc);
132 void symbol_for_each(symbol_callback_t func, void *arg);
133 void symbol_print_versions(void);
134 void symbol_free(void);
135
136 /*
137 * die.c
138 */
139
140 enum die_state {
141 DIE_INCOMPLETE,
142 DIE_UNEXPANDED,
143 DIE_COMPLETE,
144 DIE_SYMBOL,
145 DIE_LAST = DIE_SYMBOL
146 };
147
148 enum die_fragment_type {
149 FRAGMENT_EMPTY,
150 FRAGMENT_STRING,
151 FRAGMENT_LINEBREAK,
152 FRAGMENT_DIE
153 };
154
155 struct die_fragment {
156 enum die_fragment_type type;
157 union {
158 char *str;
159 int linebreak;
160 uintptr_t addr;
161 } data;
162 struct list_head list;
163 };
164
165 #define CASE_CONST_TO_STR(name) \
166 case name: \
167 return #name;
168
die_state_name(enum die_state state)169 static inline const char *die_state_name(enum die_state state)
170 {
171 switch (state) {
172 CASE_CONST_TO_STR(DIE_INCOMPLETE)
173 CASE_CONST_TO_STR(DIE_UNEXPANDED)
174 CASE_CONST_TO_STR(DIE_COMPLETE)
175 CASE_CONST_TO_STR(DIE_SYMBOL)
176 }
177
178 error("unexpected die_state: %d", state);
179 }
180
181 struct die {
182 enum die_state state;
183 bool mapped;
184 char *fqn;
185 int tag;
186 uintptr_t addr;
187 struct list_head fragments;
188 struct hlist_node hash;
189 };
190
191 typedef void (*die_map_callback_t)(struct die *, void *arg);
192
193 int __die_map_get(uintptr_t addr, enum die_state state, struct die **res);
194 struct die *die_map_get(Dwarf_Die *die, enum die_state state);
195 void die_map_add_string(struct die *pd, const char *str);
196 void die_map_add_linebreak(struct die *pd, int linebreak);
197 void die_map_for_each(die_map_callback_t func, void *arg);
198 void die_map_add_die(struct die *pd, struct die *child);
199 void die_map_free(void);
200
201 /*
202 * cache.c
203 */
204
205 #define CACHE_HASH_BITS 10
206
207 /* A cache for addresses we've already seen. */
208 struct cache {
209 HASHTABLE_DECLARE(cache, 1 << CACHE_HASH_BITS);
210 };
211
212 void cache_set(struct cache *cache, unsigned long key, int value);
213 int cache_get(struct cache *cache, unsigned long key);
214 void cache_init(struct cache *cache);
215 void cache_free(struct cache *cache);
216
__cache_mark_expanded(struct cache * cache,uintptr_t addr)217 static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr)
218 {
219 cache_set(cache, addr, 1);
220 }
221
__cache_was_expanded(struct cache * cache,uintptr_t addr)222 static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr)
223 {
224 return cache_get(cache, addr) == 1;
225 }
226
cache_mark_expanded(struct cache * cache,void * addr)227 static inline void cache_mark_expanded(struct cache *cache, void *addr)
228 {
229 __cache_mark_expanded(cache, (uintptr_t)addr);
230 }
231
cache_was_expanded(struct cache * cache,void * addr)232 static inline bool cache_was_expanded(struct cache *cache, void *addr)
233 {
234 return __cache_was_expanded(cache, (uintptr_t)addr);
235 }
236
237 /*
238 * dwarf.c
239 */
240
241 struct expansion_state {
242 bool expand;
243 const char *current_fqn;
244 };
245
246 struct kabi_state {
247 int members;
248 Dwarf_Die placeholder;
249 const char *orig_name;
250 };
251
252 struct state {
253 struct symbol *sym;
254 Dwarf_Die die;
255
256 /* List expansion */
257 bool first_list_item;
258
259 /* Structure expansion */
260 struct expansion_state expand;
261 struct cache expansion_cache;
262
263 /* Reserved or ignored members */
264 struct kabi_state kabi;
265 };
266
267 typedef int (*die_callback_t)(struct state *state, struct die *cache,
268 Dwarf_Die *die);
269 typedef bool (*die_match_callback_t)(Dwarf_Die *die);
270 bool match_all(Dwarf_Die *die);
271
272 int process_die_container(struct state *state, struct die *cache,
273 Dwarf_Die *die, die_callback_t func,
274 die_match_callback_t match);
275
276 void process_cu(Dwarf_Die *cudie);
277
278 /*
279 * types.c
280 */
281
282 void generate_symtypes_and_versions(FILE *file);
283
284 /*
285 * kabi.c
286 */
287
288 bool kabi_is_enumerator_ignored(const char *fqn, const char *field);
289 bool kabi_get_enumerator_value(const char *fqn, const char *field,
290 unsigned long *value);
291 bool kabi_is_declonly(const char *fqn);
292
293 void kabi_read_rules(int fd);
294 void kabi_free(void);
295
296 #endif /* __GENDWARFKSYMS_H */
297