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