File Index
Files and directories
Sign in
FILE

gendwarfksyms.h

File preview with syntax highlighting.

linux-6.19.14/scripts/gendwarfksyms/gendwarfksyms.h C
  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 */
~/ Read-only file preview.