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 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 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 219 static inline void __cache_mark_expanded(struct cache *cache, uintptr_t addr) 220 { 221 cache_set(cache, addr, 1); 222 } 223 224 static inline bool __cache_was_expanded(struct cache *cache, uintptr_t addr) 225 { 226 return cache_get(cache, addr) == 1; 227 } 228 229 static inline void cache_mark_expanded(struct cache *cache, void *addr) 230 { 231 __cache_mark_expanded(cache, (uintptr_t)addr); 232 } 233 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