From b32e07d7d744d2acc7fc04d96f2d67eef6f35b87 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Thu, 25 Jun 2009 12:39:06 +0000 Subject: [PATCH] 2009-06-25 Tristan Gingold * mach-o-target.c (bfd_mach_o_get_dynamic_symtab_upper_bound) (bfd_mach_o_canonicalize_dynamic_symtab) (bfd_mach_o_get_synthetic_symtab): Defines. (TARGET_NAME_BACKEND): Add bfd_mach_o_print_thread entry. (TARGET_NAME): Use Mach-O specific functions for dynamic. * mach-o-i386.c (bfd_mach_o_i386_swap_reloc_in): Fix howto indexes for scattered relocations. (bfd_mach_o_i386_print_thread): New function. (bfd_mach_o_print_thread): Define. * mach-o.c (text_section_names_xlat): Add an entry for __const. (bfd_mach_o_canonicalize_one_reloc, bfd_mach_o_canonicalize_relocs): New functions extracted from ... (bfd_mach_o_canonicalize_reloc): ... This. Simplified. (bfd_mach_o_get_dynamic_reloc_upper_bound): New function. (bfd_mach_o_canonicalize_dynamic_reloc): New function. (bfd_mach_o_i386_flavour_string): Adjusted after enum renaming. (bfd_mach_o_ppc_flavour_string): Reindentation. Add 64 bits cases. (bfd_mach_o_scan_read_dylinker): Do not create a section anymore. Set name_str field. (bfd_mach_o_scan_read_dylib): Ditto. (bfd_mach_o_scan_read_thread): Set mdata at declaration. Add comments, reindent. (bfd_mach_o_scan_read_dysymtab): Set mdata at declaration. Correctly decode isym and flags on little endian targets. Set dysymtab field. (bfd_mach_o_scan_start_address): Adjust for enum names. (bfd_mach_o_lookup_section): Do not look for segments anymore. (bfd_mach_o_print_section): Display bfd section name. (bfd_mach_o_print_segment): Display none if no name. (bfd_mach_o_print_dysymtab): Display next index for local, external and undefined symbols. (bfd_mach_o_bfd_print_private_bfd_data): Adjust code by using name_str. Display dylinker name. Display thread and unixthread commands content. (bfd_mach_o_print_thread): New macro. * mach-o.h (bfd_mach_o_mach_header_magic): Align numbers. (bfd_mach_o_ppc_thread_flavour): Ditto. (bfd_mach_o_i386_thread_flavour): Ditto. (BFD_MACH_O_PPC_THREAD_STATE_NONE): New enum. (BFD_MACH_O_x86_THREAD_STATE_NONE): Replaces BFD_MACH_O_THREAD_STATE_NONE. (bfd_mach_o_segment_command): Remove segment field. (bfd_mach_o_thread_flavour): Field offset is now unsigned long. (bfd_mach_o_dylinker_command): Remove section field, add name_str. (bfd_mach_o_prebound_dylib_command): Ditto. (bfd_mach_o_dylib_command): Ditto. (bfd_mach_o_prebound_dylib_command): Remove section field. (mach_o_data_struct): Add dysymtab field. (bfd_mach_o_backend_data): Add _bfd_mach_o_print_thread field. (bfd_mach_o_get_reloc_upper_bound, bfd_mach_o_canonicalize_reloc) (bfd_mach_o_build_commands): Remove parameter names and attributes. (bfd_mach_o_get_dynamic_reloc_upper_bound) (bfd_mach_o_canonicalize_dynamic_reloc): New prototypes. --- bfd/ChangeLog | 57 ++++++ bfd/mach-o-i386.c | 67 ++++++- bfd/mach-o-target.c | 9 +- bfd/mach-o.c | 431 +++++++++++++++++++++++++------------------- bfd/mach-o.h | 61 ++++--- 5 files changed, 409 insertions(+), 216 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0ac28206a7f..5a27b6406db 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,60 @@ +2009-06-25 Tristan Gingold + + * mach-o-target.c (bfd_mach_o_get_dynamic_symtab_upper_bound) + (bfd_mach_o_canonicalize_dynamic_symtab) + (bfd_mach_o_get_synthetic_symtab): Defines. + (TARGET_NAME_BACKEND): Add bfd_mach_o_print_thread entry. + (TARGET_NAME): Use Mach-O specific functions for dynamic. + + * mach-o-i386.c (bfd_mach_o_i386_swap_reloc_in): Fix howto indexes + for scattered relocations. + (bfd_mach_o_i386_print_thread): New function. + (bfd_mach_o_print_thread): Define. + + * mach-o.c (text_section_names_xlat): Add an entry for __const. + (bfd_mach_o_canonicalize_one_reloc, bfd_mach_o_canonicalize_relocs): + New functions extracted from ... + (bfd_mach_o_canonicalize_reloc): ... This. Simplified. + (bfd_mach_o_get_dynamic_reloc_upper_bound): New function. + (bfd_mach_o_canonicalize_dynamic_reloc): New function. + (bfd_mach_o_i386_flavour_string): Adjusted after enum renaming. + (bfd_mach_o_ppc_flavour_string): Reindentation. Add 64 bits cases. + (bfd_mach_o_scan_read_dylinker): Do not create a section anymore. + Set name_str field. + (bfd_mach_o_scan_read_dylib): Ditto. + (bfd_mach_o_scan_read_thread): Set mdata at declaration. Add comments, + reindent. + (bfd_mach_o_scan_read_dysymtab): Set mdata at declaration. Correctly + decode isym and flags on little endian targets. Set dysymtab field. + (bfd_mach_o_scan_start_address): Adjust for enum names. + (bfd_mach_o_lookup_section): Do not look for segments anymore. + (bfd_mach_o_print_section): Display bfd section name. + (bfd_mach_o_print_segment): Display none if no name. + (bfd_mach_o_print_dysymtab): Display next index for local, external + and undefined symbols. + (bfd_mach_o_bfd_print_private_bfd_data): Adjust code by using name_str. + Display dylinker name. Display thread and unixthread commands content. + (bfd_mach_o_print_thread): New macro. + + * mach-o.h (bfd_mach_o_mach_header_magic): Align numbers. + (bfd_mach_o_ppc_thread_flavour): Ditto. + (bfd_mach_o_i386_thread_flavour): Ditto. + (BFD_MACH_O_PPC_THREAD_STATE_NONE): New enum. + (BFD_MACH_O_x86_THREAD_STATE_NONE): Replaces + BFD_MACH_O_THREAD_STATE_NONE. + (bfd_mach_o_segment_command): Remove segment field. + (bfd_mach_o_thread_flavour): Field offset is now unsigned long. + (bfd_mach_o_dylinker_command): Remove section field, add name_str. + (bfd_mach_o_prebound_dylib_command): Ditto. + (bfd_mach_o_dylib_command): Ditto. + (bfd_mach_o_prebound_dylib_command): Remove section field. + (mach_o_data_struct): Add dysymtab field. + (bfd_mach_o_backend_data): Add _bfd_mach_o_print_thread field. + (bfd_mach_o_get_reloc_upper_bound, bfd_mach_o_canonicalize_reloc) + (bfd_mach_o_build_commands): Remove parameter names and attributes. + (bfd_mach_o_get_dynamic_reloc_upper_bound) + (bfd_mach_o_canonicalize_dynamic_reloc): New prototypes. + 2009-06-25 Rafael Avila de Espindola * plugin.c (load_plugin): Use stat and S_ISREG instead of the d_type diff --git a/bfd/mach-o-i386.c b/bfd/mach-o-i386.c index 02e467bfa94..53de64e826c 100644 --- a/bfd/mach-o-i386.c +++ b/bfd/mach-o-i386.c @@ -102,14 +102,14 @@ bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc) case BFD_MACH_O_GENERIC_RELOC_PAIR: if (reloc->r_length != 2) return FALSE; - res->howto = &i386_howto_table[3]; + res->howto = &i386_howto_table[6]; res->address = res[-1].address; return TRUE; case BFD_MACH_O_GENERIC_RELOC_SECTDIFF: case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF: if (reloc->r_length != 2) return FALSE; - res->howto = &i386_howto_table[2]; + res->howto = &i386_howto_table[5]; return TRUE; default: return FALSE; @@ -217,8 +217,71 @@ bfd_mach_o_i386_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, return NULL; } +static bfd_boolean +bfd_mach_o_i386_print_thread (bfd *abfd, bfd_mach_o_thread_flavour *thread, + void *vfile, char *buf) +{ + FILE *file = (FILE *)vfile; + + switch (thread->flavour) + { + case BFD_MACH_O_x86_THREAD_STATE: + if (thread->size < (8 + 16 * 4)) + return FALSE; + fprintf (file, " x86_THREAD_STATE:\n"); + fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 0), + (unsigned long)bfd_get_32 (abfd, buf + 4)); + fprintf (file, " eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 8), + (unsigned long)bfd_get_32 (abfd, buf + 12), + (unsigned long)bfd_get_32 (abfd, buf + 16), + (unsigned long)bfd_get_32 (abfd, buf + 20)); + fprintf (file, " edi: %08lx esi: %08lx ebp: %08lx esp: %08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 24), + (unsigned long)bfd_get_32 (abfd, buf + 28), + (unsigned long)bfd_get_32 (abfd, buf + 32), + (unsigned long)bfd_get_32 (abfd, buf + 36)); + fprintf (file, " ss: %08lx flg: %08lx eip: %08lx cs: %08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 40), + (unsigned long)bfd_get_32 (abfd, buf + 44), + (unsigned long)bfd_get_32 (abfd, buf + 48), + (unsigned long)bfd_get_32 (abfd, buf + 52)); + fprintf (file, " ds: %08lx es: %08lx fs: %08lx gs: %08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 56), + (unsigned long)bfd_get_32 (abfd, buf + 60), + (unsigned long)bfd_get_32 (abfd, buf + 64), + (unsigned long)bfd_get_32 (abfd, buf + 68)); + return TRUE; + case BFD_MACH_O_x86_FLOAT_STATE: + if (thread->size < 8) + return FALSE; + fprintf (file, " x86_FLOAT_STATE:\n"); + fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 0), + (unsigned long)bfd_get_32 (abfd, buf + 4)); + return TRUE; + case BFD_MACH_O_x86_EXCEPTION_STATE: + if (thread->size < 8 + 3 * 4) + return FALSE; + fprintf (file, " x86_EXCEPTION_STATE:\n"); + fprintf (file, " flavor: 0x%08lx count: 0x%08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 0), + (unsigned long)bfd_get_32 (abfd, buf + 4)); + fprintf (file, " trapno: %08lx err: %08lx faultaddr: %08lx\n", + (unsigned long)bfd_get_32 (abfd, buf + 8), + (unsigned long)bfd_get_32 (abfd, buf + 12), + (unsigned long)bfd_get_32 (abfd, buf + 16)); + return TRUE; + default: + break; + } + return FALSE; +} + #define bfd_mach_o_swap_reloc_in bfd_mach_o_i386_swap_reloc_in #define bfd_mach_o_swap_reloc_out bfd_mach_o_i386_swap_reloc_out +#define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread #define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_i386_bfd_reloc_type_lookup #define bfd_mach_o_bfd_reloc_name_lookup bfd_mach_o_i386_bfd_reloc_name_lookup diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c index f203382522f..7070f5dc338 100644 --- a/bfd/mach-o-target.c +++ b/bfd/mach-o-target.c @@ -68,6 +68,10 @@ #define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data #define bfd_mach_o_core_file_matches_executable_p generic_core_file_matches_executable_p +#define bfd_mach_o_get_dynamic_symtab_upper_bound bfd_mach_o_get_symtab_upper_bound +#define bfd_mach_o_canonicalize_dynamic_symtab bfd_mach_o_canonicalize_symtab +#define bfd_mach_o_get_synthetic_symtab _bfd_nodynamic_get_synthetic_symtab + #define TARGET_NAME_BACKEND XCONCAT2(TARGET_NAME,_backend) #endif /* MACH_O_TARGET_COMMON_DEFINED */ @@ -95,7 +99,8 @@ static const bfd_mach_o_backend_data TARGET_NAME_BACKEND = { bfd_mach_o_swap_reloc_in, - bfd_mach_o_swap_reloc_out + bfd_mach_o_swap_reloc_out, + bfd_mach_o_print_thread }; const bfd_target TARGET_NAME = @@ -172,7 +177,7 @@ const bfd_target TARGET_NAME = BFD_JUMP_TABLE_RELOCS (bfd_mach_o), BFD_JUMP_TABLE_WRITE (bfd_mach_o), BFD_JUMP_TABLE_LINK (bfd_mach_o), - BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + BFD_JUMP_TABLE_DYNAMIC (bfd_mach_o), /* Alternative endian target. */ NULL, diff --git a/bfd/mach-o.c b/bfd/mach-o.c index 8071dee86ae..ac1d6b82355 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -111,6 +111,7 @@ static const struct mach_o_section_name_xlat dwarf_section_names_xlat[] = static const struct mach_o_section_name_xlat text_section_names_xlat[] = { { ".text", "__text" }, + { ".const", "__const" }, { ".cstring", "__cstring" }, { ".eh_frame", "__eh_frame" }, { NULL, NULL} @@ -514,110 +515,188 @@ bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, return (asect->reloc_count + 1) * sizeof (arelent *); } -long -bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect, - arelent **rels, asymbol **syms) +static int +bfd_mach_o_canonicalize_one_reloc (bfd *abfd, char *buf, + arelent *res, asymbol **syms) { bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd); + bfd_mach_o_reloc_info reloc; + bfd_vma addr; + bfd_vma symnum; + asymbol **sym; + + addr = bfd_get_32 (abfd, buf + 0); + symnum = bfd_get_32 (abfd, buf + 4); + + if (addr & BFD_MACH_O_SR_SCATTERED) + { + unsigned int j; + + /* Scattered relocation. + Extract section and offset from r_value. */ + res->sym_ptr_ptr = NULL; + res->addend = 0; + for (j = 0; j < mdata->nsects; j++) + { + bfd_mach_o_section *sect = mdata->sections[j]; + if (symnum >= sect->addr && symnum < sect->addr + sect->size) + { + res->sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr; + res->addend = symnum - sect->addr; + break; + } + } + res->address = BFD_MACH_O_GET_SR_ADDRESS (addr); + reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr); + reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr); + reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL; + reloc.r_scattered = 1; + } + else + { + unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum); + res->addend = 0; + res->address = addr; + if (symnum & BFD_MACH_O_R_EXTERN) + sym = syms + num; + else + { + BFD_ASSERT (num != 0); + BFD_ASSERT (num <= mdata->nsects); + sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr; + } + res->sym_ptr_ptr = sym; + reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum); + reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum); + reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0; + reloc.r_scattered = 0; + } + + if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc)) + return -1; + return 0; +} + +static int +bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos, + unsigned long count, + arelent *res, asymbol **syms) +{ unsigned long i; - arelent *res; char *native_relocs; bfd_size_type native_size; - if (asect->reloc_count == 0) - return 0; - - /* No need to go further if we don't know how to read relocs. */ - if (bed->_bfd_mach_o_swap_reloc_in == NULL) - return 0; - /* Allocate and read relocs. */ - native_size = asect->reloc_count * BFD_MACH_O_RELENT_SIZE; + native_size = count * BFD_MACH_O_RELENT_SIZE; native_relocs = bfd_malloc (native_size); if (native_relocs == NULL) return -1; - if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0 + if (bfd_seek (abfd, filepos, SEEK_SET) != 0 || bfd_bread (native_relocs, native_size, abfd) != native_size) + goto err; + + for (i = 0; i < count; i++) { - free (native_relocs); - return -1; + char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i; + + if (bfd_mach_o_canonicalize_one_reloc (abfd, buf, &res[i], syms) < 0) + goto err; } + free (native_relocs); + return i; + err: + free (native_relocs); + return -1; +} + +long +bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect, + arelent **rels, asymbol **syms) +{ + bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd); + unsigned long i; + arelent *res; + + if (asect->reloc_count == 0) + return 0; + + /* No need to go further if we don't know how to read relocs. */ + if (bed->_bfd_mach_o_swap_reloc_in == NULL) + return 0; res = bfd_malloc (asect->reloc_count * sizeof (arelent)); if (res == NULL) + return -1; + + if (bfd_mach_o_canonicalize_relocs (abfd, asect->rel_filepos, + asect->reloc_count, res, syms) < 0) { - free (native_relocs); + free (res); return -1; } for (i = 0; i < asect->reloc_count; i++) - { - char *buf = native_relocs + BFD_MACH_O_RELENT_SIZE * i; - bfd_mach_o_reloc_info reloc; - bfd_vma addr; - bfd_vma symnum; - asymbol **sym; + rels[i] = &res[i]; + rels[i] = NULL; + asect->relocation = res; - addr = bfd_get_32 (abfd, buf + 0); - symnum = bfd_get_32 (abfd, buf + 4); + return i; +} - if (addr & BFD_MACH_O_SR_SCATTERED) - { - unsigned int j; +long +bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *abfd) +{ + bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); - /* Scattered relocation. - Extract section and offset from r_value. */ - res[i].sym_ptr_ptr = NULL; - res[i].addend = 0; - for (j = 0; j < mdata->nsects; j++) - { - bfd_mach_o_section *sect = mdata->sections[j]; - if (symnum >= sect->addr && symnum < sect->addr + sect->size) - { - res[i].sym_ptr_ptr = sect->bfdsection->symbol_ptr_ptr; - res[i].addend = symnum - sect->addr; - break; - } - } - res[i].address = BFD_MACH_O_GET_SR_ADDRESS (addr); - reloc.r_type = BFD_MACH_O_GET_SR_TYPE (addr); - reloc.r_length = BFD_MACH_O_GET_SR_LENGTH (addr); - reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL; - reloc.r_scattered = 1; - } - else - { - unsigned int num = BFD_MACH_O_GET_R_SYMBOLNUM (symnum); - res[i].addend = 0; - res[i].address = addr; - if (symnum & BFD_MACH_O_R_EXTERN) - sym = syms + num; - else - { - BFD_ASSERT (num != 0); - BFD_ASSERT (num <= mdata->nsects); - sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr; - } - res[i].sym_ptr_ptr = sym; - reloc.r_type = BFD_MACH_O_GET_R_TYPE (symnum); - reloc.r_length = BFD_MACH_O_GET_R_LENGTH (symnum); - reloc.r_pcrel = (symnum & BFD_MACH_O_R_PCREL) ? 1 : 0; - reloc.r_scattered = 0; - } + if (mdata->dysymtab == NULL) + return 1; + return (mdata->dysymtab->nextrel + mdata->dysymtab->nlocrel) + * sizeof (arelent *); +} - if (!(*bed->_bfd_mach_o_swap_reloc_in)(&res[i], &reloc)) - { - free (res); - free (native_relocs); - return -1; - } - rels[i] = &res[i]; +long +bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels, + struct bfd_symbol **syms) +{ + bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); + bfd_mach_o_dysymtab_command *dysymtab = mdata->dysymtab; + bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd); + unsigned long i; + arelent *res; + + if (dysymtab == NULL) + return 0; + if (dysymtab->nextrel == 0 && dysymtab->nlocrel == 0) + return 0; + + /* No need to go further if we don't know how to read relocs. */ + if (bed->_bfd_mach_o_swap_reloc_in == NULL) + return 0; + + res = bfd_malloc ((dysymtab->nextrel + dysymtab->nlocrel) * sizeof (arelent)); + if (res == NULL) + return -1; + + if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->extreloff, + dysymtab->nextrel, res, syms) < 0) + { + free (res); + return -1; } - rels[asect->reloc_count] = NULL; - asect->relocation = res; - free (native_relocs); + + if (bfd_mach_o_canonicalize_relocs (abfd, dysymtab->locreloff, + dysymtab->nlocrel, + res + dysymtab->nextrel, syms) < 0) + { + free (res); + return -1; + } + + for (i = 0; i < dysymtab->nextrel + dysymtab->nlocrel; i++) + rels[i] = &res[i]; + rels[i] = NULL; return i; } @@ -1653,7 +1732,7 @@ bfd_mach_o_i386_flavour_string (unsigned int flavour) case BFD_MACH_O_x86_DEBUG_STATE32: return "x86_DEBUG_STATE32"; case BFD_MACH_O_x86_DEBUG_STATE64: return "x86_DEBUG_STATE64"; case BFD_MACH_O_x86_DEBUG_STATE: return "x86_DEBUG_STATE"; - case BFD_MACH_O_THREAD_STATE_NONE: return "THREAD_STATE_NONE"; + case BFD_MACH_O_x86_THREAD_STATE_NONE: return "x86_THREAD_STATE_NONE"; default: return "UNKNOWN"; } } @@ -1663,10 +1742,12 @@ bfd_mach_o_ppc_flavour_string (unsigned int flavour) { switch ((int) flavour) { - case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE"; - case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE"; - case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE"; - case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE"; + case BFD_MACH_O_PPC_THREAD_STATE: return "PPC_THREAD_STATE"; + case BFD_MACH_O_PPC_FLOAT_STATE: return "PPC_FLOAT_STATE"; + case BFD_MACH_O_PPC_EXCEPTION_STATE: return "PPC_EXCEPTION_STATE"; + case BFD_MACH_O_PPC_VECTOR_STATE: return "PPC_VECTOR_STATE"; + case BFD_MACH_O_PPC_THREAD_STATE64: return "PPC_THREAD_STATE64"; + case BFD_MACH_O_PPC_EXCEPTION_STATE64: return "PPC_EXCEPTION_STATE64"; default: return "UNKNOWN"; } } @@ -1678,9 +1759,6 @@ bfd_mach_o_scan_read_dylinker (bfd *abfd, bfd_mach_o_dylinker_command *cmd = &command->command.dylinker; unsigned char buf[4]; unsigned int nameoff; - asection *bfdsec; - char *sname; - const char *prefix; BFD_ASSERT ((command->type == BFD_MACH_O_LC_ID_DYLINKER) || (command->type == BFD_MACH_O_LC_LOAD_DYLINKER)); @@ -1693,31 +1771,12 @@ bfd_mach_o_scan_read_dylinker (bfd *abfd, cmd->name_offset = command->offset + nameoff; cmd->name_len = command->len - nameoff; - - if (command->type == BFD_MACH_O_LC_LOAD_DYLINKER) - prefix = "LC_LOAD_DYLINKER"; - else if (command->type == BFD_MACH_O_LC_ID_DYLINKER) - prefix = "LC_ID_DYLINKER"; - else - abort (); - - sname = bfd_alloc (abfd, strlen (prefix) + 1); - if (sname == NULL) + cmd->name_str = bfd_alloc (abfd, cmd->name_len); + if (cmd->name_str == NULL) return -1; - strcpy (sname, prefix); - - bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS); - if (bfdsec == NULL) + if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0 + || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len) return -1; - - bfdsec->vma = 0; - bfdsec->lma = 0; - bfdsec->size = command->len - nameoff; - bfdsec->filepos = command->offset + nameoff; - bfdsec->alignment_power = 0; - - cmd->section = bfdsec; - return 0; } @@ -1727,26 +1786,17 @@ bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command) bfd_mach_o_dylib_command *cmd = &command->command.dylib; unsigned char buf[16]; unsigned int nameoff; - asection *bfdsec; - char *sname; - const char *prefix; switch (command->type) { case BFD_MACH_O_LC_LOAD_DYLIB: - prefix = "LC_LOAD_DYLIB"; - break; case BFD_MACH_O_LC_LOAD_WEAK_DYLIB: - prefix = "LC_LOAD_WEAK_DYLIB"; - break; case BFD_MACH_O_LC_ID_DYLIB: - prefix = "LC_ID_DYLIB"; - break; case BFD_MACH_O_LC_REEXPORT_DYLIB: - prefix = "LC_REEXPORT_DYLIB"; break; default: - abort (); + BFD_FAIL (); + return -1; } if (bfd_seek (abfd, command->offset + 8, SEEK_SET) != 0 @@ -1760,24 +1810,12 @@ bfd_mach_o_scan_read_dylib (bfd *abfd, bfd_mach_o_load_command *command) cmd->name_offset = command->offset + nameoff; cmd->name_len = command->len - nameoff; - - sname = bfd_alloc (abfd, strlen (prefix) + 1); - if (sname == NULL) + cmd->name_str = bfd_alloc (abfd, cmd->name_len); + if (cmd->name_str == NULL) return -1; - strcpy (sname, prefix); - - bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS); - if (bfdsec == NULL) + if (bfd_seek (abfd, cmd->name_offset, SEEK_SET) != 0 + || bfd_bread (cmd->name_str, cmd->name_len, abfd) != cmd->name_len) return -1; - - bfdsec->vma = 0; - bfdsec->lma = 0; - bfdsec->size = command->len - 8; - bfdsec->filepos = command->offset + 8; - bfdsec->alignment_power = 0; - - cmd->section = bfdsec; - return 0; } @@ -1794,7 +1832,7 @@ bfd_mach_o_scan_read_prebound_dylib (bfd *abfd ATTRIBUTE_UNUSED, static int bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command) { - bfd_mach_o_data_struct *mdata = NULL; + bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); bfd_mach_o_thread_command *cmd = &command->command.thread; unsigned char buf[8]; unsigned int offset; @@ -1804,9 +1842,7 @@ bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command) BFD_ASSERT ((command->type == BFD_MACH_O_LC_THREAD) || (command->type == BFD_MACH_O_LC_UNIXTHREAD)); - BFD_ASSERT (bfd_mach_o_valid (abfd)); - mdata = bfd_mach_o_get_data (abfd); - + /* Count the number of threads. */ offset = 8; nflavours = 0; while (offset != command->len) @@ -1822,7 +1858,9 @@ bfd_mach_o_scan_read_thread (bfd *abfd, bfd_mach_o_load_command *command) nflavours++; } - cmd->flavours = bfd_alloc (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour)); + /* Allocate threads. */ + cmd->flavours = bfd_alloc + (abfd, nflavours * sizeof (bfd_mach_o_thread_flavour)); if (cmd->flavours == NULL) return -1; cmd->nflavours = nflavours; @@ -1903,6 +1941,7 @@ static int bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) { bfd_mach_o_dysymtab_command *cmd = &command->command.dysymtab; + bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); unsigned char buf[72]; BFD_ASSERT (command->type == BFD_MACH_O_LC_DYSYMTAB); @@ -2051,12 +2090,26 @@ bfd_mach_o_scan_read_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) if (bfd_bread ((PTR) buf, 4, abfd) != 4) return -1; + /* Fields isym and flags are written as bit-fields, thus we need + a specific processing for endianness. */ v = bfd_h_get_32 (abfd, buf + 0); - ref->isym = (v >> 8) & 0xffffff; - ref->flags = v & 0xff; + if (bfd_big_endian (abfd)) + { + ref->isym = (v >> 8) & 0xffffff; + ref->flags = v & 0xff; + } + else + { + ref->isym = v & 0xffffff; + ref->flags = (v >> 24) & 0xff; + } } } + if (mdata->dysymtab) + return -1; + mdata->dysymtab = cmd; + return 0; } @@ -2433,7 +2486,7 @@ bfd_mach_o_scan_start_address (bfd *abfd) abfd->start_address = bfd_h_get_32 (abfd, buf); } else if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_POWERPC_64) - && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE_64)) + && (cmd->flavours[i].flavour == BFD_MACH_O_PPC_THREAD_STATE64)) { unsigned char buf[8]; @@ -2880,13 +2933,6 @@ bfd_mach_o_lookup_section (bfd *abfd, continue; seg = &cmd->command.segment; - if (seg->segment == section) - { - if (num == 0) - ncmd = cmd; - num++; - } - for (j = 0; j < seg->nsects; j++) { struct bfd_mach_o_section *sect = &seg->sections[j]; @@ -2894,7 +2940,10 @@ bfd_mach_o_lookup_section (bfd *abfd, if (sect->bfdsection == section) { if (num == 0) - nsect = sect; + { + nsect = sect; + ncmd = cmd; + } num++; } } @@ -3232,8 +3281,8 @@ static void bfd_mach_o_print_section (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec, FILE *file) { - fprintf (file, " Section: sectname: %-16s segname: %-16s\n", - sec->sectname, sec->segname); + fprintf (file, " Section: %-16s %-16s (bfdname: %s)\n", + sec->sectname, sec->segname, sec->bfdsection->name); fprintf (file, " addr: "); fprintf_vma (file, sec->addr); fprintf (file, " size: "); @@ -3285,7 +3334,7 @@ bfd_mach_o_print_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_segment_command *seg = &cmd->command.segment; unsigned int i; - fprintf (file, " name: %s\n", seg->segname); + fprintf (file, " name: %s\n", *seg->segname ? seg->segname : "*none*"); fprintf (file, " vmaddr: "); fprintf_vma (file, seg->vmaddr); fprintf (file, " vmsize: "); @@ -3312,12 +3361,18 @@ bfd_mach_o_print_dysymtab (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd); unsigned int i; - fprintf (file, " local symbols: idx: %10lu num: %lu\n", + fprintf (file, " local symbols: idx: %10lu num: %-8lu", dysymtab->ilocalsym, dysymtab->nlocalsym); - fprintf (file, " external symbols: idx: %10lu num: %lu\n", + fprintf (file, " (nxtidx: %lu)\n", + dysymtab->ilocalsym + dysymtab->nlocalsym); + fprintf (file, " external symbols: idx: %10lu num: %-8lu", dysymtab->iextdefsym, dysymtab->nextdefsym); - fprintf (file, " undefined symbols: idx: %10lu num: %lu\n", + fprintf (file, " (nxtidx: %lu)\n", + dysymtab->iextdefsym + dysymtab->nextdefsym); + fprintf (file, " undefined symbols: idx: %10lu num: %-8lu", dysymtab->iundefsym, dysymtab->nundefsym); + fprintf (file, " (nxtidx: %lu)\n", + dysymtab->iundefsym + dysymtab->nundefsym); fprintf (file, " table of content: off: 0x%08lx num: %-8lu", dysymtab->tocoff, dysymtab->ntoc); fprintf (file, " (endoff: 0x%08lx)\n", @@ -3521,43 +3576,19 @@ bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr) case BFD_MACH_O_LC_ID_DYLIB: { bfd_mach_o_dylib_command *dylib = &cmd->command.dylib; - bfd_byte *data = NULL; - - if (! bfd_malloc_and_get_section (abfd, dylib->section, &data)) - { - if (data != NULL) - free (data); - break; - } - fprintf (file, - " %s\n", - data + dylib->name_offset - cmd->offset - 8); + fprintf (file, " %s\n", dylib->name_str); fprintf (file, " time stamp: 0x%08lx\n", dylib->timestamp); fprintf (file, " current version: 0x%08lx\n", dylib->current_version); fprintf (file, " comptibility version: 0x%08lx\n", dylib->compatibility_version); - free (data); break; } case BFD_MACH_O_LC_LOAD_DYLINKER: - { - bfd_mach_o_dylinker_command *linker = &cmd->command.dylinker; - bfd_byte *data = NULL; - - if (! bfd_malloc_and_get_section (abfd, linker->section, &data)) - { - if (data != NULL) - free (data); - break; - } - fprintf (file, - " %s\n", - data + linker->name_offset - cmd->offset - 8); - free (data); - break; - } + case BFD_MACH_O_LC_ID_DYLINKER: + fprintf (file, " %s\n", cmd->command.dylinker.name_str); + break; case BFD_MACH_O_LC_SYMTAB: { bfd_mach_o_symtab_command *symtab = &cmd->command.symtab; @@ -3598,6 +3629,37 @@ bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr) fprintf (file, " %s\n", str->str); break; } + case BFD_MACH_O_LC_THREAD: + case BFD_MACH_O_LC_UNIXTHREAD: + { + bfd_mach_o_thread_command *thread = &cmd->command.thread; + unsigned int j; + bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd); + + fprintf (file, " nflavours: %lu\n", thread->nflavours); + for (j = 0; j < thread->nflavours; j++) + { + bfd_mach_o_thread_flavour *flavour = &thread->flavours[j]; + + fprintf (file, " %2u: flavour: 0x%08lx offset: 0x%08lx" + " size: 0x%08lx\n", + j, flavour->flavour, flavour->offset, + flavour->size); + if (bed->_bfd_mach_o_print_thread) + { + char *buf = bfd_malloc (flavour->size); + + if (buf + && bfd_seek (abfd, flavour->offset, SEEK_SET) == 0 + && (bfd_bread (buf, flavour->size, abfd) + == flavour->size)) + (*bed->_bfd_mach_o_print_thread)(abfd, flavour, + file, buf); + free (buf); + } + } + break; + } default: fprintf (file, "\n"); break; @@ -3727,6 +3789,7 @@ bfd_mach_o_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED) #define bfd_mach_o_swap_reloc_in NULL #define bfd_mach_o_swap_reloc_out NULL +#define bfd_mach_o_print_thread NULL #define TARGET_NAME mach_o_be_vec #define TARGET_STRING "mach-o-be" diff --git a/bfd/mach-o.h b/bfd/mach-o.h index 252991d6b8b..0f48324f52f 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -54,8 +54,8 @@ typedef enum bfd_mach_o_mach_header_magic { - BFD_MACH_O_MH_MAGIC = 0xfeedface, - BFD_MACH_O_MH_CIGAM = 0xcefaedfe, + BFD_MACH_O_MH_MAGIC = 0xfeedface, + BFD_MACH_O_MH_CIGAM = 0xcefaedfe, BFD_MACH_O_MH_MAGIC_64 = 0xfeedfacf, BFD_MACH_O_MH_CIGAM_64 = 0xcffaedfe } @@ -63,30 +63,32 @@ bfd_mach_o_mach_header_magic; typedef enum bfd_mach_o_ppc_thread_flavour { - BFD_MACH_O_PPC_THREAD_STATE = 1, - BFD_MACH_O_PPC_FLOAT_STATE = 2, - BFD_MACH_O_PPC_EXCEPTION_STATE = 3, - BFD_MACH_O_PPC_VECTOR_STATE = 4, - BFD_MACH_O_PPC_THREAD_STATE_64 = 5 + BFD_MACH_O_PPC_THREAD_STATE = 1, + BFD_MACH_O_PPC_FLOAT_STATE = 2, + BFD_MACH_O_PPC_EXCEPTION_STATE = 3, + BFD_MACH_O_PPC_VECTOR_STATE = 4, + BFD_MACH_O_PPC_THREAD_STATE64 = 5, + BFD_MACH_O_PPC_EXCEPTION_STATE64 = 6, + BFD_MACH_O_PPC_THREAD_STATE_NONE = 7 } bfd_mach_o_ppc_thread_flavour; /* Defined in */ typedef enum bfd_mach_o_i386_thread_flavour { - BFD_MACH_O_x86_THREAD_STATE32 = 1, - BFD_MACH_O_x86_FLOAT_STATE32 = 2, + BFD_MACH_O_x86_THREAD_STATE32 = 1, + BFD_MACH_O_x86_FLOAT_STATE32 = 2, BFD_MACH_O_x86_EXCEPTION_STATE32 = 3, - BFD_MACH_O_x86_THREAD_STATE64 = 4, - BFD_MACH_O_x86_FLOAT_STATE64 = 5, + BFD_MACH_O_x86_THREAD_STATE64 = 4, + BFD_MACH_O_x86_FLOAT_STATE64 = 5, BFD_MACH_O_x86_EXCEPTION_STATE64 = 6, - BFD_MACH_O_x86_THREAD_STATE = 7, - BFD_MACH_O_x86_FLOAT_STATE = 8, - BFD_MACH_O_x86_EXCEPTION_STATE = 9, - BFD_MACH_O_x86_DEBUG_STATE32 = 10, - BFD_MACH_O_x86_DEBUG_STATE64 = 11, - BFD_MACH_O_x86_DEBUG_STATE = 12, - BFD_MACH_O_THREAD_STATE_NONE = 13 + BFD_MACH_O_x86_THREAD_STATE = 7, + BFD_MACH_O_x86_FLOAT_STATE = 8, + BFD_MACH_O_x86_EXCEPTION_STATE = 9, + BFD_MACH_O_x86_DEBUG_STATE32 = 10, + BFD_MACH_O_x86_DEBUG_STATE64 = 11, + BFD_MACH_O_x86_DEBUG_STATE = 12, + BFD_MACH_O_x86_THREAD_STATE_NONE = 13 } bfd_mach_o_i386_thread_flavour; @@ -373,7 +375,6 @@ typedef struct bfd_mach_o_segment_command unsigned long nsects; unsigned long flags; bfd_mach_o_section *sections; - asection *segment; } bfd_mach_o_segment_command; #define BFD_MACH_O_LC_SEGMENT_SIZE 56 @@ -689,10 +690,12 @@ bfd_mach_o_dysymtab_command; #define BFD_MACH_O_INDIRECT_SYMBOL_ABS 0x40000000 #define BFD_MACH_O_INDIRECT_SYMBOL_SIZE 4 +/* For LC_THREAD or LC_UNIXTHREAD. */ + typedef struct bfd_mach_o_thread_flavour { unsigned long flavour; - bfd_vma offset; + unsigned long offset; unsigned long size; } bfd_mach_o_thread_flavour; @@ -711,7 +714,7 @@ typedef struct bfd_mach_o_dylinker_command { unsigned long name_offset; /* Offset to library's path name. */ unsigned long name_len; /* Offset to library's path name. */ - asection *section; + char *name_str; } bfd_mach_o_dylinker_command; @@ -725,7 +728,7 @@ typedef struct bfd_mach_o_dylib_command unsigned long timestamp; /* Library's build time stamp. */ unsigned long current_version; /* Library's current version number. */ unsigned long compatibility_version; /* Library's compatibility vers number. */ - asection *section; + char *name_str; } bfd_mach_o_dylib_command; @@ -736,7 +739,6 @@ typedef struct bfd_mach_o_prebound_dylib_command unsigned long name; /* Library's path name. */ unsigned long nmodules; /* Number of modules in library. */ unsigned long linked_modules; /* Bit vector of linked modules. */ - asection *section; } bfd_mach_o_prebound_dylib_command; @@ -808,6 +810,7 @@ typedef struct mach_o_data_struct a direct access to it. Also it is not clearly stated, only one symtab is expected. */ bfd_mach_o_symtab_command *symtab; + bfd_mach_o_dysymtab_command *dysymtab; } bfd_mach_o_data_struct; @@ -816,6 +819,8 @@ typedef struct bfd_mach_o_backend_data { bfd_boolean (*_bfd_mach_o_swap_reloc_in)(arelent *, bfd_mach_o_reloc_info *); bfd_boolean (*_bfd_mach_o_swap_reloc_out)(arelent *, bfd_mach_o_reloc_info *); + bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *, + void *, char *); } bfd_mach_o_backend_data; @@ -842,10 +847,10 @@ bfd_boolean bfd_mach_o_bfd_copy_private_section_data (bfd *, asection *, bfd_boolean bfd_mach_o_bfd_copy_private_bfd_data (bfd *, bfd *); long bfd_mach_o_get_symtab_upper_bound (bfd *); long bfd_mach_o_canonicalize_symtab (bfd *, asymbol **); -long bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, - asection *asect); -long bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect, - arelent **rels, asymbol **syms); +long bfd_mach_o_get_reloc_upper_bound (bfd *, asection *); +long bfd_mach_o_canonicalize_reloc (bfd *, asection *, arelent **, asymbol **); +long bfd_mach_o_get_dynamic_reloc_upper_bound (bfd *); +long bfd_mach_o_canonicalize_dynamic_reloc (bfd *, arelent **, asymbol **); asymbol *bfd_mach_o_make_empty_symbol (bfd *); void bfd_mach_o_get_symbol_info (bfd *, asymbol *, symbol_info *); void bfd_mach_o_print_symbol (bfd *, PTR, asymbol *, bfd_print_symbol_type); @@ -859,7 +864,7 @@ bfd_boolean bfd_mach_o_core_file_matches_executable_p (bfd *, bfd *); bfd *bfd_mach_o_fat_extract (bfd *, bfd_format , const bfd_arch_info_type *); const bfd_target *bfd_mach_o_header_p (bfd *, bfd_mach_o_filetype, bfd_mach_o_cpu_type); -bfd_boolean bfd_mach_o_build_commands (bfd *abfd); +bfd_boolean bfd_mach_o_build_commands (bfd *); bfd_boolean bfd_mach_o_set_section_contents (bfd *, asection *, const void *, file_ptr, bfd_size_type); unsigned int bfd_mach_o_version (bfd *); -- 2.30.2