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