00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "safe-ctype.h"
00026
00027 #include "pef.h"
00028 #include "pef-traceback.h"
00029
00030 #include "bfd.h"
00031 #include "sysdep.h"
00032 #include "libbfd.h"
00033
00034 #include "libiberty.h"
00035
00036 #ifndef BFD_IO_FUNCS
00037 #define BFD_IO_FUNCS 0
00038 #endif
00039
00040 #define bfd_pef_close_and_cleanup _bfd_generic_close_and_cleanup
00041 #define bfd_pef_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
00042 #define bfd_pef_new_section_hook _bfd_generic_new_section_hook
00043 #define bfd_pef_bfd_is_local_label_name bfd_generic_is_local_label_name
00044 #define bfd_pef_bfd_is_target_special_symbol ((bfd_boolean (*) (bfd *, asymbol *)) bfd_false)
00045 #define bfd_pef_get_lineno _bfd_nosymbols_get_lineno
00046 #define bfd_pef_find_nearest_line _bfd_nosymbols_find_nearest_line
00047 #define bfd_pef_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
00048 #define bfd_pef_read_minisymbols _bfd_generic_read_minisymbols
00049 #define bfd_pef_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
00050 #define bfd_pef_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
00051 #define bfd_pef_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
00052 #define bfd_pef_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
00053 #define bfd_pef_set_arch_mach _bfd_generic_set_arch_mach
00054 #define bfd_pef_get_section_contents _bfd_generic_get_section_contents
00055 #define bfd_pef_set_section_contents _bfd_generic_set_section_contents
00056 #define bfd_pef_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
00057 #define bfd_pef_bfd_relax_section bfd_generic_relax_section
00058 #define bfd_pef_bfd_gc_sections bfd_generic_gc_sections
00059 #define bfd_pef_bfd_merge_sections bfd_generic_merge_sections
00060 #define bfd_pef_bfd_is_group_section bfd_generic_is_group_section
00061 #define bfd_pef_bfd_discard_group bfd_generic_discard_group
00062 #define bfd_pef_section_already_linked _bfd_generic_section_already_linked
00063 #define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
00064 #define bfd_pef_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
00065 #define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols
00066 #define bfd_pef_bfd_link_just_syms _bfd_generic_link_just_syms
00067 #define bfd_pef_bfd_final_link _bfd_generic_final_link
00068 #define bfd_pef_bfd_link_split_section _bfd_generic_link_split_section
00069 #define bfd_pef_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
00070
00071 static void bfd_pef_print_symbol PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
00072 static void bfd_pef_convert_architecture PARAMS ((unsigned long, enum bfd_architecture *, unsigned long *));
00073 static bfd_boolean bfd_pef_mkobject PARAMS ((bfd *));
00074 static int bfd_pef_parse_traceback_table PARAMS ((bfd *, asection *, unsigned char *, size_t, size_t, asymbol *, FILE *));
00075 static const char *bfd_pef_section_name PARAMS ((bfd_pef_section *));
00076 static unsigned long bfd_pef_section_flags PARAMS ((bfd_pef_section *));
00077 static asection *bfd_pef_make_bfd_section PARAMS ((bfd *, bfd_pef_section *));
00078 static int bfd_pef_read_header PARAMS ((bfd *, bfd_pef_header *));
00079 static const bfd_target *bfd_pef_object_p PARAMS ((bfd *));
00080 static int bfd_pef_parse_traceback_tables PARAMS ((bfd *, asection *, unsigned char *, size_t, long *, asymbol **));
00081 static int bfd_pef_parse_function_stub PARAMS ((bfd *, unsigned char *, size_t, unsigned long *));
00082 static int bfd_pef_parse_function_stubs PARAMS ((bfd *, asection *, unsigned char *, size_t, unsigned char *, size_t, unsigned long *, asymbol **));
00083 static long bfd_pef_parse_symbols PARAMS ((bfd *, asymbol **));
00084 static long bfd_pef_count_symbols PARAMS ((bfd *));
00085 static long bfd_pef_get_symtab_upper_bound PARAMS ((bfd *));
00086 static long bfd_pef_canonicalize_symtab PARAMS ((bfd *, asymbol **));
00087 static asymbol *bfd_pef_make_empty_symbol PARAMS ((bfd *));
00088 static void bfd_pef_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
00089 static int bfd_pef_sizeof_headers PARAMS ((bfd *, bfd_boolean));
00090 static int bfd_pef_xlib_read_header PARAMS ((bfd *, bfd_pef_xlib_header *));
00091 static int bfd_pef_xlib_scan PARAMS ((bfd *, bfd_pef_xlib_header *));
00092 static const bfd_target *bfd_pef_xlib_object_p PARAMS ((bfd *));
00093
00094 static void
00095 bfd_pef_print_symbol (abfd, afile, symbol, how)
00096 bfd *abfd;
00097 PTR afile;
00098 asymbol *symbol;
00099 bfd_print_symbol_type how;
00100 {
00101 FILE *file = (FILE *) afile;
00102
00103 switch (how)
00104 {
00105 case bfd_print_symbol_name:
00106 fprintf (file, "%s", symbol->name);
00107 break;
00108 default:
00109 bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
00110 fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
00111 if (strncmp (symbol->name, "__traceback_", strlen ("__traceback_")) == 0)
00112 {
00113 unsigned char *buf = alloca (symbol->udata.i);
00114 size_t offset = symbol->value + 4;
00115 size_t len = symbol->udata.i;
00116 int ret;
00117
00118 bfd_get_section_contents (abfd, symbol->section, buf, offset, len);
00119 ret = bfd_pef_parse_traceback_table (abfd, symbol->section, buf,
00120 len, 0, NULL, file);
00121 if (ret < 0)
00122 fprintf (file, " [ERROR]");
00123 }
00124 }
00125 }
00126
00127 static void
00128 bfd_pef_convert_architecture (architecture, type, subtype)
00129 unsigned long architecture;
00130 enum bfd_architecture *type;
00131 unsigned long *subtype;
00132 {
00133 const unsigned long ARCH_POWERPC = 0x70777063;
00134 const unsigned long ARCH_M68K = 0x6d36386b;
00135
00136 *subtype = bfd_arch_unknown;
00137 *type = bfd_arch_unknown;
00138
00139 if (architecture == ARCH_POWERPC)
00140 *type = bfd_arch_powerpc;
00141 else if (architecture == ARCH_M68K)
00142 *type = bfd_arch_m68k;
00143 }
00144
00145 static bfd_boolean
00146 bfd_pef_mkobject (abfd)
00147 bfd *abfd ATTRIBUTE_UNUSED;
00148 {
00149 return TRUE;
00150 }
00151
00152 static int
00153 bfd_pef_parse_traceback_table (abfd, section, buf, len, pos, sym, file)
00154 bfd *abfd;
00155 asection *section;
00156 unsigned char *buf;
00157 size_t len;
00158 size_t pos;
00159 asymbol *sym;
00160 FILE *file;
00161 {
00162 struct traceback_table table;
00163 size_t offset;
00164 const char *s;
00165 asymbol tmpsymbol;
00166
00167 if (sym == NULL)
00168 sym = &tmpsymbol;
00169
00170 sym->name = NULL;
00171 sym->value = 0;
00172 sym->the_bfd = abfd;
00173 sym->section = section;
00174 sym->flags = 0;
00175 sym->udata.i = 0;
00176
00177
00178
00179 if ((pos + 8) > len)
00180 return -1;
00181 memcpy (&table, buf + pos, 8);
00182
00183
00184
00185
00186 if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS))
00187 return -1;
00188
00189 if (! (table.flags2 & TB_NAME_PRESENT))
00190 return -1;
00191
00192 if (! table.flags1 & TB_HAS_TBOFF)
00193 return -1;
00194
00195 offset = 8;
00196
00197 if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams))
00198 offset += 4;
00199
00200 if (table.flags1 & TB_HAS_TBOFF)
00201 {
00202 struct traceback_table_tboff off;
00203
00204 if ((pos + offset + 4) > len)
00205 return -1;
00206 off.tb_offset = bfd_getb32 (buf + pos + offset);
00207 offset += 4;
00208
00209
00210
00211
00212 if (file != NULL)
00213 fprintf (file, " [offset = 0x%lx]", off.tb_offset);
00214
00215 if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset)))
00216 return -1;
00217
00218 sym->value = pos - off.tb_offset - 4;
00219 }
00220
00221 if (table.flags2 & TB_INT_HNDL)
00222 offset += 4;
00223
00224 if (table.flags1 & TB_HAS_CTL)
00225 {
00226 struct traceback_table_anchors anchors;
00227
00228 if ((pos + offset + 4) > len)
00229 return -1;
00230 anchors.ctl_info = bfd_getb32 (buf + pos + offset);
00231 offset += 4;
00232
00233 if (anchors.ctl_info > 1024)
00234 return -1;
00235
00236 offset += anchors.ctl_info * 4;
00237 }
00238
00239 if (table.flags2 & TB_NAME_PRESENT)
00240 {
00241 struct traceback_table_routine name;
00242 char *namebuf;
00243
00244 if ((pos + offset + 2) > len)
00245 return -1;
00246 name.name_len = bfd_getb16 (buf + pos + offset);
00247 offset += 2;
00248
00249 if (name.name_len > 4096)
00250 return -1;
00251
00252 if ((pos + offset + name.name_len) > len)
00253 return -1;
00254
00255 namebuf = (char *) bfd_alloc (abfd, name.name_len + 1);
00256 if (namebuf == NULL)
00257 return -1;
00258
00259 memcpy (namebuf, buf + pos + offset, name.name_len);
00260 namebuf[name.name_len] = '\0';
00261
00262
00263 if (namebuf[0] == '.')
00264 memmove (namebuf, namebuf + 1, name.name_len + 1);
00265
00266 sym->name = namebuf;
00267
00268 for (s = sym->name; (*s != '\0'); s++)
00269 if (! ISPRINT (*s))
00270 return -1;
00271
00272 offset += name.name_len;
00273 }
00274
00275 if (table.flags2 & TB_USES_ALLOCA)
00276 offset += 4;
00277
00278 if (table.flags4 & TB_HAS_VEC_INFO)
00279 offset += 4;
00280
00281 if (file != NULL)
00282 fprintf (file, " [length = 0x%lx]", (long) offset);
00283
00284 return offset;
00285 }
00286
00287 static const char *bfd_pef_section_name (section)
00288 bfd_pef_section *section;
00289 {
00290 switch (section->section_kind)
00291 {
00292 case BFD_PEF_SECTION_CODE: return "code";
00293 case BFD_PEF_SECTION_UNPACKED_DATA: return "unpacked-data";
00294 case BFD_PEF_SECTION_PACKED_DATA: return "packed-data";
00295 case BFD_PEF_SECTION_CONSTANT: return "constant";
00296 case BFD_PEF_SECTION_LOADER: return "loader";
00297 case BFD_PEF_SECTION_DEBUG: return "debug";
00298 case BFD_PEF_SECTION_EXEC_DATA: return "exec-data";
00299 case BFD_PEF_SECTION_EXCEPTION: return "exception";
00300 case BFD_PEF_SECTION_TRACEBACK: return "traceback";
00301 default: return "unknown";
00302 }
00303 }
00304
00305 static unsigned long bfd_pef_section_flags (section)
00306 bfd_pef_section *section;
00307 {
00308 switch (section->section_kind)
00309 {
00310 case BFD_PEF_SECTION_CODE:
00311 return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
00312 case BFD_PEF_SECTION_UNPACKED_DATA:
00313 case BFD_PEF_SECTION_PACKED_DATA:
00314 case BFD_PEF_SECTION_CONSTANT:
00315 case BFD_PEF_SECTION_LOADER:
00316 case BFD_PEF_SECTION_DEBUG:
00317 case BFD_PEF_SECTION_EXEC_DATA:
00318 case BFD_PEF_SECTION_EXCEPTION:
00319 case BFD_PEF_SECTION_TRACEBACK:
00320 default:
00321 return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
00322 }
00323 }
00324
00325 static asection *
00326 bfd_pef_make_bfd_section (abfd, section)
00327 bfd *abfd;
00328 bfd_pef_section *section;
00329 {
00330 asection *bfdsec;
00331 const char *name = bfd_pef_section_name (section);
00332
00333 bfdsec = bfd_make_section_anyway (abfd, name);
00334 if (bfdsec == NULL)
00335 return NULL;
00336
00337 bfdsec->vma = section->default_address + section->container_offset;
00338 bfdsec->lma = section->default_address + section->container_offset;
00339 bfdsec->size = section->container_length;
00340 bfdsec->filepos = section->container_offset;
00341 bfdsec->alignment_power = section->alignment;
00342
00343 bfdsec->flags = bfd_pef_section_flags (section);
00344
00345 return bfdsec;
00346 }
00347
00348 int bfd_pef_parse_loader_header (abfd, buf, len, header)
00349 bfd *abfd ATTRIBUTE_UNUSED;
00350 unsigned char *buf;
00351 size_t len;
00352 bfd_pef_loader_header *header;
00353 {
00354 BFD_ASSERT (len == 56);
00355
00356 header->main_section = bfd_getb32 (buf);
00357 header->main_offset = bfd_getb32 (buf + 4);
00358 header->init_section = bfd_getb32 (buf + 8);
00359 header->init_offset = bfd_getb32 (buf + 12);
00360 header->term_section = bfd_getb32 (buf + 16);
00361 header->term_offset = bfd_getb32 (buf + 20);
00362 header->imported_library_count = bfd_getb32 (buf + 24);
00363 header->total_imported_symbol_count = bfd_getb32 (buf + 28);
00364 header->reloc_section_count = bfd_getb32 (buf + 32);
00365 header->reloc_instr_offset = bfd_getb32 (buf + 36);
00366 header->loader_strings_offset = bfd_getb32 (buf + 40);
00367 header->export_hash_offset = bfd_getb32 (buf + 44);
00368 header->export_hash_table_power = bfd_getb32 (buf + 48);
00369 header->exported_symbol_count = bfd_getb32 (buf + 52);
00370
00371 return 0;
00372 }
00373
00374 int bfd_pef_parse_imported_library (abfd, buf, len, header)
00375 bfd *abfd ATTRIBUTE_UNUSED;
00376 unsigned char *buf;
00377 size_t len;
00378 bfd_pef_imported_library *header;
00379 {
00380 BFD_ASSERT (len == 24);
00381
00382 header->name_offset = bfd_getb32 (buf);
00383 header->old_implementation_version = bfd_getb32 (buf + 4);
00384 header->current_version = bfd_getb32 (buf + 8);
00385 header->imported_symbol_count = bfd_getb32 (buf + 12);
00386 header->first_imported_symbol = bfd_getb32 (buf + 16);
00387 header->options = buf[20];
00388 header->reserved_a = buf[21];
00389 header->reserved_b = bfd_getb16 (buf + 22);
00390
00391 return 0;
00392 }
00393
00394 int bfd_pef_parse_imported_symbol (abfd, buf, len, symbol)
00395 bfd *abfd ATTRIBUTE_UNUSED;
00396 unsigned char *buf;
00397 size_t len;
00398 bfd_pef_imported_symbol *symbol;
00399 {
00400 unsigned long value;
00401
00402 BFD_ASSERT (len == 4);
00403
00404 value = bfd_getb32 (buf);
00405 symbol->class = value >> 24;
00406 symbol->name = value & 0x00ffffff;
00407
00408 return 0;
00409 }
00410
00411 int bfd_pef_scan_section (abfd, section)
00412 bfd *abfd;
00413 bfd_pef_section *section;
00414 {
00415 unsigned char buf[28];
00416
00417 bfd_seek (abfd, section->header_offset, SEEK_SET);
00418 if (bfd_bread ((PTR) buf, 28, abfd) != 28)
00419 return -1;
00420
00421 section->name_offset = bfd_h_get_32 (abfd, buf);
00422 section->default_address = bfd_h_get_32 (abfd, buf + 4);
00423 section->total_length = bfd_h_get_32 (abfd, buf + 8);
00424 section->unpacked_length = bfd_h_get_32 (abfd, buf + 12);
00425 section->container_length = bfd_h_get_32 (abfd, buf + 16);
00426 section->container_offset = bfd_h_get_32 (abfd, buf + 20);
00427 section->section_kind = buf[24];
00428 section->share_kind = buf[25];
00429 section->alignment = buf[26];
00430 section->reserved = buf[27];
00431
00432 section->bfd_section = bfd_pef_make_bfd_section (abfd, section);
00433 if (section->bfd_section == NULL)
00434 return -1;
00435
00436 return 0;
00437 }
00438
00439 void
00440 bfd_pef_print_loader_header (abfd, header, file)
00441 bfd *abfd ATTRIBUTE_UNUSED;
00442 bfd_pef_loader_header *header;
00443 FILE *file;
00444 {
00445 fprintf (file, "main_section: %ld\n", header->main_section);
00446 fprintf (file, "main_offset: %lu\n", header->main_offset);
00447 fprintf (file, "init_section: %ld\n", header->init_section);
00448 fprintf (file, "init_offset: %lu\n", header->init_offset);
00449 fprintf (file, "term_section: %ld\n", header->term_section);
00450 fprintf (file, "term_offset: %lu\n", header->term_offset);
00451 fprintf (file, "imported_library_count: %lu\n",
00452 header->imported_library_count);
00453 fprintf (file, "total_imported_symbol_count: %lu\n",
00454 header->total_imported_symbol_count);
00455 fprintf (file, "reloc_section_count: %lu\n", header->reloc_section_count);
00456 fprintf (file, "reloc_instr_offset: %lu\n", header->reloc_instr_offset);
00457 fprintf (file, "loader_strings_offset: %lu\n",
00458 header->loader_strings_offset);
00459 fprintf (file, "export_hash_offset: %lu\n", header->export_hash_offset);
00460 fprintf (file, "export_hash_table_power: %lu\n",
00461 header->export_hash_table_power);
00462 fprintf (file, "exported_symbol_count: %lu\n",
00463 header->exported_symbol_count);
00464 }
00465
00466 int
00467 bfd_pef_print_loader_section (abfd, file)
00468 bfd *abfd;
00469 FILE *file;
00470 {
00471 bfd_pef_loader_header header;
00472 asection *loadersec = NULL;
00473 unsigned char *loaderbuf = NULL;
00474 size_t loaderlen = 0;
00475 int ret;
00476
00477 loadersec = bfd_get_section_by_name (abfd, "loader");
00478 if (loadersec == NULL)
00479 return -1;
00480
00481 loaderlen = loadersec->size;
00482 loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
00483 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
00484 {
00485 free (loaderbuf);
00486 return -1;
00487 }
00488 if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen)
00489 {
00490 free (loaderbuf);
00491 return -1;
00492 }
00493
00494 if (loaderlen < 56)
00495 {
00496 free (loaderbuf);
00497 return -1;
00498 }
00499 ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
00500 if (ret < 0)
00501 {
00502 free (loaderbuf);
00503 return -1;
00504 }
00505
00506 bfd_pef_print_loader_header (abfd, &header, file);
00507 return 0;
00508 }
00509
00510 int
00511 bfd_pef_scan_start_address (abfd)
00512 bfd *abfd;
00513 {
00514 bfd_pef_loader_header header;
00515 asection *section;
00516
00517 asection *loadersec = NULL;
00518 unsigned char *loaderbuf = NULL;
00519 size_t loaderlen = 0;
00520 int ret;
00521
00522 loadersec = bfd_get_section_by_name (abfd, "loader");
00523 if (loadersec == NULL)
00524 goto end;
00525
00526 loaderlen = loadersec->size;
00527 loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
00528 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
00529 goto error;
00530 if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen)
00531 goto error;
00532
00533 if (loaderlen < 56)
00534 goto error;
00535 ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
00536 if (ret < 0)
00537 goto error;
00538
00539 if (header.main_section < 0)
00540 goto end;
00541
00542 for (section = abfd->sections; section != NULL; section = section->next)
00543 if ((section->index + 1) == header.main_section)
00544 break;
00545
00546 if (section == NULL)
00547 goto error;
00548
00549 abfd->start_address = section->vma + header.main_offset;
00550
00551 end:
00552 if (loaderbuf != NULL)
00553 free (loaderbuf);
00554 return 0;
00555
00556 error:
00557 if (loaderbuf != NULL)
00558 free (loaderbuf);
00559 return -1;
00560 }
00561
00562 int
00563 bfd_pef_scan (abfd, header, mdata)
00564 bfd *abfd;
00565 bfd_pef_header *header;
00566 bfd_pef_data_struct *mdata;
00567 {
00568 unsigned int i;
00569 enum bfd_architecture cputype;
00570 unsigned long cpusubtype;
00571
00572 mdata->header = *header;
00573
00574 bfd_pef_convert_architecture (header->architecture, &cputype, &cpusubtype);
00575 if (cputype == bfd_arch_unknown)
00576 {
00577 fprintf (stderr, "bfd_pef_scan: unknown architecture 0x%lx\n",
00578 header->architecture);
00579 return -1;
00580 }
00581 bfd_set_arch_mach (abfd, cputype, cpusubtype);
00582
00583 mdata->header = *header;
00584
00585 abfd->flags = (abfd->xvec->object_flags
00586 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
00587
00588 if (header->section_count != 0)
00589 {
00590 mdata->sections =
00591 ((bfd_pef_section *)
00592 bfd_alloc (abfd, header->section_count * sizeof (bfd_pef_section)));
00593
00594 if (mdata->sections == NULL)
00595 return -1;
00596
00597 for (i = 0; i < header->section_count; i++)
00598 {
00599 bfd_pef_section *cur = &mdata->sections[i];
00600 cur->header_offset = 40 + (i * 28);
00601 if (bfd_pef_scan_section (abfd, cur) < 0)
00602 return -1;
00603 }
00604 }
00605
00606 if (bfd_pef_scan_start_address (abfd) < 0)
00607 return -1;
00608
00609 abfd->tdata.pef_data = mdata;
00610
00611 return 0;
00612 }
00613
00614 static int
00615 bfd_pef_read_header (abfd, header)
00616 bfd *abfd;
00617 bfd_pef_header *header;
00618 {
00619 unsigned char buf[40];
00620
00621 bfd_seek (abfd, 0, SEEK_SET);
00622
00623 if (bfd_bread ((PTR) buf, 40, abfd) != 40)
00624 return -1;
00625
00626 header->tag1 = bfd_getb32 (buf);
00627 header->tag2 = bfd_getb32 (buf + 4);
00628 header->architecture = bfd_getb32 (buf + 8);
00629 header->format_version = bfd_getb32 (buf + 12);
00630 header->timestamp = bfd_getb32 (buf + 16);
00631 header->old_definition_version = bfd_getb32 (buf + 20);
00632 header->old_implementation_version = bfd_getb32 (buf + 24);
00633 header->current_version = bfd_getb32 (buf + 28);
00634 header->section_count = bfd_getb32 (buf + 32) + 1;
00635 header->instantiated_section_count = bfd_getb32 (buf + 34);
00636 header->reserved = bfd_getb32 (buf + 36);
00637
00638 return 0;
00639 }
00640
00641 static const bfd_target *
00642 bfd_pef_object_p (abfd)
00643 bfd *abfd;
00644 {
00645 struct bfd_preserve preserve;
00646 bfd_pef_header header;
00647
00648 preserve.marker = NULL;
00649 if (bfd_pef_read_header (abfd, &header) != 0)
00650 goto wrong;
00651
00652 if (header.tag1 != BFD_PEF_TAG1 || header.tag2 != BFD_PEF_TAG2)
00653 goto wrong;
00654
00655 preserve.marker = bfd_zalloc (abfd, sizeof (bfd_pef_data_struct));
00656 if (preserve.marker == NULL
00657 || !bfd_preserve_save (abfd, &preserve))
00658 goto fail;
00659
00660 if (bfd_pef_scan (abfd, &header,
00661 (bfd_pef_data_struct *) preserve.marker) != 0)
00662 goto wrong;
00663
00664 bfd_preserve_finish (abfd, &preserve);
00665 return abfd->xvec;
00666
00667 wrong:
00668 bfd_set_error (bfd_error_wrong_format);
00669
00670 fail:
00671 if (preserve.marker != NULL)
00672 bfd_preserve_restore (abfd, &preserve);
00673 return NULL;
00674 }
00675
00676 static int bfd_pef_parse_traceback_tables (abfd, sec, buf, len, nsym, csym)
00677 bfd *abfd;
00678 asection *sec;
00679 unsigned char *buf;
00680 size_t len;
00681 long *nsym;
00682 asymbol **csym;
00683 {
00684 char *name;
00685
00686 asymbol function;
00687 asymbol traceback;
00688
00689 const char *const tbprefix = "__traceback_";
00690 size_t tbnamelen;
00691
00692 size_t pos = 0;
00693 unsigned long count = 0;
00694 int ret;
00695
00696 for (;;)
00697 {
00698
00699 if (csym && ((csym[count] == NULL) || (csym[count + 1] == NULL)))
00700 break;
00701
00702 pos += 3;
00703 pos -= (pos % 4);
00704
00705 while ((pos + 4) <= len)
00706 {
00707 if (bfd_getb32 (buf + pos) == 0)
00708 break;
00709 pos += 4;
00710 }
00711
00712 if ((pos + 4) > len)
00713 break;
00714
00715 ret = bfd_pef_parse_traceback_table (abfd, sec, buf, len, pos + 4,
00716 &function, 0);
00717 if (ret < 0)
00718 {
00719
00720 pos += 4;
00721 continue;
00722 }
00723
00724 BFD_ASSERT (function.name != NULL);
00725
00726
00727
00728
00729 if (csym)
00730 {
00731 tbnamelen = strlen (tbprefix) + strlen (function.name);
00732 name = bfd_alloc (abfd, tbnamelen + 1);
00733 if (name == NULL)
00734 {
00735 bfd_release (abfd, (PTR) function.name);
00736 function.name = NULL;
00737 break;
00738 }
00739 snprintf (name, tbnamelen + 1, "%s%s", tbprefix, function.name);
00740 traceback.name = name;
00741 traceback.value = pos;
00742 traceback.the_bfd = abfd;
00743 traceback.section = sec;
00744 traceback.flags = 0;
00745 traceback.udata.i = ret;
00746
00747 *(csym[count]) = function;
00748 *(csym[count + 1]) = traceback;
00749 }
00750
00751 pos += ret;
00752 count += 2;
00753 }
00754
00755 *nsym = count;
00756 return 0;
00757 }
00758
00759 static int bfd_pef_parse_function_stub (abfd, buf, len, offset)
00760 bfd *abfd ATTRIBUTE_UNUSED;
00761 unsigned char *buf;
00762 size_t len;
00763 unsigned long *offset;
00764 {
00765 BFD_ASSERT (len == 24);
00766
00767 if ((bfd_getb32 (buf) & 0xffff0000) != 0x81820000)
00768 return -1;
00769 if (bfd_getb32 (buf + 4) != 0x90410014)
00770 return -1;
00771 if (bfd_getb32 (buf + 8) != 0x800c0000)
00772 return -1;
00773 if (bfd_getb32 (buf + 12) != 0x804c0004)
00774 return -1;
00775 if (bfd_getb32 (buf + 16) != 0x7c0903a6)
00776 return -1;
00777 if (bfd_getb32 (buf + 20) != 0x4e800420)
00778 return -1;
00779
00780 if (offset != NULL)
00781 *offset = (bfd_getb32 (buf) & 0x0000ffff) / 4;
00782
00783 return 0;
00784 }
00785
00786 static int bfd_pef_parse_function_stubs (abfd, codesec, codebuf, codelen,
00787 loaderbuf, loaderlen, nsym, csym)
00788 bfd *abfd;
00789 asection *codesec;
00790 unsigned char *codebuf;
00791 size_t codelen;
00792 unsigned char *loaderbuf;
00793 size_t loaderlen;
00794 unsigned long *nsym;
00795 asymbol **csym;
00796 {
00797 const char *const sprefix = "__stub_";
00798
00799 size_t codepos = 0;
00800 unsigned long count = 0;
00801
00802 bfd_pef_loader_header header;
00803 bfd_pef_imported_library *libraries = NULL;
00804 bfd_pef_imported_symbol *imports = NULL;
00805
00806 unsigned long i;
00807 int ret;
00808
00809 if (loaderlen < 56)
00810 goto error;
00811
00812 ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
00813 if (ret < 0)
00814 goto error;
00815
00816 libraries = (bfd_pef_imported_library *) bfd_malloc
00817 (header.imported_library_count * sizeof (bfd_pef_imported_library));
00818 imports = (bfd_pef_imported_symbol *) bfd_malloc
00819 (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol));
00820
00821 if (loaderlen < (56 + (header.imported_library_count * 24)))
00822 goto error;
00823 for (i = 0; i < header.imported_library_count; i++)
00824 {
00825 ret = bfd_pef_parse_imported_library
00826 (abfd, loaderbuf + 56 + (i * 24), 24, &libraries[i]);
00827 if (ret < 0)
00828 goto error;
00829 }
00830
00831 if (loaderlen < (56 + (header.imported_library_count * 24)
00832 + (header.total_imported_symbol_count * 4)))
00833 goto error;
00834 for (i = 0; i < header.total_imported_symbol_count; i++)
00835 {
00836 ret = (bfd_pef_parse_imported_symbol
00837 (abfd,
00838 loaderbuf + 56 + (header.imported_library_count * 24) + (i * 4),
00839 4, &imports[i]));
00840 if (ret < 0)
00841 goto error;
00842 }
00843
00844 codepos = 0;
00845
00846 for (;;)
00847 {
00848 asymbol sym;
00849 const char *symname;
00850 char *name;
00851 unsigned long index;
00852 int ret;
00853
00854 if (csym && (csym[count] == NULL))
00855 break;
00856
00857 codepos += 3;
00858 codepos -= (codepos % 4);
00859
00860 while ((codepos + 4) <= codelen)
00861 {
00862 if ((bfd_getb32 (codebuf + codepos) & 0xffff0000) == 0x81820000)
00863 break;
00864 codepos += 4;
00865 }
00866
00867 if ((codepos + 4) > codelen)
00868 break;
00869
00870 ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &index);
00871 if (ret < 0)
00872 {
00873 codepos += 24;
00874 continue;
00875 }
00876
00877 if (index >= header.total_imported_symbol_count)
00878 {
00879 codepos += 24;
00880 continue;
00881 }
00882
00883 {
00884 size_t max, namelen;
00885 const char *s;
00886
00887 if (loaderlen < (header.loader_strings_offset + imports[index].name))
00888 goto error;
00889
00890 max = loaderlen - (header.loader_strings_offset + imports[index].name);
00891 symname = (char *) loaderbuf;
00892 symname += header.loader_strings_offset + imports[index].name;
00893 namelen = 0;
00894 for (s = symname; s < (symname + max); s++)
00895 {
00896 if (*s == '\0')
00897 break;
00898 if (! ISPRINT (*s))
00899 goto error;
00900 namelen++;
00901 }
00902 if (*s != '\0')
00903 goto error;
00904
00905 name = bfd_alloc (abfd, strlen (sprefix) + namelen + 1);
00906 if (name == NULL)
00907 break;
00908
00909 snprintf (name, strlen (sprefix) + namelen + 1, "%s%s",
00910 sprefix, symname);
00911 sym.name = name;
00912 }
00913
00914 sym.value = codepos;
00915 sym.the_bfd = abfd;
00916 sym.section = codesec;
00917 sym.flags = 0;
00918 sym.udata.i = 0;
00919
00920 codepos += 24;
00921
00922 if (csym != NULL)
00923 *(csym[count]) = sym;
00924
00925 count++;
00926 }
00927
00928 goto end;
00929
00930 end:
00931 if (libraries != NULL)
00932 free (libraries);
00933 if (imports != NULL)
00934 free (imports);
00935 *nsym = count;
00936 return 0;
00937
00938 error:
00939 if (libraries != NULL)
00940 free (libraries);
00941 if (imports != NULL)
00942 free (imports);
00943 *nsym = count;
00944 return -1;
00945 }
00946
00947 static long bfd_pef_parse_symbols (abfd, csym)
00948 bfd *abfd;
00949 asymbol **csym;
00950 {
00951 unsigned long count = 0;
00952
00953 asection *codesec = NULL;
00954 unsigned char *codebuf = NULL;
00955 size_t codelen = 0;
00956
00957 asection *loadersec = NULL;
00958 unsigned char *loaderbuf = NULL;
00959 size_t loaderlen = 0;
00960
00961 codesec = bfd_get_section_by_name (abfd, "code");
00962 if (codesec != NULL)
00963 {
00964 codelen = codesec->size;
00965 codebuf = (unsigned char *) bfd_malloc (codelen);
00966 if (bfd_seek (abfd, codesec->filepos, SEEK_SET) < 0)
00967 goto end;
00968 if (bfd_bread ((PTR) codebuf, codelen, abfd) != codelen)
00969 goto end;
00970 }
00971
00972 loadersec = bfd_get_section_by_name (abfd, "loader");
00973 if (loadersec != NULL)
00974 {
00975 loaderlen = loadersec->size;
00976 loaderbuf = (unsigned char *) bfd_malloc (loaderlen);
00977 if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) < 0)
00978 goto end;
00979 if (bfd_bread ((PTR) loaderbuf, loaderlen, abfd) != loaderlen)
00980 goto end;
00981 }
00982
00983 count = 0;
00984 if (codesec != NULL)
00985 {
00986 long ncount = 0;
00987 bfd_pef_parse_traceback_tables (abfd, codesec, codebuf, codelen,
00988 &ncount, csym);
00989 count += ncount;
00990 }
00991
00992 if ((codesec != NULL) && (loadersec != NULL))
00993 {
00994 unsigned long ncount = 0;
00995 bfd_pef_parse_function_stubs
00996 (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, &ncount,
00997 (csym != NULL) ? (csym + count) : NULL);
00998 count += ncount;
00999 }
01000
01001 if (csym != NULL)
01002 csym[count] = NULL;
01003
01004 end:
01005 if (codebuf != NULL)
01006 free (codebuf);
01007
01008 if (loaderbuf != NULL)
01009 free (loaderbuf);
01010
01011 return count;
01012 }
01013
01014 static long
01015 bfd_pef_count_symbols (abfd)
01016 bfd *abfd;
01017 {
01018 return bfd_pef_parse_symbols (abfd, NULL);
01019 }
01020
01021 static long
01022 bfd_pef_get_symtab_upper_bound (abfd)
01023 bfd *abfd;
01024 {
01025 long nsyms = bfd_pef_count_symbols (abfd);
01026 if (nsyms < 0)
01027 return nsyms;
01028 return ((nsyms + 1) * sizeof (asymbol *));
01029 }
01030
01031 static long
01032 bfd_pef_canonicalize_symtab (abfd, alocation)
01033 bfd *abfd;
01034 asymbol **alocation;
01035 {
01036 long i;
01037 asymbol *syms;
01038 long ret;
01039
01040 long nsyms = bfd_pef_count_symbols (abfd);
01041 if (nsyms < 0)
01042 return nsyms;
01043
01044 syms = bfd_alloc (abfd, nsyms * sizeof (asymbol));
01045 if (syms == NULL)
01046 return -1;
01047
01048 for (i = 0; i < nsyms; i++)
01049 alocation[i] = &syms[i];
01050
01051 alocation[nsyms] = NULL;
01052
01053 ret = bfd_pef_parse_symbols (abfd, alocation);
01054 if (ret != nsyms)
01055 return 0;
01056
01057 return ret;
01058 }
01059
01060 static asymbol *
01061 bfd_pef_make_empty_symbol (abfd)
01062 bfd *abfd;
01063 {
01064 return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
01065 }
01066
01067 static void
01068 bfd_pef_get_symbol_info (abfd, symbol, ret)
01069 bfd *abfd ATTRIBUTE_UNUSED;
01070 asymbol *symbol;
01071 symbol_info *ret;
01072 {
01073 bfd_symbol_info (symbol, ret);
01074 }
01075
01076 static int
01077 bfd_pef_sizeof_headers (abfd, exec)
01078 bfd *abfd ATTRIBUTE_UNUSED;
01079 bfd_boolean exec ATTRIBUTE_UNUSED;
01080 {
01081 return 0;
01082 }
01083
01084 const bfd_target pef_vec =
01085 {
01086 "pef",
01087 bfd_target_pef_flavour,
01088 BFD_ENDIAN_BIG,
01089 BFD_ENDIAN_BIG,
01090 (HAS_RELOC | EXEC_P |
01091 HAS_LINENO | HAS_DEBUG |
01092 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
01093 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
01094 | SEC_ROM | SEC_HAS_CONTENTS),
01095 0,
01096 ' ',
01097 16,
01098 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01099 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01100 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01101 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01102 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01103 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01104 {
01105 _bfd_dummy_target,
01106 bfd_pef_object_p,
01107 _bfd_dummy_target,
01108 _bfd_dummy_target,
01109 },
01110 {
01111 bfd_false,
01112 bfd_pef_mkobject,
01113 bfd_false,
01114 bfd_false,
01115 },
01116 {
01117 bfd_false,
01118 bfd_true,
01119 bfd_false,
01120 bfd_false,
01121 },
01122
01123 BFD_JUMP_TABLE_GENERIC (bfd_pef),
01124 BFD_JUMP_TABLE_COPY (_bfd_generic),
01125 BFD_JUMP_TABLE_CORE (_bfd_nocore),
01126 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
01127 BFD_JUMP_TABLE_SYMBOLS (bfd_pef),
01128 BFD_JUMP_TABLE_RELOCS (bfd_pef),
01129 BFD_JUMP_TABLE_WRITE (bfd_pef),
01130 BFD_JUMP_TABLE_LINK (bfd_pef),
01131 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01132
01133 NULL,
01134
01135 NULL
01136 };
01137
01138 #define bfd_pef_xlib_close_and_cleanup _bfd_generic_close_and_cleanup
01139 #define bfd_pef_xlib_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
01140 #define bfd_pef_xlib_new_section_hook _bfd_generic_new_section_hook
01141 #define bfd_pef_xlib_get_section_contents _bfd_generic_get_section_contents
01142 #define bfd_pef_xlib_set_section_contents _bfd_generic_set_section_contents
01143 #define bfd_pef_xlib_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
01144 #define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window
01145
01146 static int
01147 bfd_pef_xlib_read_header (abfd, header)
01148 bfd *abfd;
01149 bfd_pef_xlib_header *header;
01150 {
01151 unsigned char buf[76];
01152
01153 bfd_seek (abfd, 0, SEEK_SET);
01154
01155 if (bfd_bread ((PTR) buf, 76, abfd) != 76)
01156 return -1;
01157
01158 header->tag1 = bfd_getb32 (buf);
01159 header->tag2 = bfd_getb32 (buf + 4);
01160 header->current_format = bfd_getb32 (buf + 8);
01161 header->container_strings_offset = bfd_getb32 (buf + 12);
01162 header->export_hash_offset = bfd_getb32 (buf + 16);
01163 header->export_key_offset = bfd_getb32 (buf + 20);
01164 header->export_symbol_offset = bfd_getb32 (buf + 24);
01165 header->export_names_offset = bfd_getb32 (buf + 28);
01166 header->export_hash_table_power = bfd_getb32 (buf + 32);
01167 header->exported_symbol_count = bfd_getb32 (buf + 36);
01168 header->frag_name_offset = bfd_getb32 (buf + 40);
01169 header->frag_name_length = bfd_getb32 (buf + 44);
01170 header->dylib_path_offset = bfd_getb32 (buf + 48);
01171 header->dylib_path_length = bfd_getb32 (buf + 52);
01172 header->cpu_family = bfd_getb32 (buf + 56);
01173 header->cpu_model = bfd_getb32 (buf + 60);
01174 header->date_time_stamp = bfd_getb32 (buf + 64);
01175 header->current_version = bfd_getb32 (buf + 68);
01176 header->old_definition_version = bfd_getb32 (buf + 72);
01177 header->old_implementation_version = bfd_getb32 (buf + 76);
01178
01179 return 0;
01180 }
01181
01182 int
01183 bfd_pef_xlib_scan (abfd, header)
01184 bfd *abfd;
01185 bfd_pef_xlib_header *header;
01186 {
01187 bfd_pef_xlib_data_struct *mdata = NULL;
01188
01189 mdata = ((bfd_pef_xlib_data_struct *)
01190 bfd_alloc (abfd, sizeof (bfd_pef_xlib_data_struct)));
01191 if (mdata == NULL)
01192 return -1;
01193
01194 mdata->header = *header;
01195
01196 abfd->flags = (abfd->xvec->object_flags
01197 | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
01198
01199 abfd->tdata.pef_xlib_data = mdata;
01200
01201 return 0;
01202 }
01203
01204 static const bfd_target *
01205 bfd_pef_xlib_object_p (abfd)
01206 bfd *abfd;
01207 {
01208 struct bfd_preserve preserve;
01209 bfd_pef_xlib_header header;
01210
01211 if (bfd_pef_xlib_read_header (abfd, &header) != 0)
01212 {
01213 bfd_set_error (bfd_error_wrong_format);
01214 return NULL;
01215 }
01216
01217 if ((header.tag1 != BFD_PEF_XLIB_TAG1)
01218 || ((header.tag2 != BFD_PEF_VLIB_TAG2)
01219 && (header.tag2 != BFD_PEF_BLIB_TAG2)))
01220 {
01221 bfd_set_error (bfd_error_wrong_format);
01222 return NULL;
01223 }
01224
01225 if (! bfd_preserve_save (abfd, &preserve))
01226 {
01227 bfd_set_error (bfd_error_wrong_format);
01228 return NULL;
01229 }
01230
01231 if (bfd_pef_xlib_scan (abfd, &header) != 0)
01232 {
01233 bfd_preserve_restore (abfd, &preserve);
01234 bfd_set_error (bfd_error_wrong_format);
01235 return NULL;
01236 }
01237
01238 bfd_preserve_finish (abfd, &preserve);
01239 return abfd->xvec;
01240 }
01241
01242 const bfd_target pef_xlib_vec =
01243 {
01244 "pef-xlib",
01245 bfd_target_pef_xlib_flavour,
01246 BFD_ENDIAN_BIG,
01247 BFD_ENDIAN_BIG,
01248 (HAS_RELOC | EXEC_P |
01249 HAS_LINENO | HAS_DEBUG |
01250 HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
01251 (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
01252 | SEC_ROM | SEC_HAS_CONTENTS),
01253 0,
01254 ' ',
01255 16,
01256 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01257 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01258 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01259 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
01260 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
01261 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
01262 {
01263 _bfd_dummy_target,
01264 bfd_pef_xlib_object_p,
01265 _bfd_dummy_target,
01266 _bfd_dummy_target,
01267 },
01268 {
01269 bfd_false,
01270 bfd_pef_mkobject,
01271 bfd_false,
01272 bfd_false,
01273 },
01274 {
01275 bfd_false,
01276 bfd_true,
01277 bfd_false,
01278 bfd_false,
01279 },
01280
01281 BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib),
01282 BFD_JUMP_TABLE_COPY (_bfd_generic),
01283 BFD_JUMP_TABLE_CORE (_bfd_nocore),
01284 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
01285 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
01286 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
01287 BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
01288 BFD_JUMP_TABLE_LINK (_bfd_nolink),
01289 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
01290
01291 NULL,
01292
01293 NULL
01294 };