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