xref: /linux/scripts/gendwarfksyms/symbols.c (revision a752782a2843323d2c04ee6ab79531d027072e88)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2024 Google LLC
4  */
5 
6 #include "gendwarfksyms.h"
7 
8 #define SYMBOL_HASH_BITS 12
9 
10 /* struct symbol_addr -> struct symbol */
11 static HASHTABLE_DEFINE(symbol_addrs, 1 << SYMBOL_HASH_BITS);
12 /* name -> struct symbol */
13 static HASHTABLE_DEFINE(symbol_names, 1 << SYMBOL_HASH_BITS);
14 
symbol_addr_hash(const struct symbol_addr * addr)15 static inline unsigned int symbol_addr_hash(const struct symbol_addr *addr)
16 {
17 	return hash_32(addr->section ^ addr_hash(addr->address));
18 }
19 
__for_each_addr(struct symbol * sym,symbol_callback_t func,void * data)20 static unsigned int __for_each_addr(struct symbol *sym, symbol_callback_t func,
21 				    void *data)
22 {
23 	struct hlist_node *tmp;
24 	struct symbol *match = NULL;
25 	unsigned int processed = 0;
26 
27 	hash_for_each_possible_safe(symbol_addrs, match, tmp, addr_hash,
28 				    symbol_addr_hash(&sym->addr)) {
29 		if (match == sym)
30 			continue; /* Already processed */
31 
32 		if (match->addr.section == sym->addr.section &&
33 		    match->addr.address == sym->addr.address) {
34 			func(match, data);
35 			++processed;
36 		}
37 	}
38 
39 	return processed;
40 }
41 
42 /*
43  * For symbols without debugging information (e.g. symbols defined in other
44  * TUs), we also match __gendwarfksyms_ptr_<symbol_name> symbols, which the
45  * kernel uses to ensure type information is present in the TU that exports
46  * the symbol. A __gendwarfksyms_ptr pointer must have the same type as the
47  * exported symbol, e.g.:
48  *
49  *   typeof(symname) *__gendwarf_ptr_symname = &symname;
50  */
is_symbol_ptr(const char * name)51 bool is_symbol_ptr(const char *name)
52 {
53 	return name && !strncmp(name, SYMBOL_PTR_PREFIX, SYMBOL_PTR_PREFIX_LEN);
54 }
55 
for_each(const char * name,symbol_callback_t func,void * data)56 static unsigned int for_each(const char *name, symbol_callback_t func,
57 			     void *data)
58 {
59 	struct hlist_node *tmp;
60 	struct symbol *match;
61 
62 	if (!name || !*name)
63 		return 0;
64 	if (is_symbol_ptr(name))
65 		name += SYMBOL_PTR_PREFIX_LEN;
66 
67 	hash_for_each_possible_safe(symbol_names, match, tmp, name_hash,
68 				    hash_str(name)) {
69 		if (strcmp(match->name, name))
70 			continue;
71 
72 		/* Call func for the match, and all address matches */
73 		if (func)
74 			func(match, data);
75 
76 		if (match->addr.section != SHN_UNDEF)
77 			return __for_each_addr(match, func, data) + 1;
78 
79 		return 1;
80 	}
81 
82 	return 0;
83 }
84 
set_crc(struct symbol * sym,void * data)85 static void set_crc(struct symbol *sym, void *data)
86 {
87 	unsigned long *crc = data;
88 
89 	if (sym->state == SYMBOL_PROCESSED && sym->crc != *crc)
90 		warn("overriding version for symbol %s (crc %lx vs. %lx)",
91 		     sym->name, sym->crc, *crc);
92 
93 	sym->state = SYMBOL_PROCESSED;
94 	sym->crc = *crc;
95 }
96 
symbol_set_crc(struct symbol * sym,unsigned long crc)97 void symbol_set_crc(struct symbol *sym, unsigned long crc)
98 {
99 	if (for_each(sym->name, set_crc, &crc) == 0)
100 		error("no matching symbols: '%s'", sym->name);
101 }
102 
set_ptr(struct symbol * sym,void * data)103 static void set_ptr(struct symbol *sym, void *data)
104 {
105 	sym->ptr_die_addr = (uintptr_t)((Dwarf_Die *)data)->addr;
106 }
107 
symbol_set_ptr(struct symbol * sym,Dwarf_Die * ptr)108 void symbol_set_ptr(struct symbol *sym, Dwarf_Die *ptr)
109 {
110 	if (for_each(sym->name, set_ptr, ptr) == 0)
111 		error("no matching symbols: '%s'", sym->name);
112 }
113 
set_die(struct symbol * sym,void * data)114 static void set_die(struct symbol *sym, void *data)
115 {
116 	sym->die_addr = (uintptr_t)((Dwarf_Die *)data)->addr;
117 	sym->state = SYMBOL_MAPPED;
118 }
119 
symbol_set_die(struct symbol * sym,Dwarf_Die * die)120 void symbol_set_die(struct symbol *sym, Dwarf_Die *die)
121 {
122 	if (for_each(sym->name, set_die, die) == 0)
123 		error("no matching symbols: '%s'", sym->name);
124 }
125 
is_exported(const char * name)126 static bool is_exported(const char *name)
127 {
128 	return for_each(name, NULL, NULL) > 0;
129 }
130 
symbol_read_exports(FILE * file)131 int symbol_read_exports(FILE *file)
132 {
133 	struct symbol *sym;
134 	char *line = NULL;
135 	char *name = NULL;
136 	size_t size = 0;
137 	int nsym = 0;
138 
139 	while (getline(&line, &size, file) > 0) {
140 		if (sscanf(line, "%ms\n", &name) != 1)
141 			error("malformed input line: %s", line);
142 
143 		if (is_exported(name)) {
144 			/* Ignore duplicates */
145 			free(name);
146 			continue;
147 		}
148 
149 		sym = xcalloc(1, sizeof(*sym));
150 		sym->name = name;
151 		sym->addr.section = SHN_UNDEF;
152 		sym->state = SYMBOL_UNPROCESSED;
153 
154 		hash_add(symbol_names, &sym->name_hash, hash_str(sym->name));
155 		++nsym;
156 
157 		debug("%s", sym->name);
158 	}
159 
160 	free(line);
161 	debug("%d exported symbols", nsym);
162 
163 	return nsym;
164 }
165 
get_symbol(struct symbol * sym,void * arg)166 static void get_symbol(struct symbol *sym, void *arg)
167 {
168 	struct symbol **res = arg;
169 
170 	if (sym->state == SYMBOL_UNPROCESSED)
171 		*res = sym;
172 }
173 
symbol_get(const char * name)174 struct symbol *symbol_get(const char *name)
175 {
176 	struct symbol *sym = NULL;
177 
178 	for_each(name, get_symbol, &sym);
179 	return sym;
180 }
181 
symbol_for_each(symbol_callback_t func,void * arg)182 void symbol_for_each(symbol_callback_t func, void *arg)
183 {
184 	struct hlist_node *tmp;
185 	struct symbol *sym;
186 
187 	hash_for_each_safe(symbol_names, sym, tmp, name_hash) {
188 		func(sym, arg);
189 	}
190 }
191 
192 typedef void (*elf_symbol_callback_t)(const char *name, GElf_Sym *sym,
193 				      Elf32_Word xndx, void *arg);
194 
elf_for_each_global(int fd,elf_symbol_callback_t func,void * arg)195 static void elf_for_each_global(int fd, elf_symbol_callback_t func, void *arg)
196 {
197 	size_t sym_size;
198 	GElf_Shdr shdr_mem;
199 	GElf_Shdr *shdr;
200 	Elf_Data *xndx_data = NULL;
201 	Elf_Scn *scn;
202 	Elf *elf;
203 
204 	if (elf_version(EV_CURRENT) != EV_CURRENT)
205 		error("elf_version failed: %s", elf_errmsg(-1));
206 
207 	elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
208 	if (!elf)
209 		error("elf_begin failed: %s", elf_errmsg(-1));
210 
211 	scn = elf_nextscn(elf, NULL);
212 
213 	while (scn) {
214 		shdr = gelf_getshdr(scn, &shdr_mem);
215 		if (!shdr)
216 			error("gelf_getshdr failed: %s", elf_errmsg(-1));
217 
218 		if (shdr->sh_type == SHT_SYMTAB_SHNDX) {
219 			xndx_data = elf_getdata(scn, NULL);
220 			if (!xndx_data)
221 				error("elf_getdata failed: %s", elf_errmsg(-1));
222 			break;
223 		}
224 
225 		scn = elf_nextscn(elf, scn);
226 	}
227 
228 	sym_size = gelf_fsize(elf, ELF_T_SYM, 1, EV_CURRENT);
229 	scn = elf_nextscn(elf, NULL);
230 
231 	while (scn) {
232 		shdr = gelf_getshdr(scn, &shdr_mem);
233 		if (!shdr)
234 			error("gelf_getshdr failed: %s", elf_errmsg(-1));
235 
236 		if (shdr->sh_type == SHT_SYMTAB) {
237 			unsigned int nsyms;
238 			unsigned int n;
239 			Elf_Data *data = elf_getdata(scn, NULL);
240 
241 			if (!data)
242 				error("elf_getdata failed: %s", elf_errmsg(-1));
243 
244 			if (shdr->sh_entsize != sym_size)
245 				error("expected sh_entsize (%lu) to be %zu",
246 				      shdr->sh_entsize, sym_size);
247 
248 			nsyms = shdr->sh_size / shdr->sh_entsize;
249 
250 			for (n = 1; n < nsyms; ++n) {
251 				const char *name = NULL;
252 				Elf32_Word xndx = 0;
253 				GElf_Sym sym_mem;
254 				GElf_Sym *sym;
255 
256 				sym = gelf_getsymshndx(data, xndx_data, n,
257 						       &sym_mem, &xndx);
258 				if (!sym)
259 					error("gelf_getsymshndx failed: %s",
260 					      elf_errmsg(-1));
261 
262 				if (GELF_ST_BIND(sym->st_info) == STB_LOCAL)
263 					continue;
264 
265 				if (sym->st_shndx != SHN_XINDEX)
266 					xndx = sym->st_shndx;
267 
268 				name = elf_strptr(elf, shdr->sh_link,
269 						  sym->st_name);
270 				if (!name)
271 					error("elf_strptr failed: %s",
272 					      elf_errmsg(-1));
273 
274 				/* Skip empty symbol names */
275 				if (*name)
276 					func(name, sym, xndx, arg);
277 			}
278 		}
279 
280 		scn = elf_nextscn(elf, scn);
281 	}
282 
283 	check(elf_end(elf));
284 }
285 
set_symbol_addr(struct symbol * sym,void * arg)286 static void set_symbol_addr(struct symbol *sym, void *arg)
287 {
288 	struct symbol_addr *addr = arg;
289 
290 	if (sym->addr.section == SHN_UNDEF) {
291 		sym->addr = *addr;
292 		hash_add(symbol_addrs, &sym->addr_hash,
293 			 symbol_addr_hash(&sym->addr));
294 
295 		debug("%s -> { %u, %lx }", sym->name, sym->addr.section,
296 		      sym->addr.address);
297 	} else if (sym->addr.section != addr->section ||
298 		   sym->addr.address != addr->address) {
299 		warn("multiple addresses for symbol %s?", sym->name);
300 	}
301 }
302 
elf_set_symbol_addr(const char * name,GElf_Sym * sym,Elf32_Word xndx,void * arg)303 static void elf_set_symbol_addr(const char *name, GElf_Sym *sym,
304 				Elf32_Word xndx, void *arg)
305 {
306 	struct symbol_addr addr = { .section = xndx, .address = sym->st_value };
307 
308 	/* Set addresses for exported symbols */
309 	if (addr.section != SHN_UNDEF)
310 		for_each(name, set_symbol_addr, &addr);
311 }
312 
symbol_read_symtab(int fd)313 void symbol_read_symtab(int fd)
314 {
315 	elf_for_each_global(fd, elf_set_symbol_addr, NULL);
316 }
317 
symbol_print_versions(void)318 void symbol_print_versions(void)
319 {
320 	struct hlist_node *tmp;
321 	struct symbol *sym;
322 
323 	hash_for_each_safe(symbol_names, sym, tmp, name_hash) {
324 		if (sym->state != SYMBOL_PROCESSED)
325 			warn("no information for symbol %s", sym->name);
326 
327 		printf("#SYMVER %s 0x%08lx\n", sym->name, sym->crc);
328 	}
329 }
330 
symbol_free(void)331 void symbol_free(void)
332 {
333 	struct hlist_node *tmp;
334 	struct symbol *sym;
335 
336 	hash_for_each_safe(symbol_names, sym, tmp, name_hash) {
337 		free((void *)sym->name);
338 		free(sym);
339 	}
340 
341 	hash_init(symbol_addrs);
342 	hash_init(symbol_names);
343 }
344