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 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 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 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 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 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 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 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 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 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 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 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 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 243 static void version_init(struct version *version) 244 { 245 version->crc = crc32(0, NULL, 0); 246 type_expansion_init(&version->type); 247 } 248 249 static void version_free(struct version *version) 250 { 251 type_expansion_free(&version->type); 252 } 253 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 */ 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 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 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 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 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 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 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 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 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 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 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