1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2024 Google LLC 4 */ 5 6 #include <inttypes.h> 7 #include <stdarg.h> 8 #include "gendwarfksyms.h" 9 10 static bool do_linebreak; 11 static int indentation_level; 12 13 /* Line breaks and indentation for pretty-printing */ 14 static void process_linebreak(struct die *cache, int n) 15 { 16 indentation_level += n; 17 do_linebreak = true; 18 die_map_add_linebreak(cache, n); 19 } 20 21 #define DEFINE_GET_ATTR(attr, type) \ 22 static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \ 23 type *value) \ 24 { \ 25 Dwarf_Attribute da; \ 26 return dwarf_attr(die, id, &da) && \ 27 !dwarf_form##attr(&da, value); \ 28 } 29 30 DEFINE_GET_ATTR(flag, bool) 31 DEFINE_GET_ATTR(udata, Dwarf_Word) 32 33 static bool get_ref_die_attr(Dwarf_Die *die, unsigned int id, Dwarf_Die *value) 34 { 35 Dwarf_Attribute da; 36 37 /* dwarf_formref_die returns a pointer instead of an error value. */ 38 return dwarf_attr(die, id, &da) && dwarf_formref_die(&da, value); 39 } 40 41 #define DEFINE_GET_STRING_ATTR(attr) \ 42 static const char *get_##attr##_attr(Dwarf_Die *die) \ 43 { \ 44 Dwarf_Attribute da; \ 45 if (dwarf_attr(die, DW_AT_##attr, &da)) \ 46 return dwarf_formstring(&da); \ 47 return NULL; \ 48 } 49 50 DEFINE_GET_STRING_ATTR(name) 51 DEFINE_GET_STRING_ATTR(linkage_name) 52 53 static const char *get_symbol_name(Dwarf_Die *die) 54 { 55 const char *name; 56 57 /* rustc uses DW_AT_linkage_name for exported symbols */ 58 name = get_linkage_name_attr(die); 59 if (!name) 60 name = get_name_attr(die); 61 62 return name; 63 } 64 65 static bool match_export_symbol(struct state *state, Dwarf_Die *die) 66 { 67 Dwarf_Die *source = die; 68 Dwarf_Die origin; 69 70 /* If the DIE has an abstract origin, use it for type information. */ 71 if (get_ref_die_attr(die, DW_AT_abstract_origin, &origin)) 72 source = &origin; 73 74 state->sym = symbol_get(get_symbol_name(die)); 75 76 /* Look up using the origin name if there are no matches. */ 77 if (!state->sym && source != die) 78 state->sym = symbol_get(get_symbol_name(source)); 79 80 state->die = *source; 81 return !!state->sym; 82 } 83 84 /* DW_AT_decl_file -> struct srcfile */ 85 static struct cache srcfile_cache; 86 87 static bool is_definition_private(Dwarf_Die *die) 88 { 89 Dwarf_Word filenum; 90 Dwarf_Files *files; 91 Dwarf_Die cudie; 92 const char *s; 93 int res; 94 95 /* 96 * Definitions in .c files cannot change the public ABI, 97 * so consider them private. 98 */ 99 if (!get_udata_attr(die, DW_AT_decl_file, &filenum)) 100 return false; 101 102 res = cache_get(&srcfile_cache, filenum); 103 if (res >= 0) 104 return !!res; 105 106 if (!dwarf_cu_die(die->cu, &cudie, NULL, NULL, NULL, NULL, NULL, NULL)) 107 error("dwarf_cu_die failed: '%s'", dwarf_errmsg(-1)); 108 109 if (dwarf_getsrcfiles(&cudie, &files, NULL)) 110 error("dwarf_getsrcfiles failed: '%s'", dwarf_errmsg(-1)); 111 112 s = dwarf_filesrc(files, filenum, NULL, NULL); 113 if (!s) 114 error("dwarf_filesrc failed: '%s'", dwarf_errmsg(-1)); 115 116 s = strrchr(s, '.'); 117 res = s && !strcmp(s, ".c"); 118 cache_set(&srcfile_cache, filenum, res); 119 120 return !!res; 121 } 122 123 static bool is_kabi_definition(struct die *cache, Dwarf_Die *die) 124 { 125 bool value; 126 127 if (get_flag_attr(die, DW_AT_declaration, &value) && value) 128 return false; 129 130 if (kabi_is_declonly(cache->fqn)) 131 return false; 132 133 return !is_definition_private(die); 134 } 135 136 /* 137 * Type string processing 138 */ 139 static void process(struct die *cache, const char *s) 140 { 141 s = s ?: "<null>"; 142 143 if (dump_dies && do_linebreak) { 144 fputs("\n", stderr); 145 for (int i = 0; i < indentation_level; i++) 146 fputs(" ", stderr); 147 do_linebreak = false; 148 } 149 if (dump_dies) 150 fputs(s, stderr); 151 152 if (cache) 153 die_debug_r("cache %p string '%s'", cache, s); 154 die_map_add_string(cache, s); 155 } 156 157 #define MAX_FMT_BUFFER_SIZE 128 158 159 static void process_fmt(struct die *cache, const char *fmt, ...) 160 { 161 char buf[MAX_FMT_BUFFER_SIZE]; 162 va_list args; 163 164 va_start(args, fmt); 165 166 if (checkp(vsnprintf(buf, sizeof(buf), fmt, args)) >= sizeof(buf)) 167 error("vsnprintf overflow: increase MAX_FMT_BUFFER_SIZE"); 168 169 process(cache, buf); 170 va_end(args); 171 } 172 173 #define MAX_FQN_SIZE 64 174 175 /* Get a fully qualified name from DWARF scopes */ 176 static char *get_fqn(Dwarf_Die *die) 177 { 178 const char *list[MAX_FQN_SIZE]; 179 Dwarf_Die *scopes = NULL; 180 bool has_name = false; 181 char *fqn = NULL; 182 char *p; 183 int count = 0; 184 int len = 0; 185 int res; 186 int i; 187 188 res = checkp(dwarf_getscopes_die(die, &scopes)); 189 if (!res) { 190 list[count] = get_name_attr(die); 191 192 if (!list[count]) 193 return NULL; 194 195 len += strlen(list[count]); 196 count++; 197 198 goto done; 199 } 200 201 for (i = res - 1; i >= 0 && count < MAX_FQN_SIZE; i--) { 202 if (dwarf_tag(&scopes[i]) == DW_TAG_compile_unit) 203 continue; 204 205 list[count] = get_name_attr(&scopes[i]); 206 207 if (list[count]) { 208 has_name = true; 209 } else { 210 list[count] = "<anonymous>"; 211 has_name = false; 212 } 213 214 len += strlen(list[count]); 215 count++; 216 217 if (i > 0) { 218 list[count++] = "::"; 219 len += 2; 220 } 221 } 222 223 free(scopes); 224 225 if (count == MAX_FQN_SIZE) 226 warn("increase MAX_FQN_SIZE: reached the maximum"); 227 228 /* Consider the DIE unnamed if the last scope doesn't have a name */ 229 if (!has_name) 230 return NULL; 231 done: 232 fqn = xmalloc(len + 1); 233 *fqn = '\0'; 234 235 p = fqn; 236 for (i = 0; i < count; i++) 237 p = stpcpy(p, list[i]); 238 239 return fqn; 240 } 241 242 static void update_fqn(struct die *cache, Dwarf_Die *die) 243 { 244 if (!cache->fqn) 245 cache->fqn = get_fqn(die) ?: ""; 246 } 247 248 static void process_fqn(struct die *cache, Dwarf_Die *die) 249 { 250 update_fqn(cache, die); 251 if (*cache->fqn) 252 process(cache, " "); 253 process(cache, cache->fqn); 254 } 255 256 #define DEFINE_PROCESS_UDATA_ATTRIBUTE(attribute) \ 257 static void process_##attribute##_attr(struct die *cache, \ 258 Dwarf_Die *die) \ 259 { \ 260 Dwarf_Word value; \ 261 if (get_udata_attr(die, DW_AT_##attribute, &value)) \ 262 process_fmt(cache, " " #attribute "(%" PRIu64 ")", \ 263 value); \ 264 } 265 266 DEFINE_PROCESS_UDATA_ATTRIBUTE(accessibility) 267 DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment) 268 DEFINE_PROCESS_UDATA_ATTRIBUTE(bit_size) 269 DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size) 270 DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding) 271 DEFINE_PROCESS_UDATA_ATTRIBUTE(data_bit_offset) 272 DEFINE_PROCESS_UDATA_ATTRIBUTE(data_member_location) 273 DEFINE_PROCESS_UDATA_ATTRIBUTE(discr_value) 274 275 /* Match functions -- die_match_callback_t */ 276 #define DEFINE_MATCH(type) \ 277 static bool match_##type##_type(Dwarf_Die *die) \ 278 { \ 279 return dwarf_tag(die) == DW_TAG_##type##_type; \ 280 } 281 282 DEFINE_MATCH(enumerator) 283 DEFINE_MATCH(formal_parameter) 284 DEFINE_MATCH(member) 285 DEFINE_MATCH(subrange) 286 287 bool match_all(Dwarf_Die *die) 288 { 289 return true; 290 } 291 292 int process_die_container(struct state *state, struct die *cache, 293 Dwarf_Die *die, die_callback_t func, 294 die_match_callback_t match) 295 { 296 Dwarf_Die current; 297 int res; 298 299 /* Track the first item in lists. */ 300 if (state) 301 state->first_list_item = true; 302 303 res = checkp(dwarf_child(die, ¤t)); 304 while (!res) { 305 if (match(¤t)) { 306 /* <0 = error, 0 = continue, >0 = stop */ 307 res = checkp(func(state, cache, ¤t)); 308 if (res) 309 goto out; 310 } 311 312 res = checkp(dwarf_siblingof(¤t, ¤t)); 313 } 314 315 res = 0; 316 out: 317 if (state) 318 state->first_list_item = false; 319 320 return res; 321 } 322 323 static int process_type(struct state *state, struct die *parent, 324 Dwarf_Die *die); 325 326 static void process_type_attr(struct state *state, struct die *cache, 327 Dwarf_Die *die) 328 { 329 Dwarf_Die type; 330 331 if (get_ref_die_attr(die, DW_AT_type, &type)) { 332 check(process_type(state, cache, &type)); 333 return; 334 } 335 336 /* Compilers can omit DW_AT_type -- print out 'void' to clarify */ 337 process(cache, "base_type void"); 338 } 339 340 static void process_list_comma(struct state *state, struct die *cache) 341 { 342 if (state->first_list_item) { 343 state->first_list_item = false; 344 } else { 345 process(cache, " ,"); 346 process_linebreak(cache, 0); 347 } 348 } 349 350 /* Comma-separated with DW_AT_type */ 351 static void __process_list_type(struct state *state, struct die *cache, 352 Dwarf_Die *die, const char *type) 353 { 354 const char *name = get_name_attr(die); 355 356 process_list_comma(state, cache); 357 process(cache, type); 358 process_type_attr(state, cache, die); 359 if (name) { 360 process(cache, " "); 361 process(cache, name); 362 } 363 process_accessibility_attr(cache, die); 364 process_bit_size_attr(cache, die); 365 process_data_bit_offset_attr(cache, die); 366 process_data_member_location_attr(cache, die); 367 } 368 369 #define DEFINE_PROCESS_LIST_TYPE(type) \ 370 static void process_##type##_type(struct state *state, \ 371 struct die *cache, Dwarf_Die *die) \ 372 { \ 373 __process_list_type(state, cache, die, #type " "); \ 374 } 375 376 DEFINE_PROCESS_LIST_TYPE(formal_parameter) 377 DEFINE_PROCESS_LIST_TYPE(member) 378 379 /* Container types with DW_AT_type */ 380 static void __process_type(struct state *state, struct die *cache, 381 Dwarf_Die *die, const char *type) 382 { 383 process(cache, type); 384 process_fqn(cache, die); 385 process(cache, " {"); 386 process_linebreak(cache, 1); 387 process_type_attr(state, cache, die); 388 process_linebreak(cache, -1); 389 process(cache, "}"); 390 process_byte_size_attr(cache, die); 391 process_alignment_attr(cache, die); 392 } 393 394 #define DEFINE_PROCESS_TYPE(type) \ 395 static void process_##type##_type(struct state *state, \ 396 struct die *cache, Dwarf_Die *die) \ 397 { \ 398 __process_type(state, cache, die, #type "_type"); \ 399 } 400 401 DEFINE_PROCESS_TYPE(atomic) 402 DEFINE_PROCESS_TYPE(const) 403 DEFINE_PROCESS_TYPE(immutable) 404 DEFINE_PROCESS_TYPE(packed) 405 DEFINE_PROCESS_TYPE(pointer) 406 DEFINE_PROCESS_TYPE(reference) 407 DEFINE_PROCESS_TYPE(restrict) 408 DEFINE_PROCESS_TYPE(rvalue_reference) 409 DEFINE_PROCESS_TYPE(shared) 410 DEFINE_PROCESS_TYPE(template_type_parameter) 411 DEFINE_PROCESS_TYPE(volatile) 412 DEFINE_PROCESS_TYPE(typedef) 413 414 static void process_subrange_type(struct state *state, struct die *cache, 415 Dwarf_Die *die) 416 { 417 Dwarf_Word count = 0; 418 419 if (get_udata_attr(die, DW_AT_count, &count)) 420 process_fmt(cache, "[%" PRIu64 "]", count); 421 else if (get_udata_attr(die, DW_AT_upper_bound, &count)) 422 process_fmt(cache, "[%" PRIu64 "]", count + 1); 423 else 424 process(cache, "[]"); 425 } 426 427 static void process_array_type(struct state *state, struct die *cache, 428 Dwarf_Die *die) 429 { 430 process(cache, "array_type"); 431 /* Array size */ 432 check(process_die_container(state, cache, die, process_type, 433 match_subrange_type)); 434 process(cache, " {"); 435 process_linebreak(cache, 1); 436 process_type_attr(state, cache, die); 437 process_linebreak(cache, -1); 438 process(cache, "}"); 439 } 440 441 static void __process_subroutine_type(struct state *state, struct die *cache, 442 Dwarf_Die *die, const char *type) 443 { 444 process(cache, type); 445 process(cache, " ("); 446 process_linebreak(cache, 1); 447 /* Parameters */ 448 check(process_die_container(state, cache, die, process_type, 449 match_formal_parameter_type)); 450 process_linebreak(cache, -1); 451 process(cache, ")"); 452 process_linebreak(cache, 0); 453 /* Return type */ 454 process(cache, "-> "); 455 process_type_attr(state, cache, die); 456 } 457 458 static void process_subroutine_type(struct state *state, struct die *cache, 459 Dwarf_Die *die) 460 { 461 __process_subroutine_type(state, cache, die, "subroutine_type"); 462 } 463 464 static void process_variant_type(struct state *state, struct die *cache, 465 Dwarf_Die *die) 466 { 467 process_list_comma(state, cache); 468 process(cache, "variant {"); 469 process_linebreak(cache, 1); 470 check(process_die_container(state, cache, die, process_type, 471 match_member_type)); 472 process_linebreak(cache, -1); 473 process(cache, "}"); 474 process_discr_value_attr(cache, die); 475 } 476 477 static void process_variant_part_type(struct state *state, struct die *cache, 478 Dwarf_Die *die) 479 { 480 process_list_comma(state, cache); 481 process(cache, "variant_part {"); 482 process_linebreak(cache, 1); 483 check(process_die_container(state, cache, die, process_type, 484 match_all)); 485 process_linebreak(cache, -1); 486 process(cache, "}"); 487 } 488 489 static int ___process_structure_type(struct state *state, struct die *cache, 490 Dwarf_Die *die) 491 { 492 switch (dwarf_tag(die)) { 493 case DW_TAG_member: 494 case DW_TAG_variant_part: 495 return check(process_type(state, cache, die)); 496 case DW_TAG_class_type: 497 case DW_TAG_enumeration_type: 498 case DW_TAG_structure_type: 499 case DW_TAG_template_type_parameter: 500 case DW_TAG_union_type: 501 case DW_TAG_subprogram: 502 /* Skip non-member types, including member functions */ 503 return 0; 504 default: 505 error("unexpected structure_type child: %x", dwarf_tag(die)); 506 } 507 } 508 509 static void __process_structure_type(struct state *state, struct die *cache, 510 Dwarf_Die *die, const char *type, 511 die_callback_t process_func, 512 die_match_callback_t match_func) 513 { 514 bool expand; 515 516 process(cache, type); 517 process_fqn(cache, die); 518 process(cache, " {"); 519 process_linebreak(cache, 1); 520 521 expand = state->expand.expand && is_kabi_definition(cache, die); 522 523 if (expand) { 524 state->expand.current_fqn = cache->fqn; 525 check(process_die_container(state, cache, die, process_func, 526 match_func)); 527 } 528 529 process_linebreak(cache, -1); 530 process(cache, "}"); 531 532 if (expand) { 533 process_byte_size_attr(cache, die); 534 process_alignment_attr(cache, die); 535 } 536 } 537 538 #define DEFINE_PROCESS_STRUCTURE_TYPE(structure) \ 539 static void process_##structure##_type( \ 540 struct state *state, struct die *cache, Dwarf_Die *die) \ 541 { \ 542 __process_structure_type(state, cache, die, \ 543 #structure "_type", \ 544 ___process_structure_type, \ 545 match_all); \ 546 } 547 548 DEFINE_PROCESS_STRUCTURE_TYPE(class) 549 DEFINE_PROCESS_STRUCTURE_TYPE(structure) 550 DEFINE_PROCESS_STRUCTURE_TYPE(union) 551 552 static void process_enumerator_type(struct state *state, struct die *cache, 553 Dwarf_Die *die) 554 { 555 bool overridden = false; 556 Dwarf_Word value; 557 558 if (stable) { 559 /* Get the fqn before we process anything */ 560 update_fqn(cache, die); 561 562 if (kabi_is_enumerator_ignored(state->expand.current_fqn, 563 cache->fqn)) 564 return; 565 566 overridden = kabi_get_enumerator_value( 567 state->expand.current_fqn, cache->fqn, &value); 568 } 569 570 process_list_comma(state, cache); 571 process(cache, "enumerator"); 572 process_fqn(cache, die); 573 574 if (overridden || get_udata_attr(die, DW_AT_const_value, &value)) { 575 process(cache, " = "); 576 process_fmt(cache, "%" PRIu64, value); 577 } 578 } 579 580 static void process_enumeration_type(struct state *state, struct die *cache, 581 Dwarf_Die *die) 582 { 583 __process_structure_type(state, cache, die, "enumeration_type", 584 process_type, match_enumerator_type); 585 } 586 587 static void process_base_type(struct state *state, struct die *cache, 588 Dwarf_Die *die) 589 { 590 process(cache, "base_type"); 591 process_fqn(cache, die); 592 process_byte_size_attr(cache, die); 593 process_encoding_attr(cache, die); 594 process_alignment_attr(cache, die); 595 } 596 597 static void process_unspecified_type(struct state *state, struct die *cache, 598 Dwarf_Die *die) 599 { 600 /* 601 * These can be emitted for stand-alone assembly code, which means we 602 * might run into them in vmlinux.o. 603 */ 604 process(cache, "unspecified_type"); 605 } 606 607 static void process_cached(struct state *state, struct die *cache, 608 Dwarf_Die *die) 609 { 610 struct die_fragment *df; 611 Dwarf_Die child; 612 613 list_for_each_entry(df, &cache->fragments, list) { 614 switch (df->type) { 615 case FRAGMENT_STRING: 616 die_debug_b("cache %p STRING '%s'", cache, 617 df->data.str); 618 process(NULL, df->data.str); 619 break; 620 case FRAGMENT_LINEBREAK: 621 process_linebreak(NULL, df->data.linebreak); 622 break; 623 case FRAGMENT_DIE: 624 if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu), 625 (void *)df->data.addr, &child)) 626 error("dwarf_die_addr_die failed"); 627 die_debug_b("cache %p DIE addr %" PRIxPTR " tag %x", 628 cache, df->data.addr, dwarf_tag(&child)); 629 check(process_type(state, NULL, &child)); 630 break; 631 default: 632 error("empty die_fragment"); 633 } 634 } 635 } 636 637 static void state_init(struct state *state) 638 { 639 state->expand.expand = true; 640 state->expand.current_fqn = NULL; 641 cache_init(&state->expansion_cache); 642 } 643 644 static void expansion_state_restore(struct expansion_state *state, 645 struct expansion_state *saved) 646 { 647 state->expand = saved->expand; 648 state->current_fqn = saved->current_fqn; 649 } 650 651 static void expansion_state_save(struct expansion_state *state, 652 struct expansion_state *saved) 653 { 654 expansion_state_restore(saved, state); 655 } 656 657 static bool is_expanded_type(int tag) 658 { 659 return tag == DW_TAG_class_type || tag == DW_TAG_structure_type || 660 tag == DW_TAG_union_type || tag == DW_TAG_enumeration_type; 661 } 662 663 #define PROCESS_TYPE(type) \ 664 case DW_TAG_##type##_type: \ 665 process_##type##_type(state, cache, die); \ 666 break; 667 668 static int process_type(struct state *state, struct die *parent, Dwarf_Die *die) 669 { 670 enum die_state want_state = DIE_COMPLETE; 671 struct die *cache; 672 struct expansion_state saved; 673 int tag = dwarf_tag(die); 674 675 expansion_state_save(&state->expand, &saved); 676 677 /* 678 * Structures and enumeration types are expanded only once per 679 * exported symbol. This is sufficient for detecting ABI changes 680 * within the structure. 681 */ 682 if (is_expanded_type(tag)) { 683 if (cache_was_expanded(&state->expansion_cache, die->addr)) 684 state->expand.expand = false; 685 686 if (state->expand.expand) 687 cache_mark_expanded(&state->expansion_cache, die->addr); 688 else 689 want_state = DIE_UNEXPANDED; 690 } 691 692 /* 693 * If we have want_state already cached, use it instead of walking 694 * through DWARF. 695 */ 696 cache = die_map_get(die, want_state); 697 698 if (cache->state == want_state) { 699 die_debug_g("cached addr %p tag %x -- %s", die->addr, tag, 700 die_state_name(cache->state)); 701 702 process_cached(state, cache, die); 703 die_map_add_die(parent, cache); 704 705 expansion_state_restore(&state->expand, &saved); 706 return 0; 707 } 708 709 die_debug_g("addr %p tag %x -- %s -> %s", die->addr, tag, 710 die_state_name(cache->state), die_state_name(want_state)); 711 712 switch (tag) { 713 /* Type modifiers */ 714 PROCESS_TYPE(atomic) 715 PROCESS_TYPE(const) 716 PROCESS_TYPE(immutable) 717 PROCESS_TYPE(packed) 718 PROCESS_TYPE(pointer) 719 PROCESS_TYPE(reference) 720 PROCESS_TYPE(restrict) 721 PROCESS_TYPE(rvalue_reference) 722 PROCESS_TYPE(shared) 723 PROCESS_TYPE(volatile) 724 /* Container types */ 725 PROCESS_TYPE(class) 726 PROCESS_TYPE(structure) 727 PROCESS_TYPE(union) 728 PROCESS_TYPE(enumeration) 729 /* Subtypes */ 730 PROCESS_TYPE(enumerator) 731 PROCESS_TYPE(formal_parameter) 732 PROCESS_TYPE(member) 733 PROCESS_TYPE(subrange) 734 PROCESS_TYPE(template_type_parameter) 735 PROCESS_TYPE(variant) 736 PROCESS_TYPE(variant_part) 737 /* Other types */ 738 PROCESS_TYPE(array) 739 PROCESS_TYPE(base) 740 PROCESS_TYPE(subroutine) 741 PROCESS_TYPE(typedef) 742 PROCESS_TYPE(unspecified) 743 default: 744 error("unexpected type: %x", tag); 745 } 746 747 die_debug_r("parent %p cache %p die addr %p tag %x", parent, cache, 748 die->addr, tag); 749 750 /* Update cache state and append to the parent (if any) */ 751 cache->tag = tag; 752 cache->state = want_state; 753 die_map_add_die(parent, cache); 754 755 expansion_state_restore(&state->expand, &saved); 756 return 0; 757 } 758 759 /* 760 * Exported symbol processing 761 */ 762 static struct die *get_symbol_cache(struct state *state, Dwarf_Die *die) 763 { 764 struct die *cache; 765 766 cache = die_map_get(die, DIE_SYMBOL); 767 768 if (cache->state != DIE_INCOMPLETE) 769 return NULL; /* We already processed a symbol for this DIE */ 770 771 cache->tag = dwarf_tag(die); 772 return cache; 773 } 774 775 static void process_symbol(struct state *state, Dwarf_Die *die, 776 die_callback_t process_func) 777 { 778 struct die *cache; 779 780 symbol_set_die(state->sym, die); 781 782 cache = get_symbol_cache(state, die); 783 if (!cache) 784 return; 785 786 debug("%s", state->sym->name); 787 check(process_func(state, cache, die)); 788 cache->state = DIE_SYMBOL; 789 if (dump_dies) 790 fputs("\n", stderr); 791 } 792 793 static int __process_subprogram(struct state *state, struct die *cache, 794 Dwarf_Die *die) 795 { 796 __process_subroutine_type(state, cache, die, "subprogram"); 797 return 0; 798 } 799 800 static void process_subprogram(struct state *state, Dwarf_Die *die) 801 { 802 process_symbol(state, die, __process_subprogram); 803 } 804 805 static int __process_variable(struct state *state, struct die *cache, 806 Dwarf_Die *die) 807 { 808 process(cache, "variable "); 809 process_type_attr(state, cache, die); 810 return 0; 811 } 812 813 static void process_variable(struct state *state, Dwarf_Die *die) 814 { 815 process_symbol(state, die, __process_variable); 816 } 817 818 static int process_exported_symbols(struct state *unused, struct die *cache, 819 Dwarf_Die *die) 820 { 821 int tag = dwarf_tag(die); 822 823 switch (tag) { 824 /* Possible containers of exported symbols */ 825 case DW_TAG_namespace: 826 case DW_TAG_class_type: 827 case DW_TAG_structure_type: 828 return check(process_die_container( 829 NULL, cache, die, process_exported_symbols, match_all)); 830 831 /* Possible exported symbols */ 832 case DW_TAG_subprogram: 833 case DW_TAG_variable: { 834 struct state state; 835 836 if (!match_export_symbol(&state, die)) 837 return 0; 838 839 state_init(&state); 840 841 if (tag == DW_TAG_subprogram) 842 process_subprogram(&state, &state.die); 843 else 844 process_variable(&state, &state.die); 845 846 cache_free(&state.expansion_cache); 847 return 0; 848 } 849 default: 850 return 0; 851 } 852 } 853 854 void process_cu(Dwarf_Die *cudie) 855 { 856 check(process_die_container(NULL, NULL, cudie, process_exported_symbols, 857 match_all)); 858 859 cache_free(&srcfile_cache); 860 } 861