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