1 /* PEF support for BFD. 2 Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 3 2009, 2011 Free Software Foundation, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "safe-ctype.h" 24 #include "pef.h" 25 #include "pef-traceback.h" 26 #include "bfd.h" 27 #include "libbfd.h" 28 #include "libiberty.h" 29 30 #ifndef BFD_IO_FUNCS 31 #define BFD_IO_FUNCS 0 32 #endif 33 34 #define bfd_pef_close_and_cleanup _bfd_generic_close_and_cleanup 35 #define bfd_pef_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 36 #define bfd_pef_new_section_hook _bfd_generic_new_section_hook 37 #define bfd_pef_bfd_is_local_label_name bfd_generic_is_local_label_name 38 #define bfd_pef_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false) 39 #define bfd_pef_get_lineno _bfd_nosymbols_get_lineno 40 #define bfd_pef_find_nearest_line _bfd_nosymbols_find_nearest_line 41 #define bfd_pef_find_inliner_info _bfd_nosymbols_find_inliner_info 42 #define bfd_pef_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol 43 #define bfd_pef_read_minisymbols _bfd_generic_read_minisymbols 44 #define bfd_pef_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol 45 #define bfd_pef_set_arch_mach _bfd_generic_set_arch_mach 46 #define bfd_pef_get_section_contents _bfd_generic_get_section_contents 47 #define bfd_pef_set_section_contents _bfd_generic_set_section_contents 48 #define bfd_pef_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents 49 #define bfd_pef_bfd_relax_section bfd_generic_relax_section 50 #define bfd_pef_bfd_gc_sections bfd_generic_gc_sections 51 #define bfd_pef_bfd_merge_sections bfd_generic_merge_sections 52 #define bfd_pef_bfd_is_group_section bfd_generic_is_group_section 53 #define bfd_pef_bfd_discard_group bfd_generic_discard_group 54 #define bfd_pef_section_already_linked _bfd_generic_section_already_linked 55 #define bfd_pef_bfd_define_common_symbol bfd_generic_define_common_symbol 56 #define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create 57 #define bfd_pef_bfd_link_hash_table_free _bfd_generic_link_hash_table_free 58 #define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols 59 #define bfd_pef_bfd_link_just_syms _bfd_generic_link_just_syms 60 #define bfd_pef_bfd_copy_link_hash_symbol_type \ 61 _bfd_generic_copy_link_hash_symbol_type 62 #define bfd_pef_bfd_final_link _bfd_generic_final_link 63 #define bfd_pef_bfd_link_split_section _bfd_generic_link_split_section 64 #define bfd_pef_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 65 66 static int 67 bfd_pef_parse_traceback_table (bfd *abfd, 68 asection *section, 69 unsigned char *buf, 70 size_t len, 71 size_t pos, 72 asymbol *sym, 73 FILE *file) 74 { 75 struct traceback_table table; 76 size_t offset; 77 const char *s; 78 asymbol tmpsymbol; 79 80 if (sym == NULL) 81 sym = & tmpsymbol; 82 83 sym->name = NULL; 84 sym->value = 0; 85 sym->the_bfd = abfd; 86 sym->section = section; 87 sym->flags = 0; 88 sym->udata.i = 0; 89 90 /* memcpy is fine since all fields are unsigned char. */ 91 if ((pos + 8) > len) 92 return -1; 93 memcpy (&table, buf + pos, 8); 94 95 /* Calling code relies on returned symbols having a name and 96 correct offset. */ 97 if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS)) 98 return -1; 99 100 if (! (table.flags2 & TB_NAME_PRESENT)) 101 return -1; 102 103 if (! (table.flags1 & TB_HAS_TBOFF)) 104 return -1; 105 106 offset = 8; 107 108 if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams)) 109 offset += 4; 110 111 if (table.flags1 & TB_HAS_TBOFF) 112 { 113 struct traceback_table_tboff off; 114 115 if ((pos + offset + 4) > len) 116 return -1; 117 off.tb_offset = bfd_getb32 (buf + pos + offset); 118 offset += 4; 119 120 /* Need to subtract 4 because the offset includes the 0x0L 121 preceding the table. */ 122 if (file != NULL) 123 fprintf (file, " [offset = 0x%lx]", off.tb_offset); 124 125 if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset))) 126 return -1; 127 128 sym->value = pos - off.tb_offset - 4; 129 } 130 131 if (table.flags2 & TB_INT_HNDL) 132 offset += 4; 133 134 if (table.flags1 & TB_HAS_CTL) 135 { 136 struct traceback_table_anchors anchors; 137 138 if ((pos + offset + 4) > len) 139 return -1; 140 anchors.ctl_info = bfd_getb32 (buf + pos + offset); 141 offset += 4; 142 143 if (anchors.ctl_info > 1024) 144 return -1; 145 146 offset += anchors.ctl_info * 4; 147 } 148 149 if (table.flags2 & TB_NAME_PRESENT) 150 { 151 struct traceback_table_routine name; 152 char *namebuf; 153 154 if ((pos + offset + 2) > len) 155 return -1; 156 name.name_len = bfd_getb16 (buf + pos + offset); 157 offset += 2; 158 159 if (name.name_len > 4096) 160 return -1; 161 162 if ((pos + offset + name.name_len) > len) 163 return -1; 164 165 namebuf = bfd_alloc (abfd, name.name_len + 1); 166 if (namebuf == NULL) 167 return -1; 168 169 memcpy (namebuf, buf + pos + offset, name.name_len); 170 namebuf[name.name_len] = '\0'; 171 172 /* Strip leading period inserted by compiler. */ 173 if (namebuf[0] == '.') 174 memmove (namebuf, namebuf + 1, name.name_len + 1); 175 176 sym->name = namebuf; 177 178 for (s = sym->name; (*s != '\0'); s++) 179 if (! ISPRINT (*s)) 180 return -1; 181 182 offset += name.name_len; 183 } 184 185 if (table.flags2 & TB_USES_ALLOCA) 186 offset += 4; 187 188 if (table.flags4 & TB_HAS_VEC_INFO) 189 offset += 4; 190 191 if (file != NULL) 192 fprintf (file, " [length = 0x%lx]", (unsigned long) offset); 193 194 return offset; 195 } 196 197 static void 198 bfd_pef_print_symbol (bfd *abfd, 199 void * afile, 200 asymbol *symbol, 201 bfd_print_symbol_type how) 202 { 203 FILE *file = (FILE *) afile; 204 205 switch (how) 206 { 207 case bfd_print_symbol_name: 208 fprintf (file, "%s", symbol->name); 209 break; 210 default: 211 bfd_print_symbol_vandf (abfd, (void *) file, symbol); 212 fprintf (file, " %-5s %s", symbol->section->name, symbol->name); 213 if (CONST_STRNEQ (symbol->name, "__traceback_")) 214 { 215 unsigned char *buf = alloca (symbol->udata.i); 216 size_t offset = symbol->value + 4; 217 size_t len = symbol->udata.i; 218 int ret; 219 220 bfd_get_section_contents (abfd, symbol->section, buf, offset, len); 221 ret = bfd_pef_parse_traceback_table (abfd, symbol->section, buf, 222 len, 0, NULL, file); 223 if (ret < 0) 224 fprintf (file, " [ERROR]"); 225 } 226 } 227 } 228 229 static void 230 bfd_pef_convert_architecture (unsigned long architecture, 231 enum bfd_architecture *type, 232 unsigned long *subtype) 233 { 234 const unsigned long ARCH_POWERPC = 0x70777063; /* 'pwpc'. */ 235 const unsigned long ARCH_M68K = 0x6d36386b; /* 'm68k'. */ 236 237 *subtype = bfd_arch_unknown; 238 *type = bfd_arch_unknown; 239 240 if (architecture == ARCH_POWERPC) 241 *type = bfd_arch_powerpc; 242 else if (architecture == ARCH_M68K) 243 *type = bfd_arch_m68k; 244 } 245 246 static bfd_boolean 247 bfd_pef_mkobject (bfd *abfd ATTRIBUTE_UNUSED) 248 { 249 return TRUE; 250 } 251 252 static const char *bfd_pef_section_name (bfd_pef_section *section) 253 { 254 switch (section->section_kind) 255 { 256 case BFD_PEF_SECTION_CODE: return "code"; 257 case BFD_PEF_SECTION_UNPACKED_DATA: return "unpacked-data"; 258 case BFD_PEF_SECTION_PACKED_DATA: return "packed-data"; 259 case BFD_PEF_SECTION_CONSTANT: return "constant"; 260 case BFD_PEF_SECTION_LOADER: return "loader"; 261 case BFD_PEF_SECTION_DEBUG: return "debug"; 262 case BFD_PEF_SECTION_EXEC_DATA: return "exec-data"; 263 case BFD_PEF_SECTION_EXCEPTION: return "exception"; 264 case BFD_PEF_SECTION_TRACEBACK: return "traceback"; 265 default: return "unknown"; 266 } 267 } 268 269 static unsigned long bfd_pef_section_flags (bfd_pef_section *section) 270 { 271 switch (section->section_kind) 272 { 273 case BFD_PEF_SECTION_CODE: 274 return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE; 275 case BFD_PEF_SECTION_UNPACKED_DATA: 276 case BFD_PEF_SECTION_PACKED_DATA: 277 case BFD_PEF_SECTION_CONSTANT: 278 case BFD_PEF_SECTION_LOADER: 279 case BFD_PEF_SECTION_DEBUG: 280 case BFD_PEF_SECTION_EXEC_DATA: 281 case BFD_PEF_SECTION_EXCEPTION: 282 case BFD_PEF_SECTION_TRACEBACK: 283 default: 284 return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC; 285 } 286 } 287 288 static asection * 289 bfd_pef_make_bfd_section (bfd *abfd, bfd_pef_section *section) 290 { 291 asection *bfdsec; 292 const char *name = bfd_pef_section_name (section); 293 294 bfdsec = bfd_make_section_anyway (abfd, name); 295 if (bfdsec == NULL) 296 return NULL; 297 298 bfdsec->vma = section->default_address + section->container_offset; 299 bfdsec->lma = section->default_address + section->container_offset; 300 bfdsec->size = section->container_length; 301 bfdsec->filepos = section->container_offset; 302 bfdsec->alignment_power = section->alignment; 303 304 bfdsec->flags = bfd_pef_section_flags (section); 305 306 return bfdsec; 307 } 308 309 int 310 bfd_pef_parse_loader_header (bfd *abfd ATTRIBUTE_UNUSED, 311 unsigned char *buf, 312 size_t len, 313 bfd_pef_loader_header *header) 314 { 315 BFD_ASSERT (len == 56); 316 317 header->main_section = bfd_getb32 (buf); 318 header->main_offset = bfd_getb32 (buf + 4); 319 header->init_section = bfd_getb32 (buf + 8); 320 header->init_offset = bfd_getb32 (buf + 12); 321 header->term_section = bfd_getb32 (buf + 16); 322 header->term_offset = bfd_getb32 (buf + 20); 323 header->imported_library_count = bfd_getb32 (buf + 24); 324 header->total_imported_symbol_count = bfd_getb32 (buf + 28); 325 header->reloc_section_count = bfd_getb32 (buf + 32); 326 header->reloc_instr_offset = bfd_getb32 (buf + 36); 327 header->loader_strings_offset = bfd_getb32 (buf + 40); 328 header->export_hash_offset = bfd_getb32 (buf + 44); 329 header->export_hash_table_power = bfd_getb32 (buf + 48); 330 header->exported_symbol_count = bfd_getb32 (buf + 52); 331 332 return 0; 333 } 334 335 int 336 bfd_pef_parse_imported_library (bfd *abfd ATTRIBUTE_UNUSED, 337 unsigned char *buf, 338 size_t len, 339 bfd_pef_imported_library *header) 340 { 341 BFD_ASSERT (len == 24); 342 343 header->name_offset = bfd_getb32 (buf); 344 header->old_implementation_version = bfd_getb32 (buf + 4); 345 header->current_version = bfd_getb32 (buf + 8); 346 header->imported_symbol_count = bfd_getb32 (buf + 12); 347 header->first_imported_symbol = bfd_getb32 (buf + 16); 348 header->options = buf[20]; 349 header->reserved_a = buf[21]; 350 header->reserved_b = bfd_getb16 (buf + 22); 351 352 return 0; 353 } 354 355 int 356 bfd_pef_parse_imported_symbol (bfd *abfd ATTRIBUTE_UNUSED, 357 unsigned char *buf, 358 size_t len, 359 bfd_pef_imported_symbol *symbol) 360 { 361 unsigned long value; 362 363 BFD_ASSERT (len == 4); 364 365 value = bfd_getb32 (buf); 366 symbol->symbol_class = value >> 24; 367 symbol->name = value & 0x00ffffff; 368 369 return 0; 370 } 371 372 int 373 bfd_pef_scan_section (bfd *abfd, bfd_pef_section *section) 374 { 375 unsigned char buf[28]; 376 377 bfd_seek (abfd, section->header_offset, SEEK_SET); 378 if (bfd_bread ((void *) buf, 28, abfd) != 28) 379 return -1; 380 381 section->name_offset = bfd_h_get_32 (abfd, buf); 382 section->default_address = bfd_h_get_32 (abfd, buf + 4); 383 section->total_length = bfd_h_get_32 (abfd, buf + 8); 384 section->unpacked_length = bfd_h_get_32 (abfd, buf + 12); 385 section->container_length = bfd_h_get_32 (abfd, buf + 16); 386 section->container_offset = bfd_h_get_32 (abfd, buf + 20); 387 section->section_kind = buf[24]; 388 section->share_kind = buf[25]; 389 section->alignment = buf[26]; 390 section->reserved = buf[27]; 391 392 section->bfd_section = bfd_pef_make_bfd_section (abfd, section); 393 if (section->bfd_section == NULL) 394 return -1; 395 396 return 0; 397 } 398 399 void 400 bfd_pef_print_loader_header (bfd *abfd ATTRIBUTE_UNUSED, 401 bfd_pef_loader_header *header, 402 FILE *file) 403 { 404 fprintf (file, "main_section: %ld\n", header->main_section); 405 fprintf (file, "main_offset: %lu\n", header->main_offset); 406 fprintf (file, "init_section: %ld\n", header->init_section); 407 fprintf (file, "init_offset: %lu\n", header->init_offset); 408 fprintf (file, "term_section: %ld\n", header->term_section); 409 fprintf (file, "term_offset: %lu\n", header->term_offset); 410 fprintf (file, "imported_library_count: %lu\n", 411 header->imported_library_count); 412 fprintf (file, "total_imported_symbol_count: %lu\n", 413 header->total_imported_symbol_count); 414 fprintf (file, "reloc_section_count: %lu\n", header->reloc_section_count); 415 fprintf (file, "reloc_instr_offset: %lu\n", header->reloc_instr_offset); 416 fprintf (file, "loader_strings_offset: %lu\n", 417 header->loader_strings_offset); 418 fprintf (file, "export_hash_offset: %lu\n", header->export_hash_offset); 419 fprintf (file, "export_hash_table_power: %lu\n", 420 header->export_hash_table_power); 421 fprintf (file, "exported_symbol_count: %lu\n", 422 header->exported_symbol_count); 423 } 424 425 int 426 bfd_pef_print_loader_section (bfd *abfd, FILE *file) 427 { 428 bfd_pef_loader_header header; 429 asection *loadersec = NULL; 430 unsigned char *loaderbuf = NULL; 431 size_t loaderlen = 0; 432 433 loadersec = bfd_get_section_by_name (abfd, "loader"); 434 if (loadersec == NULL) 435 return -1; 436 437 loaderlen = loadersec->size; 438 loaderbuf = bfd_malloc (loaderlen); 439 440 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0 441 || bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen 442 || loaderlen < 56 443 || bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header) < 0) 444 { 445 free (loaderbuf); 446 return -1; 447 } 448 449 bfd_pef_print_loader_header (abfd, &header, file); 450 return 0; 451 } 452 453 int 454 bfd_pef_scan_start_address (bfd *abfd) 455 { 456 bfd_pef_loader_header header; 457 asection *section; 458 459 asection *loadersec = NULL; 460 unsigned char *loaderbuf = NULL; 461 size_t loaderlen = 0; 462 int ret; 463 464 loadersec = bfd_get_section_by_name (abfd, "loader"); 465 if (loadersec == NULL) 466 goto end; 467 468 loaderlen = loadersec->size; 469 loaderbuf = bfd_malloc (loaderlen); 470 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0) 471 goto error; 472 if (bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen) 473 goto error; 474 475 if (loaderlen < 56) 476 goto error; 477 ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header); 478 if (ret < 0) 479 goto error; 480 481 if (header.main_section < 0) 482 goto end; 483 484 for (section = abfd->sections; section != NULL; section = section->next) 485 if ((section->index + 1) == header.main_section) 486 break; 487 488 if (section == NULL) 489 goto error; 490 491 abfd->start_address = section->vma + header.main_offset; 492 493 end: 494 if (loaderbuf != NULL) 495 free (loaderbuf); 496 return 0; 497 498 error: 499 if (loaderbuf != NULL) 500 free (loaderbuf); 501 return -1; 502 } 503 504 int 505 bfd_pef_scan (abfd, header, mdata) 506 bfd *abfd; 507 bfd_pef_header *header; 508 bfd_pef_data_struct *mdata; 509 { 510 unsigned int i; 511 enum bfd_architecture cputype; 512 unsigned long cpusubtype; 513 514 mdata->header = *header; 515 516 bfd_pef_convert_architecture (header->architecture, &cputype, &cpusubtype); 517 if (cputype == bfd_arch_unknown) 518 { 519 (*_bfd_error_handler) (_("bfd_pef_scan: unknown architecture 0x%lx"), 520 header->architecture); 521 return -1; 522 } 523 bfd_set_arch_mach (abfd, cputype, cpusubtype); 524 525 mdata->header = *header; 526 527 abfd->flags = (abfd->xvec->object_flags 528 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS))); 529 530 if (header->section_count != 0) 531 { 532 mdata->sections = bfd_alloc (abfd, header->section_count * sizeof (bfd_pef_section)); 533 534 if (mdata->sections == NULL) 535 return -1; 536 537 for (i = 0; i < header->section_count; i++) 538 { 539 bfd_pef_section *cur = &mdata->sections[i]; 540 cur->header_offset = 40 + (i * 28); 541 if (bfd_pef_scan_section (abfd, cur) < 0) 542 return -1; 543 } 544 } 545 546 if (bfd_pef_scan_start_address (abfd) < 0) 547 return -1; 548 549 abfd->tdata.pef_data = mdata; 550 551 return 0; 552 } 553 554 static int 555 bfd_pef_read_header (bfd *abfd, bfd_pef_header *header) 556 { 557 unsigned char buf[40]; 558 559 bfd_seek (abfd, 0, SEEK_SET); 560 561 if (bfd_bread ((void *) buf, 40, abfd) != 40) 562 return -1; 563 564 header->tag1 = bfd_getb32 (buf); 565 header->tag2 = bfd_getb32 (buf + 4); 566 header->architecture = bfd_getb32 (buf + 8); 567 header->format_version = bfd_getb32 (buf + 12); 568 header->timestamp = bfd_getb32 (buf + 16); 569 header->old_definition_version = bfd_getb32 (buf + 20); 570 header->old_implementation_version = bfd_getb32 (buf + 24); 571 header->current_version = bfd_getb32 (buf + 28); 572 header->section_count = bfd_getb32 (buf + 32) + 1; 573 header->instantiated_section_count = bfd_getb32 (buf + 34); 574 header->reserved = bfd_getb32 (buf + 36); 575 576 return 0; 577 } 578 579 static const bfd_target * 580 bfd_pef_object_p (bfd *abfd) 581 { 582 struct bfd_preserve preserve; 583 bfd_pef_header header; 584 585 preserve.marker = NULL; 586 if (bfd_pef_read_header (abfd, &header) != 0) 587 goto wrong; 588 589 if (header.tag1 != BFD_PEF_TAG1 || header.tag2 != BFD_PEF_TAG2) 590 goto wrong; 591 592 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_pef_data_struct)); 593 if (preserve.marker == NULL 594 || !bfd_preserve_save (abfd, &preserve)) 595 goto fail; 596 597 if (bfd_pef_scan (abfd, &header, 598 (bfd_pef_data_struct *) preserve.marker) != 0) 599 goto wrong; 600 601 bfd_preserve_finish (abfd, &preserve); 602 return abfd->xvec; 603 604 wrong: 605 bfd_set_error (bfd_error_wrong_format); 606 607 fail: 608 if (preserve.marker != NULL) 609 bfd_preserve_restore (abfd, &preserve); 610 return NULL; 611 } 612 613 static int 614 bfd_pef_parse_traceback_tables (bfd *abfd, 615 asection *sec, 616 unsigned char *buf, 617 size_t len, 618 long *nsym, 619 asymbol **csym) 620 { 621 char *name; 622 623 asymbol function; 624 asymbol traceback; 625 626 const char *const tbprefix = "__traceback_"; 627 size_t tbnamelen; 628 629 size_t pos = 0; 630 unsigned long count = 0; 631 int ret; 632 633 for (;;) 634 { 635 /* We're reading symbols two at a time. */ 636 if (csym && ((csym[count] == NULL) || (csym[count + 1] == NULL))) 637 break; 638 639 pos += 3; 640 pos -= (pos % 4); 641 642 while ((pos + 4) <= len) 643 { 644 if (bfd_getb32 (buf + pos) == 0) 645 break; 646 pos += 4; 647 } 648 649 if ((pos + 4) > len) 650 break; 651 652 ret = bfd_pef_parse_traceback_table (abfd, sec, buf, len, pos + 4, 653 &function, 0); 654 if (ret < 0) 655 { 656 /* Skip over 0x0L to advance to next possible traceback table. */ 657 pos += 4; 658 continue; 659 } 660 661 BFD_ASSERT (function.name != NULL); 662 663 /* Don't bother to compute the name if we are just 664 counting symbols. */ 665 if (csym) 666 { 667 tbnamelen = strlen (tbprefix) + strlen (function.name); 668 name = bfd_alloc (abfd, tbnamelen + 1); 669 if (name == NULL) 670 { 671 bfd_release (abfd, (void *) function.name); 672 function.name = NULL; 673 break; 674 } 675 snprintf (name, tbnamelen + 1, "%s%s", tbprefix, function.name); 676 traceback.name = name; 677 traceback.value = pos; 678 traceback.the_bfd = abfd; 679 traceback.section = sec; 680 traceback.flags = 0; 681 traceback.udata.i = ret; 682 683 *(csym[count]) = function; 684 *(csym[count + 1]) = traceback; 685 } 686 687 pos += ret; 688 count += 2; 689 } 690 691 *nsym = count; 692 return 0; 693 } 694 695 static int 696 bfd_pef_parse_function_stub (bfd *abfd ATTRIBUTE_UNUSED, 697 unsigned char *buf, 698 size_t len, 699 unsigned long *offset) 700 { 701 BFD_ASSERT (len == 24); 702 703 if ((bfd_getb32 (buf) & 0xffff0000) != 0x81820000) 704 return -1; 705 if (bfd_getb32 (buf + 4) != 0x90410014) 706 return -1; 707 if (bfd_getb32 (buf + 8) != 0x800c0000) 708 return -1; 709 if (bfd_getb32 (buf + 12) != 0x804c0004) 710 return -1; 711 if (bfd_getb32 (buf + 16) != 0x7c0903a6) 712 return -1; 713 if (bfd_getb32 (buf + 20) != 0x4e800420) 714 return -1; 715 716 if (offset != NULL) 717 *offset = (bfd_getb32 (buf) & 0x0000ffff) / 4; 718 719 return 0; 720 } 721 722 static int 723 bfd_pef_parse_function_stubs (bfd *abfd, 724 asection *codesec, 725 unsigned char *codebuf, 726 size_t codelen, 727 unsigned char *loaderbuf, 728 size_t loaderlen, 729 unsigned long *nsym, 730 asymbol **csym) 731 { 732 const char *const sprefix = "__stub_"; 733 size_t codepos = 0; 734 unsigned long count = 0; 735 bfd_pef_loader_header header; 736 bfd_pef_imported_library *libraries = NULL; 737 bfd_pef_imported_symbol *imports = NULL; 738 unsigned long i; 739 int ret; 740 741 if (loaderlen < 56) 742 goto error; 743 744 ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header); 745 if (ret < 0) 746 goto error; 747 748 libraries = bfd_malloc 749 (header.imported_library_count * sizeof (bfd_pef_imported_library)); 750 imports = bfd_malloc 751 (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol)); 752 753 if (loaderlen < (56 + (header.imported_library_count * 24))) 754 goto error; 755 for (i = 0; i < header.imported_library_count; i++) 756 { 757 ret = bfd_pef_parse_imported_library 758 (abfd, loaderbuf + 56 + (i * 24), 24, &libraries[i]); 759 if (ret < 0) 760 goto error; 761 } 762 763 if (loaderlen < (56 + (header.imported_library_count * 24) 764 + (header.total_imported_symbol_count * 4))) 765 goto error; 766 for (i = 0; i < header.total_imported_symbol_count; i++) 767 { 768 ret = (bfd_pef_parse_imported_symbol 769 (abfd, 770 loaderbuf + 56 + (header.imported_library_count * 24) + (i * 4), 771 4, &imports[i])); 772 if (ret < 0) 773 goto error; 774 } 775 776 codepos = 0; 777 778 for (;;) 779 { 780 asymbol sym; 781 const char *symname; 782 char *name; 783 unsigned long sym_index; 784 785 if (csym && (csym[count] == NULL)) 786 break; 787 788 codepos += 3; 789 codepos -= (codepos % 4); 790 791 while ((codepos + 4) <= codelen) 792 { 793 if ((bfd_getb32 (codebuf + codepos) & 0xffff0000) == 0x81820000) 794 break; 795 codepos += 4; 796 } 797 798 if ((codepos + 4) > codelen) 799 break; 800 801 ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &sym_index); 802 if (ret < 0) 803 { 804 codepos += 24; 805 continue; 806 } 807 808 if (sym_index >= header.total_imported_symbol_count) 809 { 810 codepos += 24; 811 continue; 812 } 813 814 { 815 size_t max, namelen; 816 const char *s; 817 818 if (loaderlen < (header.loader_strings_offset + imports[sym_index].name)) 819 goto error; 820 821 max = loaderlen - (header.loader_strings_offset + imports[sym_index].name); 822 symname = (char *) loaderbuf; 823 symname += header.loader_strings_offset + imports[sym_index].name; 824 namelen = 0; 825 for (s = symname; s < (symname + max); s++) 826 { 827 if (*s == '\0') 828 break; 829 if (! ISPRINT (*s)) 830 goto error; 831 namelen++; 832 } 833 if (*s != '\0') 834 goto error; 835 836 name = bfd_alloc (abfd, strlen (sprefix) + namelen + 1); 837 if (name == NULL) 838 break; 839 840 snprintf (name, strlen (sprefix) + namelen + 1, "%s%s", 841 sprefix, symname); 842 sym.name = name; 843 } 844 845 sym.value = codepos; 846 sym.the_bfd = abfd; 847 sym.section = codesec; 848 sym.flags = 0; 849 sym.udata.i = 0; 850 851 codepos += 24; 852 853 if (csym != NULL) 854 *(csym[count]) = sym; 855 856 count++; 857 } 858 859 goto end; 860 861 end: 862 if (libraries != NULL) 863 free (libraries); 864 if (imports != NULL) 865 free (imports); 866 *nsym = count; 867 return 0; 868 869 error: 870 if (libraries != NULL) 871 free (libraries); 872 if (imports != NULL) 873 free (imports); 874 *nsym = count; 875 return -1; 876 } 877 878 static long 879 bfd_pef_parse_symbols (bfd *abfd, asymbol **csym) 880 { 881 unsigned long count = 0; 882 883 asection *codesec = NULL; 884 unsigned char *codebuf = NULL; 885 size_t codelen = 0; 886 887 asection *loadersec = NULL; 888 unsigned char *loaderbuf = NULL; 889 size_t loaderlen = 0; 890 891 codesec = bfd_get_section_by_name (abfd, "code"); 892 if (codesec != NULL) 893 { 894 codelen = codesec->size; 895 codebuf = bfd_malloc (codelen); 896 if (bfd_seek (abfd, codesec->filepos, SEEK_SET) < 0) 897 goto end; 898 if (bfd_bread ((void *) codebuf, codelen, abfd) != codelen) 899 goto end; 900 } 901 902 loadersec = bfd_get_section_by_name (abfd, "loader"); 903 if (loadersec != NULL) 904 { 905 loaderlen = loadersec->size; 906 loaderbuf = bfd_malloc (loaderlen); 907 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0) 908 goto end; 909 if (bfd_bread ((void *) loaderbuf, loaderlen, abfd) != loaderlen) 910 goto end; 911 } 912 913 count = 0; 914 if (codesec != NULL) 915 { 916 long ncount = 0; 917 bfd_pef_parse_traceback_tables (abfd, codesec, codebuf, codelen, 918 &ncount, csym); 919 count += ncount; 920 } 921 922 if ((codesec != NULL) && (loadersec != NULL)) 923 { 924 unsigned long ncount = 0; 925 bfd_pef_parse_function_stubs 926 (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, &ncount, 927 (csym != NULL) ? (csym + count) : NULL); 928 count += ncount; 929 } 930 931 if (csym != NULL) 932 csym[count] = NULL; 933 934 end: 935 if (codebuf != NULL) 936 free (codebuf); 937 938 if (loaderbuf != NULL) 939 free (loaderbuf); 940 941 return count; 942 } 943 944 static long 945 bfd_pef_count_symbols (bfd *abfd) 946 { 947 return bfd_pef_parse_symbols (abfd, NULL); 948 } 949 950 static long 951 bfd_pef_get_symtab_upper_bound (bfd *abfd) 952 { 953 long nsyms = bfd_pef_count_symbols (abfd); 954 955 if (nsyms < 0) 956 return nsyms; 957 return ((nsyms + 1) * sizeof (asymbol *)); 958 } 959 960 static long 961 bfd_pef_canonicalize_symtab (bfd *abfd, asymbol **alocation) 962 { 963 long i; 964 asymbol *syms; 965 long ret; 966 long nsyms = bfd_pef_count_symbols (abfd); 967 968 if (nsyms < 0) 969 return nsyms; 970 971 syms = bfd_alloc (abfd, nsyms * sizeof (asymbol)); 972 if (syms == NULL) 973 return -1; 974 975 for (i = 0; i < nsyms; i++) 976 alocation[i] = &syms[i]; 977 978 alocation[nsyms] = NULL; 979 980 ret = bfd_pef_parse_symbols (abfd, alocation); 981 if (ret != nsyms) 982 return 0; 983 984 return ret; 985 } 986 987 #define bfd_pef_make_empty_symbol _bfd_generic_make_empty_symbol 988 989 static void 990 bfd_pef_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED, 991 asymbol *symbol, 992 symbol_info *ret) 993 { 994 bfd_symbol_info (symbol, ret); 995 } 996 997 static int 998 bfd_pef_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, 999 struct bfd_link_info *info ATTRIBUTE_UNUSED) 1000 { 1001 return 0; 1002 } 1003 1004 const bfd_target pef_vec = 1005 { 1006 "pef", /* Name. */ 1007 bfd_target_pef_flavour, /* Flavour. */ 1008 BFD_ENDIAN_BIG, /* Byteorder. */ 1009 BFD_ENDIAN_BIG, /* Header_byteorder. */ 1010 (HAS_RELOC | EXEC_P | /* Object flags. */ 1011 HAS_LINENO | HAS_DEBUG | 1012 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), 1013 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA 1014 | SEC_ROM | SEC_HAS_CONTENTS), /* Section_flags. */ 1015 0, /* Symbol_leading_char. */ 1016 ' ', /* AR_pad_char. */ 1017 16, /* AR_max_namelen. */ 1018 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1019 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1020 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 1021 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1022 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1023 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 1024 { /* bfd_check_format. */ 1025 _bfd_dummy_target, 1026 bfd_pef_object_p, /* bfd_check_format. */ 1027 _bfd_dummy_target, 1028 _bfd_dummy_target, 1029 }, 1030 { /* bfd_set_format. */ 1031 bfd_false, 1032 bfd_pef_mkobject, 1033 bfd_false, 1034 bfd_false, 1035 }, 1036 { /* bfd_write_contents. */ 1037 bfd_false, 1038 bfd_true, 1039 bfd_false, 1040 bfd_false, 1041 }, 1042 1043 BFD_JUMP_TABLE_GENERIC (bfd_pef), 1044 BFD_JUMP_TABLE_COPY (_bfd_generic), 1045 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1046 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 1047 BFD_JUMP_TABLE_SYMBOLS (bfd_pef), 1048 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 1049 BFD_JUMP_TABLE_WRITE (bfd_pef), 1050 BFD_JUMP_TABLE_LINK (bfd_pef), 1051 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1052 1053 NULL, 1054 1055 NULL 1056 }; 1057 1058 #define bfd_pef_xlib_close_and_cleanup _bfd_generic_close_and_cleanup 1059 #define bfd_pef_xlib_bfd_free_cached_info _bfd_generic_bfd_free_cached_info 1060 #define bfd_pef_xlib_new_section_hook _bfd_generic_new_section_hook 1061 #define bfd_pef_xlib_get_section_contents _bfd_generic_get_section_contents 1062 #define bfd_pef_xlib_set_section_contents _bfd_generic_set_section_contents 1063 #define bfd_pef_xlib_get_section_contents_in_window _bfd_generic_get_section_contents_in_window 1064 #define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window 1065 1066 static int 1067 bfd_pef_xlib_read_header (bfd *abfd, bfd_pef_xlib_header *header) 1068 { 1069 unsigned char buf[76]; 1070 1071 bfd_seek (abfd, 0, SEEK_SET); 1072 1073 if (bfd_bread ((void *) buf, 76, abfd) != 76) 1074 return -1; 1075 1076 header->tag1 = bfd_getb32 (buf); 1077 header->tag2 = bfd_getb32 (buf + 4); 1078 header->current_format = bfd_getb32 (buf + 8); 1079 header->container_strings_offset = bfd_getb32 (buf + 12); 1080 header->export_hash_offset = bfd_getb32 (buf + 16); 1081 header->export_key_offset = bfd_getb32 (buf + 20); 1082 header->export_symbol_offset = bfd_getb32 (buf + 24); 1083 header->export_names_offset = bfd_getb32 (buf + 28); 1084 header->export_hash_table_power = bfd_getb32 (buf + 32); 1085 header->exported_symbol_count = bfd_getb32 (buf + 36); 1086 header->frag_name_offset = bfd_getb32 (buf + 40); 1087 header->frag_name_length = bfd_getb32 (buf + 44); 1088 header->dylib_path_offset = bfd_getb32 (buf + 48); 1089 header->dylib_path_length = bfd_getb32 (buf + 52); 1090 header->cpu_family = bfd_getb32 (buf + 56); 1091 header->cpu_model = bfd_getb32 (buf + 60); 1092 header->date_time_stamp = bfd_getb32 (buf + 64); 1093 header->current_version = bfd_getb32 (buf + 68); 1094 header->old_definition_version = bfd_getb32 (buf + 72); 1095 header->old_implementation_version = bfd_getb32 (buf + 76); 1096 1097 return 0; 1098 } 1099 1100 static int 1101 bfd_pef_xlib_scan (bfd *abfd, bfd_pef_xlib_header *header) 1102 { 1103 bfd_pef_xlib_data_struct *mdata = NULL; 1104 1105 mdata = bfd_alloc (abfd, sizeof (* mdata)); 1106 if (mdata == NULL) 1107 return -1; 1108 1109 mdata->header = *header; 1110 1111 abfd->flags = (abfd->xvec->object_flags 1112 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS))); 1113 1114 abfd->tdata.pef_xlib_data = mdata; 1115 1116 return 0; 1117 } 1118 1119 static const bfd_target * 1120 bfd_pef_xlib_object_p (bfd *abfd) 1121 { 1122 struct bfd_preserve preserve; 1123 bfd_pef_xlib_header header; 1124 1125 if (bfd_pef_xlib_read_header (abfd, &header) != 0) 1126 { 1127 bfd_set_error (bfd_error_wrong_format); 1128 return NULL; 1129 } 1130 1131 if ((header.tag1 != BFD_PEF_XLIB_TAG1) 1132 || ((header.tag2 != BFD_PEF_VLIB_TAG2) 1133 && (header.tag2 != BFD_PEF_BLIB_TAG2))) 1134 { 1135 bfd_set_error (bfd_error_wrong_format); 1136 return NULL; 1137 } 1138 1139 if (! bfd_preserve_save (abfd, &preserve)) 1140 { 1141 bfd_set_error (bfd_error_wrong_format); 1142 return NULL; 1143 } 1144 1145 if (bfd_pef_xlib_scan (abfd, &header) != 0) 1146 { 1147 bfd_preserve_restore (abfd, &preserve); 1148 bfd_set_error (bfd_error_wrong_format); 1149 return NULL; 1150 } 1151 1152 bfd_preserve_finish (abfd, &preserve); 1153 return abfd->xvec; 1154 } 1155 1156 const bfd_target pef_xlib_vec = 1157 { 1158 "pef-xlib", /* Name. */ 1159 bfd_target_pef_xlib_flavour, /* Flavour. */ 1160 BFD_ENDIAN_BIG, /* Byteorder */ 1161 BFD_ENDIAN_BIG, /* Header_byteorder. */ 1162 (HAS_RELOC | EXEC_P | /* Object flags. */ 1163 HAS_LINENO | HAS_DEBUG | 1164 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), 1165 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA 1166 | SEC_ROM | SEC_HAS_CONTENTS),/* Section_flags. */ 1167 0, /* Symbol_leading_char. */ 1168 ' ', /* AR_pad_char. */ 1169 16, /* AR_max_namelen. */ 1170 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1171 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1172 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ 1173 bfd_getb64, bfd_getb_signed_64, bfd_putb64, 1174 bfd_getb32, bfd_getb_signed_32, bfd_putb32, 1175 bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers. */ 1176 { /* bfd_check_format. */ 1177 _bfd_dummy_target, 1178 bfd_pef_xlib_object_p, /* bfd_check_format. */ 1179 _bfd_dummy_target, 1180 _bfd_dummy_target, 1181 }, 1182 { /* bfd_set_format. */ 1183 bfd_false, 1184 bfd_pef_mkobject, 1185 bfd_false, 1186 bfd_false, 1187 }, 1188 { /* bfd_write_contents. */ 1189 bfd_false, 1190 bfd_true, 1191 bfd_false, 1192 bfd_false, 1193 }, 1194 1195 BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib), 1196 BFD_JUMP_TABLE_COPY (_bfd_generic), 1197 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1198 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive), 1199 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols), 1200 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), 1201 BFD_JUMP_TABLE_WRITE (_bfd_nowrite), 1202 BFD_JUMP_TABLE_LINK (_bfd_nolink), 1203 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1204 1205 NULL, 1206 1207 NULL 1208 }; 1209