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