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