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_FQN,
143 	DIE_UNEXPANDED,
144 	DIE_COMPLETE,
145 	DIE_SYMBOL,
146 	DIE_LAST = DIE_SYMBOL
147 };
148 
149 enum die_fragment_type {
150 	FRAGMENT_EMPTY,
151 	FRAGMENT_STRING,
152 	FRAGMENT_LINEBREAK,
153 	FRAGMENT_DIE
154 };
155 
156 struct die_fragment {
157 	enum die_fragment_type type;
158 	union {
159 		char *str;
160 		int linebreak;
161 		uintptr_t addr;
162 	} data;
163 	struct list_head list;
164 };
165 
166 #define CASE_CONST_TO_STR(name) \
167 	case name:              \
168 		return #name;
169 
die_state_name(enum die_state state)170 static inline const char *die_state_name(enum die_state state)
171 {
172 	switch (state) {
173 	CASE_CONST_TO_STR(DIE_INCOMPLETE)
174 	CASE_CONST_TO_STR(DIE_FQN)
175 	CASE_CONST_TO_STR(DIE_UNEXPANDED)
176 	CASE_CONST_TO_STR(DIE_COMPLETE)
177 	CASE_CONST_TO_STR(DIE_SYMBOL)
178 	}
179 
180 	error("unexpected die_state: %d", state);
181 }
182 
183 struct die {
184 	enum die_state state;
185 	bool mapped;
186 	char *fqn;
187 	int tag;
188 	uintptr_t addr;
189 	struct list_head fragments;
190 	struct hlist_node hash;
191 };
192 
193 typedef void (*die_map_callback_t)(struct die *, void *arg);
194 
195 int __die_map_get(uintptr_t addr, enum die_state state, struct die **res);
196 struct die *die_map_get(Dwarf_Die *die, enum die_state state);
197 void die_map_add_string(struct die *pd, const char *str);
198 void die_map_add_linebreak(struct die *pd, int linebreak);
199 void die_map_for_each(die_map_callback_t func, void *arg);
200 void die_map_add_die(struct die *pd, struct die *child);
201 void die_map_free(void);
202 
203 /*
204  * cache.c
205  */
206 
207 #define CACHE_HASH_BITS 10
208 
209 /* A cache for addresses we've already seen. */
210 struct cache {
211 	HASHTABLE_DECLARE(cache, 1 << CACHE_HASH_BITS);
212 };
213 
214 void cache_set(struct cache *cache, unsigned long key, int value);
215 int cache_get(struct cache *cache, unsigned long key);
216 void cache_init(struct cache *cache);
217 void cache_free(struct cache *cache);
218 
__cache_mark_expanded(struct cache * cache,uintptr_t addr)219 static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr)
220 {
221 	cache_set(cache, addr, 1);
222 }
223 
__cache_was_expanded(struct cache * cache,uintptr_t addr)224 static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr)
225 {
226 	return cache_get(cache, addr) == 1;
227 }
228 
cache_mark_expanded(struct cache * cache,void * addr)229 static inline void cache_mark_expanded(struct cache *cache, void *addr)
230 {
231 	__cache_mark_expanded(cache, (uintptr_t)addr);
232 }
233 
cache_was_expanded(struct cache * cache,void * addr)234 static inline bool cache_was_expanded(struct cache *cache, void *addr)
235 {
236 	return __cache_was_expanded(cache, (uintptr_t)addr);
237 }
238 
239 /*
240  * dwarf.c
241  */
242 
243 struct expansion_state {
244 	bool expand;
245 	const char *current_fqn;
246 };
247 
248 struct kabi_state {
249 	int members;
250 	Dwarf_Die placeholder;
251 	const char *orig_name;
252 };
253 
254 struct state {
255 	struct symbol *sym;
256 	Dwarf_Die die;
257 
258 	/* List expansion */
259 	bool first_list_item;
260 
261 	/* Structure expansion */
262 	struct expansion_state expand;
263 	struct cache expansion_cache;
264 
265 	/* Reserved or ignored members */
266 	struct kabi_state kabi;
267 };
268 
269 typedef int (*die_callback_t)(struct state *state, struct die *cache,
270 			      Dwarf_Die *die);
271 typedef bool (*die_match_callback_t)(Dwarf_Die *die);
272 bool match_all(Dwarf_Die *die);
273 
274 int process_die_container(struct state *state, struct die *cache,
275 			  Dwarf_Die *die, die_callback_t func,
276 			  die_match_callback_t match);
277 
278 void process_cu(Dwarf_Die *cudie);
279 
280 /*
281  * types.c
282  */
283 
284 void generate_symtypes_and_versions(FILE *file);
285 
286 /*
287  * kabi.c
288  */
289 
290 bool kabi_is_enumerator_ignored(const char *fqn, const char *field);
291 bool kabi_get_enumerator_value(const char *fqn, const char *field,
292 			       unsigned long *value);
293 bool kabi_is_declonly(const char *fqn);
294 
295 void kabi_read_rules(int fd);
296 void kabi_free(void);
297 
298 #endif /* __GENDWARFKSYMS_H */
299