xref: /linux/scripts/gendwarfksyms/types.c (revision 08215f5486ec4d7c39cf14987ffb133e1e1f6c10)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2024 Google LLC
4  */
5 
6 #define _GNU_SOURCE
7 #include <inttypes.h>
8 #include <stdio.h>
9 #include <zlib.h>
10 
11 #include "gendwarfksyms.h"
12 
13 static struct cache expansion_cache;
14 
15 /*
16  * A simple linked list of shared or owned strings to avoid copying strings
17  * around when not necessary.
18  */
19 struct type_list_entry {
20 	const char *str;
21 	void *owned;
22 	struct list_head list;
23 };
24 
type_list_free(struct list_head * list)25 static void type_list_free(struct list_head *list)
26 {
27 	struct type_list_entry *entry;
28 	struct type_list_entry *tmp;
29 
30 	list_for_each_entry_safe(entry, tmp, list, list) {
31 		if (entry->owned)
32 			free(entry->owned);
33 		free(entry);
34 	}
35 
36 	INIT_LIST_HEAD(list);
37 }
38 
type_list_append(struct list_head * list,const char * s,void * owned)39 static int type_list_append(struct list_head *list, const char *s, void *owned)
40 {
41 	struct type_list_entry *entry;
42 
43 	if (!s)
44 		return 0;
45 
46 	entry = xmalloc(sizeof(struct type_list_entry));
47 	entry->str = s;
48 	entry->owned = owned;
49 	list_add_tail(&entry->list, list);
50 
51 	return strlen(entry->str);
52 }
53 
type_list_write(struct list_head * list,FILE * file)54 static void type_list_write(struct list_head *list, FILE *file)
55 {
56 	struct type_list_entry *entry;
57 
58 	list_for_each_entry(entry, list, list) {
59 		if (entry->str)
60 			checkp(fputs(entry->str, file));
61 	}
62 }
63 
64 /*
65  * An expanded type string in symtypes format.
66  */
67 struct type_expansion {
68 	char *name;
69 	size_t len;
70 	struct list_head expanded;
71 	struct hlist_node hash;
72 };
73 
type_expansion_init(struct type_expansion * type)74 static void type_expansion_init(struct type_expansion *type)
75 {
76 	type->name = NULL;
77 	type->len = 0;
78 	INIT_LIST_HEAD(&type->expanded);
79 }
80 
type_expansion_free(struct type_expansion * type)81 static inline void type_expansion_free(struct type_expansion *type)
82 {
83 	free(type->name);
84 	type->name = NULL;
85 	type->len = 0;
86 	type_list_free(&type->expanded);
87 }
88 
type_expansion_append(struct type_expansion * type,const char * s,void * owned)89 static void type_expansion_append(struct type_expansion *type, const char *s,
90 				  void *owned)
91 {
92 	type->len += type_list_append(&type->expanded, s, owned);
93 }
94 
95 /*
96  * type_map -- the longest expansions for each type.
97  *
98  * const char *name -> struct type_expansion *
99  */
100 #define TYPE_HASH_BITS 12
101 static HASHTABLE_DEFINE(type_map, 1 << TYPE_HASH_BITS);
102 
__type_map_get(const char * name,struct type_expansion ** res)103 static int __type_map_get(const char *name, struct type_expansion **res)
104 {
105 	struct type_expansion *e;
106 
107 	hash_for_each_possible(type_map, e, hash, hash_str(name)) {
108 		if (!strcmp(name, e->name)) {
109 			*res = e;
110 			return 0;
111 		}
112 	}
113 
114 	return -1;
115 }
116 
type_map_add(const char * name,struct type_expansion * type)117 static struct type_expansion *type_map_add(const char *name,
118 					   struct type_expansion *type)
119 {
120 	struct type_expansion *e;
121 
122 	if (__type_map_get(name, &e)) {
123 		e = xmalloc(sizeof(struct type_expansion));
124 		type_expansion_init(e);
125 		e->name = xstrdup(name);
126 
127 		hash_add(type_map, &e->hash, hash_str(e->name));
128 
129 		if (dump_types)
130 			debug("adding %s", e->name);
131 	} else {
132 		/* Use the longest available expansion */
133 		if (type->len <= e->len)
134 			return e;
135 
136 		type_list_free(&e->expanded);
137 
138 		if (dump_types)
139 			debug("replacing %s", e->name);
140 	}
141 
142 	/* Take ownership of type->expanded */
143 	list_replace_init(&type->expanded, &e->expanded);
144 	e->len = type->len;
145 
146 	if (dump_types) {
147 		checkp(fputs(e->name, stderr));
148 		checkp(fputs(" ", stderr));
149 		type_list_write(&e->expanded, stderr);
150 		checkp(fputs("\n", stderr));
151 	}
152 
153 	return e;
154 }
155 
156 static void type_parse(const char *name, const char *str,
157 		       struct type_expansion *type);
158 
type_map_get(const char * name,struct type_expansion ** res)159 static int type_map_get(const char *name, struct type_expansion **res)
160 {
161 	struct type_expansion type;
162 	const char *override;
163 
164 	if (!__type_map_get(name, res))
165 		return 0;
166 
167 	/*
168 	 * If die_map didn't contain a type, we might still have
169 	 * a type_string kABI rule that defines it.
170 	 */
171 	if (stable && kabi_get_type_string(name, &override)) {
172 		type_expansion_init(&type);
173 		type_parse(name, override, &type);
174 		*res = type_map_add(name, &type);
175 		type_expansion_free(&type);
176 		return 0;
177 	}
178 
179 	return -1;
180 }
181 
type_map_write(FILE * file)182 static void type_map_write(FILE *file)
183 {
184 	struct type_expansion *e;
185 	struct hlist_node *tmp;
186 
187 	if (!file)
188 		return;
189 
190 	hash_for_each_safe(type_map, e, tmp, hash) {
191 		checkp(fputs(e->name, file));
192 		checkp(fputs(" ", file));
193 		type_list_write(&e->expanded, file);
194 		checkp(fputs("\n", file));
195 	}
196 }
197 
type_map_free(void)198 static void type_map_free(void)
199 {
200 	struct type_expansion *e;
201 	struct hlist_node *tmp;
202 
203 	hash_for_each_safe(type_map, e, tmp, hash) {
204 		type_expansion_free(e);
205 		free(e);
206 	}
207 
208 	hash_init(type_map);
209 }
210 
211 /*
212  * CRC for a type, with an optional fully expanded type string for
213  * debugging.
214  */
215 struct version {
216 	struct type_expansion type;
217 	unsigned long crc;
218 };
219 
version_init(struct version * version)220 static void version_init(struct version *version)
221 {
222 	version->crc = crc32(0, NULL, 0);
223 	type_expansion_init(&version->type);
224 }
225 
version_free(struct version * version)226 static void version_free(struct version *version)
227 {
228 	type_expansion_free(&version->type);
229 }
230 
version_add(struct version * version,const char * s)231 static void version_add(struct version *version, const char *s)
232 {
233 	version->crc = crc32(version->crc, (void *)s, strlen(s));
234 	if (dump_versions)
235 		type_expansion_append(&version->type, s, NULL);
236 }
237 
238 /*
239  * Type reference format: <prefix>#<name>, where prefix:
240  * 	s -> structure
241  * 	u -> union
242  * 	e -> enum
243  * 	t -> typedef
244  *
245  * Names with spaces are additionally wrapped in single quotes.
246  */
is_type_prefix(const char * s)247 static inline bool is_type_prefix(const char *s)
248 {
249 	return (s[0] == 's' || s[0] == 'u' || s[0] == 'e' || s[0] == 't') &&
250 	       s[1] == '#';
251 }
252 
get_type_prefix(int tag)253 static char get_type_prefix(int tag)
254 {
255 	switch (tag) {
256 	case DW_TAG_class_type:
257 	case DW_TAG_structure_type:
258 		return 's';
259 	case DW_TAG_union_type:
260 		return 'u';
261 	case DW_TAG_enumeration_type:
262 		return 'e';
263 	case DW_TAG_typedef_type:
264 		return 't';
265 	default:
266 		return 0;
267 	}
268 }
269 
get_type_name(struct die * cache)270 static char *get_type_name(struct die *cache)
271 {
272 	const char *quote;
273 	char prefix;
274 	char *name;
275 
276 	if (cache->state == DIE_INCOMPLETE) {
277 		warn("found incomplete cache entry: %p", cache);
278 		return NULL;
279 	}
280 	if (cache->state == DIE_SYMBOL || cache->state == DIE_FQN)
281 		return NULL;
282 	if (!cache->fqn || !*cache->fqn)
283 		return NULL;
284 
285 	prefix = get_type_prefix(cache->tag);
286 	if (!prefix)
287 		return NULL;
288 
289 	/* Wrap names with spaces in single quotes */
290 	quote = strstr(cache->fqn, " ") ? "'" : "";
291 
292 	/* <prefix>#<type_name>\0 */
293 	if (asprintf(&name, "%c#%s%s%s", prefix, quote, cache->fqn, quote) < 0)
294 		error("asprintf failed for '%s'", cache->fqn);
295 
296 	return name;
297 }
298 
__calculate_version(struct version * version,struct type_expansion * type)299 static void __calculate_version(struct version *version,
300 				struct type_expansion *type)
301 {
302 	struct type_list_entry *entry;
303 	struct type_expansion *e;
304 
305 	/* Calculate a CRC over an expanded type string */
306 	list_for_each_entry(entry, &type->expanded, list) {
307 		if (is_type_prefix(entry->str)) {
308 			if (type_map_get(entry->str, &e))
309 				error("unknown type reference to '%s' when expanding '%s'",
310 				      entry->str, type->name);
311 
312 			/*
313 			 * It's sufficient to expand each type reference just
314 			 * once to detect changes.
315 			 */
316 			if (cache_was_expanded(&expansion_cache, e)) {
317 				version_add(version, entry->str);
318 			} else {
319 				cache_mark_expanded(&expansion_cache, e);
320 				__calculate_version(version, e);
321 			}
322 		} else {
323 			version_add(version, entry->str);
324 		}
325 	}
326 }
327 
calculate_version(struct version * version,struct type_expansion * type)328 static void calculate_version(struct version *version,
329 			      struct type_expansion *type)
330 {
331 	version_init(version);
332 	__calculate_version(version, type);
333 	cache_free(&expansion_cache);
334 }
335 
__type_expand(struct die * cache,struct type_expansion * type)336 static void __type_expand(struct die *cache, struct type_expansion *type)
337 {
338 	struct die_fragment *df;
339 	struct die *child;
340 	char *name;
341 
342 	list_for_each_entry(df, &cache->fragments, list) {
343 		switch (df->type) {
344 		case FRAGMENT_STRING:
345 			type_expansion_append(type, df->data.str, NULL);
346 			break;
347 		case FRAGMENT_DIE:
348 			/* Use a complete die_map expansion if available */
349 			if (__die_map_get(df->data.addr, DIE_COMPLETE,
350 					  &child) &&
351 			    __die_map_get(df->data.addr, DIE_UNEXPANDED,
352 					  &child))
353 				error("unknown child: %" PRIxPTR,
354 				      df->data.addr);
355 
356 			name = get_type_name(child);
357 			if (name)
358 				type_expansion_append(type, name, name);
359 			else
360 				__type_expand(child, type);
361 
362 			break;
363 		case FRAGMENT_LINEBREAK:
364 			/*
365 			 * Keep whitespace in the symtypes format, but avoid
366 			 * repeated spaces.
367 			 */
368 			if (list_is_last(&df->list, &cache->fragments) ||
369 			    list_next_entry(df, list)->type !=
370 				    FRAGMENT_LINEBREAK)
371 				type_expansion_append(type, " ", NULL);
372 			break;
373 		default:
374 			error("empty die_fragment in %p", cache);
375 		}
376 	}
377 }
378 
type_expand(const char * name,struct die * cache,struct type_expansion * type)379 static void type_expand(const char *name, struct die *cache,
380 			struct type_expansion *type)
381 {
382 	const char *override;
383 
384 	type_expansion_init(type);
385 
386 	if (stable && kabi_get_type_string(name, &override))
387 		type_parse(name, override, type);
388 	else
389 		__type_expand(cache, type);
390 }
391 
type_parse(const char * name,const char * str,struct type_expansion * type)392 static void type_parse(const char *name, const char *str,
393 		       struct type_expansion *type)
394 {
395 	char *fragment;
396 	size_t start = 0;
397 	size_t end;
398 	size_t pos;
399 
400 	if (!*str)
401 		error("empty type string override for '%s'", name);
402 
403 	for (pos = 0; str[pos]; ++pos) {
404 		bool empty;
405 		char marker = ' ';
406 
407 		if (!is_type_prefix(&str[pos]))
408 			continue;
409 
410 		end = pos + 2;
411 
412 		/*
413 		 * Find the end of the type reference. If the type name contains
414 		 * spaces, it must be in single quotes.
415 		 */
416 		if (str[end] == '\'') {
417 			marker = '\'';
418 			++end;
419 		}
420 		while (str[end] && str[end] != marker)
421 			++end;
422 
423 		/* Check that we have a non-empty type name */
424 		if (marker == '\'') {
425 			if (str[end] != marker)
426 				error("incomplete %c# type reference for '%s' (string : '%s')",
427 				      str[pos], name, str);
428 			empty = end == pos + 3;
429 			++end;
430 		} else {
431 			empty = end == pos + 2;
432 		}
433 		if (empty)
434 			error("empty %c# type name for '%s' (string: '%s')",
435 			      str[pos], name, str);
436 
437 		/* Append the part of the string before the type reference */
438 		if (pos > start) {
439 			fragment = xstrndup(&str[start], pos - start);
440 			type_expansion_append(type, fragment, fragment);
441 		}
442 
443 		/*
444 		 * Append the type reference -- note that if the reference
445 		 * is invalid, i.e. points to a non-existent type, we will
446 		 * print out an error when calculating versions.
447 		 */
448 		fragment = xstrndup(&str[pos], end - pos);
449 		type_expansion_append(type, fragment, fragment);
450 
451 		start = end;
452 		pos = end - 1;
453 	}
454 
455 	/* Append the rest of the type string, if there's any left */
456 	if (str[start])
457 		type_expansion_append(type, &str[start], NULL);
458 }
459 
expand_type(struct die * cache,void * arg)460 static void expand_type(struct die *cache, void *arg)
461 {
462 	struct type_expansion type;
463 	char *name;
464 
465 	if (cache->mapped)
466 		return;
467 
468 	cache->mapped = true;
469 
470 	/*
471 	 * Skip unexpanded die_map entries if there's a complete
472 	 * expansion available for this DIE.
473 	 */
474 	if (cache->state == DIE_UNEXPANDED &&
475 	    !__die_map_get(cache->addr, DIE_COMPLETE, &cache)) {
476 		if (cache->mapped)
477 			return;
478 
479 		cache->mapped = true;
480 	}
481 
482 	name = get_type_name(cache);
483 	if (!name)
484 		return;
485 
486 	debug("%s", name);
487 
488 	type_expand(name, cache, &type);
489 	type_map_add(name, &type);
490 	type_expansion_free(&type);
491 	free(name);
492 }
493 
expand_symbol(struct symbol * sym,void * arg)494 static void expand_symbol(struct symbol *sym, void *arg)
495 {
496 	struct type_expansion type;
497 	struct version version;
498 	struct die *cache;
499 
500 	/*
501 	 * No need to expand again unless we want a symtypes file entry
502 	 * for the symbol. Note that this means `sym` has the same address
503 	 * as another symbol that was already processed.
504 	 */
505 	if (!symtypes && sym->state == SYMBOL_PROCESSED)
506 		return;
507 
508 	if (__die_map_get(sym->die_addr, DIE_SYMBOL, &cache))
509 		return; /* We'll warn about missing CRCs later. */
510 
511 	type_expand(sym->name, cache, &type);
512 
513 	/* If the symbol already has a version, don't calculate it again. */
514 	if (sym->state != SYMBOL_PROCESSED) {
515 		calculate_version(&version, &type);
516 		symbol_set_crc(sym, version.crc);
517 		debug("%s = %lx", sym->name, version.crc);
518 
519 		if (dump_versions) {
520 			checkp(fputs(sym->name, stderr));
521 			checkp(fputs(" ", stderr));
522 			type_list_write(&version.type.expanded, stderr);
523 			checkp(fputs("\n", stderr));
524 		}
525 
526 		version_free(&version);
527 	}
528 
529 	/* These aren't needed in type_map unless we want a symtypes file. */
530 	if (symtypes)
531 		type_map_add(sym->name, &type);
532 
533 	type_expansion_free(&type);
534 }
535 
generate_symtypes_and_versions(FILE * file)536 void generate_symtypes_and_versions(FILE *file)
537 {
538 	cache_init(&expansion_cache);
539 
540 	/*
541 	 * die_map processing:
542 	 *
543 	 *   1. die_map contains all types referenced in exported symbol
544 	 *      signatures, but can contain duplicates just like the original
545 	 *      DWARF, and some references may not be fully expanded depending
546 	 *      on how far we processed the DIE tree for that specific symbol.
547 	 *
548 	 *      For each die_map entry, find the longest available expansion,
549 	 *      and add it to type_map.
550 	 */
551 	die_map_for_each(expand_type, NULL);
552 
553 	/*
554 	 *   2. For each exported symbol, expand the die_map type, and use
555 	 *      type_map expansions to calculate a symbol version from the
556 	 *      fully expanded type string.
557 	 */
558 	symbol_for_each(expand_symbol, NULL);
559 
560 	/*
561 	 *   3. If a symtypes file is requested, write type_map contents to
562 	 *      the file.
563 	 */
564 	type_map_write(file);
565 	type_map_free();
566 }
567