Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 290 lines 7.2 kB view raw
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 */ 22extern int debug; 23extern int dump_dies; 24extern int dump_die_map; 25extern int dump_types; 26extern int dump_versions; 27extern int stable; 28extern 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 96static inline unsigned int addr_hash(uintptr_t addr) 97{ 98 return hash_ptr((const void *)addr); 99} 100 101enum symbol_state { 102 SYMBOL_UNPROCESSED, 103 SYMBOL_MAPPED, 104 SYMBOL_PROCESSED 105}; 106 107struct symbol_addr { 108 uint32_t section; 109 Elf64_Addr address; 110}; 111 112struct 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 123typedef void (*symbol_callback_t)(struct symbol *, void *arg); 124 125bool is_symbol_ptr(const char *name); 126int symbol_read_exports(FILE *file); 127void symbol_read_symtab(int fd); 128struct symbol *symbol_get(const char *name); 129void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr); 130void symbol_set_die(struct symbol *sym, Dwarf_Die *die); 131void symbol_set_crc(struct symbol *sym, unsigned long crc); 132void symbol_for_each(symbol_callback_t func, void *arg); 133void symbol_print_versions(void); 134void symbol_free(void); 135 136/* 137 * die.c 138 */ 139 140enum die_state { 141 DIE_INCOMPLETE, 142 DIE_FQN, 143 DIE_UNEXPANDED, 144 DIE_COMPLETE, 145 DIE_SYMBOL, 146 DIE_LAST = DIE_SYMBOL 147}; 148 149enum die_fragment_type { 150 FRAGMENT_EMPTY, 151 FRAGMENT_STRING, 152 FRAGMENT_LINEBREAK, 153 FRAGMENT_DIE 154}; 155 156struct 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 170static 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 183struct 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 193typedef void (*die_map_callback_t)(struct die *, void *arg); 194 195int __die_map_get(uintptr_t addr, enum die_state state, struct die **res); 196struct die *die_map_get(Dwarf_Die *die, enum die_state state); 197void die_map_add_string(struct die *pd, const char *str); 198void die_map_add_linebreak(struct die *pd, int linebreak); 199void die_map_for_each(die_map_callback_t func, void *arg); 200void die_map_add_die(struct die *pd, struct die *child); 201void 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. */ 210struct cache { 211 HASHTABLE_DECLARE(cache, 1 << CACHE_HASH_BITS); 212}; 213 214void cache_set(struct cache *cache, unsigned long key, int value); 215int cache_get(struct cache *cache, unsigned long key); 216void cache_init(struct cache *cache); 217void cache_free(struct cache *cache); 218 219static inline void cache_mark_expanded(struct cache *cache, void *addr) 220{ 221 cache_set(cache, (unsigned long)addr, 1); 222} 223 224static inline bool cache_was_expanded(struct cache *cache, void *addr) 225{ 226 return cache_get(cache, (unsigned long)addr) == 1; 227} 228 229/* 230 * dwarf.c 231 */ 232 233struct expansion_state { 234 bool expand; 235 const char *current_fqn; 236}; 237 238struct kabi_state { 239 int members; 240 Dwarf_Die placeholder; 241 const char *orig_name; 242}; 243 244struct state { 245 struct symbol *sym; 246 Dwarf_Die die; 247 248 /* List expansion */ 249 bool first_list_item; 250 251 /* Structure expansion */ 252 struct expansion_state expand; 253 struct cache expansion_cache; 254 255 /* Reserved or ignored members */ 256 struct kabi_state kabi; 257}; 258 259typedef int (*die_callback_t)(struct state *state, struct die *cache, 260 Dwarf_Die *die); 261typedef bool (*die_match_callback_t)(Dwarf_Die *die); 262bool match_all(Dwarf_Die *die); 263 264int process_die_container(struct state *state, struct die *cache, 265 Dwarf_Die *die, die_callback_t func, 266 die_match_callback_t match); 267 268void process_cu(Dwarf_Die *cudie); 269 270/* 271 * types.c 272 */ 273 274void generate_symtypes_and_versions(FILE *file); 275 276/* 277 * kabi.c 278 */ 279 280bool kabi_get_byte_size(const char *fqn, unsigned long *value); 281bool kabi_is_enumerator_ignored(const char *fqn, const char *field); 282bool kabi_get_enumerator_value(const char *fqn, const char *field, 283 unsigned long *value); 284bool kabi_is_declonly(const char *fqn); 285bool kabi_get_type_string(const char *type, const char **str); 286 287void kabi_read_rules(int fd); 288void kabi_free(void); 289 290#endif /* __GENDWARFKSYMS_H */