1/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces. 2 Copyright (C) 2015-2021 Free Software Foundation, Inc. 3 Adapted from elf.c by Tristan Gingold, AdaCore. 4 5Redistribution and use in source and binary forms, with or without 6modification, are permitted provided that the following conditions are 7met: 8 9 (1) Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 12 (2) Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in 14 the documentation and/or other materials provided with the 15 distribution. 16 17 (3) The name of the author may not be used to 18 endorse or promote products derived from this software without 19 specific prior written permission. 20 21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31POSSIBILITY OF SUCH DAMAGE. */ 32 33#include "config.h" 34 35#include <stdlib.h> 36#include <string.h> 37#include <sys/types.h> 38 39#include "backtrace.h" 40#include "internal.h" 41 42/* Coff file header. */ 43 44typedef struct { 45 uint16_t machine; 46 uint16_t number_of_sections; 47 uint32_t time_date_stamp; 48 uint32_t pointer_to_symbol_table; 49 uint32_t number_of_symbols; 50 uint16_t size_of_optional_header; 51 uint16_t characteristics; 52} b_coff_file_header; 53 54/* Coff optional header. */ 55 56typedef struct { 57 uint16_t magic; 58 uint8_t major_linker_version; 59 uint8_t minor_linker_version; 60 uint32_t size_of_code; 61 uint32_t size_of_initialized_data; 62 uint32_t size_of_uninitialized_data; 63 uint32_t address_of_entry_point; 64 uint32_t base_of_code; 65 union { 66 struct { 67 uint32_t base_of_data; 68 uint32_t image_base; 69 } pe; 70 struct { 71 uint64_t image_base; 72 } pep; 73 } u; 74} b_coff_optional_header; 75 76/* Values of magic in optional header. */ 77 78#define PE_MAGIC 0x10b /* PE32 executable. */ 79#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */ 80 81/* Coff section header. */ 82 83typedef struct { 84 char name[8]; 85 uint32_t virtual_size; 86 uint32_t virtual_address; 87 uint32_t size_of_raw_data; 88 uint32_t pointer_to_raw_data; 89 uint32_t pointer_to_relocations; 90 uint32_t pointer_to_line_numbers; 91 uint16_t number_of_relocations; 92 uint16_t number_of_line_numbers; 93 uint32_t characteristics; 94} b_coff_section_header; 95 96/* Coff symbol name. */ 97 98typedef union { 99 char short_name[8]; 100 struct { 101 unsigned char zeroes[4]; 102 unsigned char off[4]; 103 } long_name; 104} b_coff_name; 105 106/* Coff symbol (external representation which is unaligned). */ 107 108typedef struct { 109 b_coff_name name; 110 unsigned char value[4]; 111 unsigned char section_number[2]; 112 unsigned char type[2]; 113 unsigned char storage_class; 114 unsigned char number_of_aux_symbols; 115} b_coff_external_symbol; 116 117/* Symbol types. */ 118 119#define N_TBSHFT 4 /* Shift for the derived type. */ 120#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */ 121 122/* Size of a coff symbol. */ 123 124#define SYM_SZ 18 125 126/* Coff symbol, internal representation (aligned). */ 127 128typedef struct { 129 const char *name; 130 uint32_t value; 131 int16_t sec; 132 uint16_t type; 133 uint16_t sc; 134} b_coff_internal_symbol; 135 136/* Names of sections, indexed by enum dwarf_section in internal.h. */ 137 138static const char * const debug_section_names[DEBUG_MAX] = 139{ 140 ".debug_info", 141 ".debug_line", 142 ".debug_abbrev", 143 ".debug_ranges", 144 ".debug_str", 145 ".debug_addr", 146 ".debug_str_offsets", 147 ".debug_line_str", 148 ".debug_rnglists" 149}; 150 151/* Information we gather for the sections we care about. */ 152 153struct debug_section_info 154{ 155 /* Section file offset. */ 156 off_t offset; 157 /* Section size. */ 158 size_t size; 159}; 160 161/* Information we keep for an coff symbol. */ 162 163struct coff_symbol 164{ 165 /* The name of the symbol. */ 166 const char *name; 167 /* The address of the symbol. */ 168 uintptr_t address; 169}; 170 171/* Information to pass to coff_syminfo. */ 172 173struct coff_syminfo_data 174{ 175 /* Symbols for the next module. */ 176 struct coff_syminfo_data *next; 177 /* The COFF symbols, sorted by address. */ 178 struct coff_symbol *symbols; 179 /* The number of symbols. */ 180 size_t count; 181}; 182 183/* A dummy callback function used when we can't find any debug info. */ 184 185static int 186coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, 187 uintptr_t pc ATTRIBUTE_UNUSED, 188 backtrace_full_callback callback ATTRIBUTE_UNUSED, 189 backtrace_error_callback error_callback, void *data) 190{ 191 error_callback (data, "no debug info in PE/COFF executable", -1); 192 return 0; 193} 194 195/* A dummy callback function used when we can't find a symbol 196 table. */ 197 198static void 199coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, 200 uintptr_t addr ATTRIBUTE_UNUSED, 201 backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, 202 backtrace_error_callback error_callback, void *data) 203{ 204 error_callback (data, "no symbol table in PE/COFF executable", -1); 205} 206 207/* Read a potentially unaligned 4 byte word at P, using native endianness. */ 208 209static uint32_t 210coff_read4 (const unsigned char *p) 211{ 212 uint32_t res; 213 214 memcpy (&res, p, 4); 215 return res; 216} 217 218/* Read a potentially unaligned 2 byte word at P, using native endianness. 219 All 2 byte word in symbols are always aligned, but for coherency all 220 fields are declared as char arrays. */ 221 222static uint16_t 223coff_read2 (const unsigned char *p) 224{ 225 uint16_t res; 226 227 memcpy (&res, p, sizeof (res)); 228 return res; 229} 230 231/* Return the length (without the trailing 0) of a COFF short name. */ 232 233static size_t 234coff_short_name_len (const char *name) 235{ 236 int i; 237 238 for (i = 0; i < 8; i++) 239 if (name[i] == 0) 240 return i; 241 return 8; 242} 243 244/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated 245 string). */ 246 247static int 248coff_short_name_eq (const char *name, const char *cname) 249{ 250 int i; 251 252 for (i = 0; i < 8; i++) 253 { 254 if (name[i] != cname[i]) 255 return 0; 256 if (name[i] == 0) 257 return 1; 258 } 259 return name[8] == 0; 260} 261 262/* Return true iff NAME is the same as string at offset OFF. */ 263 264static int 265coff_long_name_eq (const char *name, unsigned int off, 266 struct backtrace_view *str_view) 267{ 268 if (off >= str_view->len) 269 return 0; 270 return strcmp (name, (const char *)str_view->data + off) == 0; 271} 272 273/* Compare struct coff_symbol for qsort. */ 274 275static int 276coff_symbol_compare (const void *v1, const void *v2) 277{ 278 const struct coff_symbol *e1 = (const struct coff_symbol *) v1; 279 const struct coff_symbol *e2 = (const struct coff_symbol *) v2; 280 281 if (e1->address < e2->address) 282 return -1; 283 else if (e1->address > e2->address) 284 return 1; 285 else 286 return 0; 287} 288 289/* Convert SYM to internal (and aligned) format ISYM, using string table 290 from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM. 291 Return -1 in case of error (invalid section number or string index). */ 292 293static int 294coff_expand_symbol (b_coff_internal_symbol *isym, 295 const b_coff_external_symbol *sym, 296 uint16_t sects_num, 297 const unsigned char *strtab, size_t strtab_size) 298{ 299 isym->type = coff_read2 (sym->type); 300 isym->sec = coff_read2 (sym->section_number); 301 isym->sc = sym->storage_class; 302 303 if (isym->sec > 0 && (uint16_t) isym->sec > sects_num) 304 return -1; 305 if (sym->name.short_name[0] != 0) 306 isym->name = sym->name.short_name; 307 else 308 { 309 uint32_t off = coff_read4 (sym->name.long_name.off); 310 311 if (off >= strtab_size) 312 return -1; 313 isym->name = (const char *) strtab + off; 314 } 315 return 0; 316} 317 318/* Return true iff SYM is a defined symbol for a function. Data symbols 319 aren't considered because they aren't easily identified (same type as 320 section names, presence of symbols defined by the linker script). */ 321 322static int 323coff_is_function_symbol (const b_coff_internal_symbol *isym) 324{ 325 return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION 326 && isym->sec > 0; 327} 328 329/* Initialize the symbol table info for coff_syminfo. */ 330 331static int 332coff_initialize_syminfo (struct backtrace_state *state, 333 uintptr_t base_address, int is_64, 334 const b_coff_section_header *sects, size_t sects_num, 335 const b_coff_external_symbol *syms, size_t syms_size, 336 const unsigned char *strtab, size_t strtab_size, 337 backtrace_error_callback error_callback, 338 void *data, struct coff_syminfo_data *sdata) 339{ 340 size_t syms_count; 341 char *coff_symstr; 342 size_t coff_symstr_len; 343 size_t coff_symbol_count; 344 size_t coff_symbol_size; 345 struct coff_symbol *coff_symbols; 346 struct coff_symbol *coff_sym; 347 char *coff_str; 348 size_t i; 349 350 syms_count = syms_size / SYM_SZ; 351 352 /* We only care about function symbols. Count them. Also count size of 353 strings for in-symbol names. */ 354 coff_symbol_count = 0; 355 coff_symstr_len = 0; 356 for (i = 0; i < syms_count; ++i) 357 { 358 const b_coff_external_symbol *asym = &syms[i]; 359 b_coff_internal_symbol isym; 360 361 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0) 362 { 363 error_callback (data, "invalid section or offset in coff symbol", 0); 364 return 0; 365 } 366 if (coff_is_function_symbol (&isym)) 367 { 368 ++coff_symbol_count; 369 if (asym->name.short_name[0] != 0) 370 coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1; 371 } 372 373 i += asym->number_of_aux_symbols; 374 } 375 376 coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol); 377 coff_symbols = ((struct coff_symbol *) 378 backtrace_alloc (state, coff_symbol_size, error_callback, 379 data)); 380 if (coff_symbols == NULL) 381 return 0; 382 383 /* Allocate memory for symbols strings. */ 384 if (coff_symstr_len > 0) 385 { 386 coff_symstr = ((char *) 387 backtrace_alloc (state, coff_symstr_len, error_callback, 388 data)); 389 if (coff_symstr == NULL) 390 { 391 backtrace_free (state, coff_symbols, coff_symbol_size, 392 error_callback, data); 393 return 0; 394 } 395 } 396 else 397 coff_symstr = NULL; 398 399 /* Copy symbols. */ 400 coff_sym = coff_symbols; 401 coff_str = coff_symstr; 402 for (i = 0; i < syms_count; ++i) 403 { 404 const b_coff_external_symbol *asym = &syms[i]; 405 b_coff_internal_symbol isym; 406 407 if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size)) 408 { 409 /* Should not fail, as it was already tested in the previous 410 loop. */ 411 abort (); 412 } 413 if (coff_is_function_symbol (&isym)) 414 { 415 const char *name; 416 int16_t secnum; 417 418 if (asym->name.short_name[0] != 0) 419 { 420 size_t len = coff_short_name_len (isym.name); 421 name = coff_str; 422 memcpy (coff_str, isym.name, len); 423 coff_str[len] = 0; 424 coff_str += len + 1; 425 } 426 else 427 name = isym.name; 428 429 if (!is_64) 430 { 431 /* Strip leading '_'. */ 432 if (name[0] == '_') 433 name++; 434 } 435 436 /* Symbol value is section relative, so we need to read the address 437 of its section. */ 438 secnum = coff_read2 (asym->section_number); 439 440 coff_sym->name = name; 441 coff_sym->address = (coff_read4 (asym->value) 442 + sects[secnum - 1].virtual_address 443 + base_address); 444 coff_sym++; 445 } 446 447 i += asym->number_of_aux_symbols; 448 } 449 450 /* End of symbols marker. */ 451 coff_sym->name = NULL; 452 coff_sym->address = -1; 453 454 backtrace_qsort (coff_symbols, coff_symbol_count, 455 sizeof (struct coff_symbol), coff_symbol_compare); 456 457 sdata->next = NULL; 458 sdata->symbols = coff_symbols; 459 sdata->count = coff_symbol_count; 460 461 return 1; 462} 463 464/* Add EDATA to the list in STATE. */ 465 466static void 467coff_add_syminfo_data (struct backtrace_state *state, 468 struct coff_syminfo_data *sdata) 469{ 470 if (!state->threaded) 471 { 472 struct coff_syminfo_data **pp; 473 474 for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data; 475 *pp != NULL; 476 pp = &(*pp)->next) 477 ; 478 *pp = sdata; 479 } 480 else 481 { 482 while (1) 483 { 484 struct coff_syminfo_data **pp; 485 486 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data; 487 488 while (1) 489 { 490 struct coff_syminfo_data *p; 491 492 p = backtrace_atomic_load_pointer (pp); 493 494 if (p == NULL) 495 break; 496 497 pp = &p->next; 498 } 499 500 if (__sync_bool_compare_and_swap (pp, NULL, sdata)) 501 break; 502 } 503 } 504} 505 506/* Compare an ADDR against an elf_symbol for bsearch. We allocate one 507 extra entry in the array so that this can look safely at the next 508 entry. */ 509 510static int 511coff_symbol_search (const void *vkey, const void *ventry) 512{ 513 const uintptr_t *key = (const uintptr_t *) vkey; 514 const struct coff_symbol *entry = (const struct coff_symbol *) ventry; 515 uintptr_t addr; 516 517 addr = *key; 518 if (addr < entry->address) 519 return -1; 520 else if (addr >= entry[1].address) 521 return 1; 522 else 523 return 0; 524} 525 526/* Return the symbol name and value for an ADDR. */ 527 528static void 529coff_syminfo (struct backtrace_state *state, uintptr_t addr, 530 backtrace_syminfo_callback callback, 531 backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 532 void *data) 533{ 534 struct coff_syminfo_data *sdata; 535 struct coff_symbol *sym = NULL; 536 537 if (!state->threaded) 538 { 539 for (sdata = (struct coff_syminfo_data *) state->syminfo_data; 540 sdata != NULL; 541 sdata = sdata->next) 542 { 543 sym = ((struct coff_symbol *) 544 bsearch (&addr, sdata->symbols, sdata->count, 545 sizeof (struct coff_symbol), coff_symbol_search)); 546 if (sym != NULL) 547 break; 548 } 549 } 550 else 551 { 552 struct coff_syminfo_data **pp; 553 554 pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data; 555 while (1) 556 { 557 sdata = backtrace_atomic_load_pointer (pp); 558 if (sdata == NULL) 559 break; 560 561 sym = ((struct coff_symbol *) 562 bsearch (&addr, sdata->symbols, sdata->count, 563 sizeof (struct coff_symbol), coff_symbol_search)); 564 if (sym != NULL) 565 break; 566 567 pp = &sdata->next; 568 } 569 } 570 571 if (sym == NULL) 572 callback (data, addr, NULL, 0, 0); 573 else 574 callback (data, addr, sym->name, sym->address, 0); 575} 576 577/* Add the backtrace data for one PE/COFF file. Returns 1 on success, 578 0 on failure (in both cases descriptor is closed). */ 579 580static int 581coff_add (struct backtrace_state *state, int descriptor, 582 backtrace_error_callback error_callback, void *data, 583 fileline *fileline_fn, int *found_sym, int *found_dwarf) 584{ 585 struct backtrace_view fhdr_view; 586 off_t fhdr_off; 587 int magic_ok; 588 b_coff_file_header fhdr; 589 off_t opt_sects_off; 590 size_t opt_sects_size; 591 unsigned int sects_num; 592 struct backtrace_view sects_view; 593 int sects_view_valid; 594 const b_coff_optional_header *opt_hdr; 595 const b_coff_section_header *sects; 596 struct backtrace_view str_view; 597 int str_view_valid; 598 size_t str_size; 599 off_t str_off; 600 struct backtrace_view syms_view; 601 off_t syms_off; 602 size_t syms_size; 603 int syms_view_valid; 604 unsigned int syms_num; 605 unsigned int i; 606 struct debug_section_info sections[DEBUG_MAX]; 607 off_t min_offset; 608 off_t max_offset; 609 struct backtrace_view debug_view; 610 int debug_view_valid; 611 int is_64; 612 uintptr_t image_base; 613 struct dwarf_sections dwarf_sections; 614 615 *found_sym = 0; 616 *found_dwarf = 0; 617 618 sects_view_valid = 0; 619 syms_view_valid = 0; 620 str_view_valid = 0; 621 debug_view_valid = 0; 622 623 /* Map the MS-DOS stub (if any) and extract file header offset. */ 624 if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback, 625 data, &fhdr_view)) 626 goto fail; 627 628 { 629 const unsigned char *vptr = fhdr_view.data; 630 631 if (vptr[0] == 'M' && vptr[1] == 'Z') 632 fhdr_off = coff_read4 (vptr + 0x3c); 633 else 634 fhdr_off = 0; 635 } 636 637 backtrace_release_view (state, &fhdr_view, error_callback, data); 638 639 /* Map the coff file header. */ 640 if (!backtrace_get_view (state, descriptor, fhdr_off, 641 sizeof (b_coff_file_header) + 4, 642 error_callback, data, &fhdr_view)) 643 goto fail; 644 645 if (fhdr_off != 0) 646 { 647 const char *magic = (const char *) fhdr_view.data; 648 magic_ok = memcmp (magic, "PE\0", 4) == 0; 649 fhdr_off += 4; 650 651 memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr); 652 } 653 else 654 { 655 memcpy (&fhdr, fhdr_view.data, sizeof fhdr); 656 /* TODO: test fhdr.machine for coff but non-PE platforms. */ 657 magic_ok = 0; 658 } 659 backtrace_release_view (state, &fhdr_view, error_callback, data); 660 661 if (!magic_ok) 662 { 663 error_callback (data, "executable file is not COFF", 0); 664 goto fail; 665 } 666 667 sects_num = fhdr.number_of_sections; 668 syms_num = fhdr.number_of_symbols; 669 670 opt_sects_off = fhdr_off + sizeof (fhdr); 671 opt_sects_size = (fhdr.size_of_optional_header 672 + sects_num * sizeof (b_coff_section_header)); 673 674 /* To translate PC to file/line when using DWARF, we need to find 675 the .debug_info and .debug_line sections. */ 676 677 /* Read the optional header and the section headers. */ 678 679 if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size, 680 error_callback, data, §s_view)) 681 goto fail; 682 sects_view_valid = 1; 683 opt_hdr = (const b_coff_optional_header *) sects_view.data; 684 sects = (const b_coff_section_header *) 685 (sects_view.data + fhdr.size_of_optional_header); 686 687 is_64 = 0; 688 if (fhdr.size_of_optional_header > sizeof (*opt_hdr)) 689 { 690 if (opt_hdr->magic == PE_MAGIC) 691 image_base = opt_hdr->u.pe.image_base; 692 else if (opt_hdr->magic == PEP_MAGIC) 693 { 694 image_base = opt_hdr->u.pep.image_base; 695 is_64 = 1; 696 } 697 else 698 { 699 error_callback (data, "bad magic in PE optional header", 0); 700 goto fail; 701 } 702 } 703 else 704 image_base = 0; 705 706 /* Read the symbol table and the string table. */ 707 708 if (fhdr.pointer_to_symbol_table == 0) 709 { 710 /* No symbol table, no string table. */ 711 str_off = 0; 712 str_size = 0; 713 syms_num = 0; 714 syms_size = 0; 715 } 716 else 717 { 718 /* Symbol table is followed by the string table. The string table 719 starts with its length (on 4 bytes). 720 Map the symbol table and the length of the string table. */ 721 syms_off = fhdr.pointer_to_symbol_table; 722 syms_size = syms_num * SYM_SZ; 723 724 if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4, 725 error_callback, data, &syms_view)) 726 goto fail; 727 syms_view_valid = 1; 728 729 str_size = coff_read4 (syms_view.data + syms_size); 730 731 str_off = syms_off + syms_size; 732 733 if (str_size > 4) 734 { 735 /* Map string table (including the length word). */ 736 737 if (!backtrace_get_view (state, descriptor, str_off, str_size, 738 error_callback, data, &str_view)) 739 goto fail; 740 str_view_valid = 1; 741 } 742 } 743 744 memset (sections, 0, sizeof sections); 745 746 /* Look for the symbol table. */ 747 for (i = 0; i < sects_num; ++i) 748 { 749 const b_coff_section_header *s = sects + i; 750 unsigned int str_off; 751 int j; 752 753 if (s->name[0] == '/') 754 { 755 /* Extended section name. */ 756 str_off = atoi (s->name + 1); 757 } 758 else 759 str_off = 0; 760 761 for (j = 0; j < (int) DEBUG_MAX; ++j) 762 { 763 const char *dbg_name = debug_section_names[j]; 764 int match; 765 766 if (str_off != 0) 767 match = coff_long_name_eq (dbg_name, str_off, &str_view); 768 else 769 match = coff_short_name_eq (dbg_name, s->name); 770 if (match) 771 { 772 sections[j].offset = s->pointer_to_raw_data; 773 sections[j].size = s->virtual_size <= s->size_of_raw_data ? 774 s->virtual_size : s->size_of_raw_data; 775 break; 776 } 777 } 778 } 779 780 if (syms_num != 0) 781 { 782 struct coff_syminfo_data *sdata; 783 784 sdata = ((struct coff_syminfo_data *) 785 backtrace_alloc (state, sizeof *sdata, error_callback, data)); 786 if (sdata == NULL) 787 goto fail; 788 789 if (!coff_initialize_syminfo (state, image_base, is_64, 790 sects, sects_num, 791 syms_view.data, syms_size, 792 str_view.data, str_size, 793 error_callback, data, sdata)) 794 { 795 backtrace_free (state, sdata, sizeof *sdata, error_callback, data); 796 goto fail; 797 } 798 799 *found_sym = 1; 800 801 coff_add_syminfo_data (state, sdata); 802 } 803 804 backtrace_release_view (state, §s_view, error_callback, data); 805 sects_view_valid = 0; 806 if (syms_view_valid) 807 { 808 backtrace_release_view (state, &syms_view, error_callback, data); 809 syms_view_valid = 0; 810 } 811 812 /* Read all the debug sections in a single view, since they are 813 probably adjacent in the file. We never release this view. */ 814 815 min_offset = 0; 816 max_offset = 0; 817 for (i = 0; i < (int) DEBUG_MAX; ++i) 818 { 819 off_t end; 820 821 if (sections[i].size == 0) 822 continue; 823 if (min_offset == 0 || sections[i].offset < min_offset) 824 min_offset = sections[i].offset; 825 end = sections[i].offset + sections[i].size; 826 if (end > max_offset) 827 max_offset = end; 828 } 829 if (min_offset == 0 || max_offset == 0) 830 { 831 if (!backtrace_close (descriptor, error_callback, data)) 832 goto fail; 833 *fileline_fn = coff_nodebug; 834 return 1; 835 } 836 837 if (!backtrace_get_view (state, descriptor, min_offset, 838 max_offset - min_offset, 839 error_callback, data, &debug_view)) 840 goto fail; 841 debug_view_valid = 1; 842 843 /* We've read all we need from the executable. */ 844 if (!backtrace_close (descriptor, error_callback, data)) 845 goto fail; 846 descriptor = -1; 847 848 for (i = 0; i < (int) DEBUG_MAX; ++i) 849 { 850 size_t size = sections[i].size; 851 dwarf_sections.size[i] = size; 852 if (size == 0) 853 dwarf_sections.data[i] = NULL; 854 else 855 dwarf_sections.data[i] = ((const unsigned char *) debug_view.data 856 + (sections[i].offset - min_offset)); 857 } 858 859 if (!backtrace_dwarf_add (state, /* base_address */ 0, &dwarf_sections, 860 0, /* FIXME: is_bigendian */ 861 NULL, /* altlink */ 862 error_callback, data, fileline_fn, 863 NULL /* returned fileline_entry */)) 864 goto fail; 865 866 *found_dwarf = 1; 867 868 return 1; 869 870 fail: 871 if (sects_view_valid) 872 backtrace_release_view (state, §s_view, error_callback, data); 873 if (str_view_valid) 874 backtrace_release_view (state, &str_view, error_callback, data); 875 if (syms_view_valid) 876 backtrace_release_view (state, &syms_view, error_callback, data); 877 if (debug_view_valid) 878 backtrace_release_view (state, &debug_view, error_callback, data); 879 if (descriptor != -1) 880 backtrace_close (descriptor, error_callback, data); 881 return 0; 882} 883 884/* Initialize the backtrace data we need from an ELF executable. At 885 the ELF level, all we need to do is find the debug info 886 sections. */ 887 888int 889backtrace_initialize (struct backtrace_state *state, 890 const char *filename ATTRIBUTE_UNUSED, int descriptor, 891 backtrace_error_callback error_callback, 892 void *data, fileline *fileline_fn) 893{ 894 int ret; 895 int found_sym; 896 int found_dwarf; 897 fileline coff_fileline_fn; 898 899 ret = coff_add (state, descriptor, error_callback, data, 900 &coff_fileline_fn, &found_sym, &found_dwarf); 901 if (!ret) 902 return 0; 903 904 if (!state->threaded) 905 { 906 if (found_sym) 907 state->syminfo_fn = coff_syminfo; 908 else if (state->syminfo_fn == NULL) 909 state->syminfo_fn = coff_nosyms; 910 } 911 else 912 { 913 if (found_sym) 914 backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo); 915 else 916 (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, 917 coff_nosyms); 918 } 919 920 if (!state->threaded) 921 { 922 if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug) 923 *fileline_fn = coff_fileline_fn; 924 } 925 else 926 { 927 fileline current_fn; 928 929 current_fn = backtrace_atomic_load_pointer (&state->fileline_fn); 930 if (current_fn == NULL || current_fn == coff_nodebug) 931 *fileline_fn = coff_fileline_fn; 932 } 933 934 return 1; 935} 936