From 15e1c58a0e6039cd0bdba2ee6e6639cfe34b4247 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Thu, 6 Nov 2008 13:03:43 +0000 Subject: [PATCH] 2008-11-06 Tristan Gingold * mach-o.h (BFD_MACH_O_NO_SECT): Add; reorders the macros. (BFD_MACH_O_SYM_NTYPE, BFD_MACH_O_SYM_NSECT, BFD_MACH_O_SYM_NDESC): New macros. (bfd_mach_o_i386_thread_flavour): Define according to the latest definition from system header. (bfd_mach_o_load_command_type): Add BFD_MACH_O_LC_RPATH, BFD_MACH_O_LC_CODE_SIGNATURE. (BFD_MACH_O_SECTION_TYPE_MASK, BFD_MACH_O_SECTION_ATTRIBUTES_MASK, BFD_MACH_O_SECTION_ATTRIBUTES_SYS, BFD_MACH_O_SECTION_ATTRIBUTES_USR, BFD_MACH_O_S_ATTR_LOC_RELOC, BFD_MACH_O_S_ATTR_EXT_RELOC, BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS, BFD_MACH_O_S_ATTR_DEBUG, BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS): Add. (bfd_mach_o_segment_command): Add room for a nul terminator in segname field. (BFD_MACH_O_PROT_READ, BFD_MACH_O_PROT_WRITE, BFD_MACH_O_PROT_EXECUTE): Add. (INDIRECT_SYMBOL_LOCAL): Renames to BFD_MACH_O_INDIRECT_SYMBOL_LOCAL. (INDIRECT_SYMBOL_ABS): Renames to BFD_MACH_O_INDIRECT_SYMBOL_ABS. (bfd_mach_o_uuid_command): Add the structure. (bfd_mach_o_load_command): Add uuid field. (bfd_get_mach_o_data): New macro. * mach-o.c (bfd_mach_o_bfd_print_private_bfd_data): New function which replaces the macro. (SECTION_TYPE, SECTION_ATTRIBUTES, SECTION_ATTRIBUTES_USR, S_ATTR_PURE_INSTRUCTIONS, SECTION_ATTRIBUTES_SYS, S_ATTR_SOME_INSTRUCTIONS, S_ATTR_EXT_RELOC, S_ATTR_LOC_RELOC): Renamed and moved to mach-o.h. (N_STAB, N_TYPE, N_EXT, N_UNDF, N_ABS, N_TEXT, N_DATA, N_BSS, N_SECT, N_INDR): Removed as they duplicated macros in mach-o.h. (bfd_mach_o_print_symbol): Print much more details. (bfd_mach_o_make_bfd_section): Add prot argument, use canonical dwarf name for dwarf sections. Precisely set section flags. (bfd_mach_o_scan_read_section_32): Add prot argument. (bfd_mach_o_scan_read_section_64): Ditto. (bfd_mach_o_scan_read_section): Ditto. (bfd_mach_o_scan_read_symtab_symbol): Set section for debugging stabs, set BSF_GLOBAL and LOCAL flags correctly. Fix section for N_SECT symbols. (bfd_mach_o_i386_flavour_string): Reindent and adjust for new names. (bfd_mach_o_scan_read_symtab): Set HAS_SYMS flags on bfd if there are symbols. (bfd_mach_o_scan_read_uuid): New function. (bfd_mach_o_scan_read_segment): Add a trailing nul. Segments flags are now simply HAS_CONTENTS. Pass protection to bfd_mach_o_scan_read_section. (bfd_mach_o_scan_read_command): Decode UUID command. (bfd_mach_o_flatten_sections): Add comments. Fix flavour names. (bfd_mach_o_scan): Set flags according to file type. (mach_o_fat_archentry): Remove abfd field. (bfd_mach_o_archive_p): Remove initialization of abfd field. (bfd_mach_o_openr_next_archived_file): Find previous archive by position and not by bfd (as former bfds may have been freed). Give architecture name to archived file. * mach-o-target.c (TARGET_NAME): Use generic archive for non fat targets. --- bfd/ChangeLog | 60 ++++++ bfd/mach-o-target.c | 10 +- bfd/mach-o.c | 444 ++++++++++++++++++++++++++++++++++---------- bfd/mach-o.h | 94 +++++++--- 4 files changed, 486 insertions(+), 122 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9a70d7dffcf..b9d5a99fd78 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,63 @@ +2008-11-06 Tristan Gingold + + * mach-o.h (BFD_MACH_O_NO_SECT): Add; reorders the macros. + (BFD_MACH_O_SYM_NTYPE, BFD_MACH_O_SYM_NSECT, + BFD_MACH_O_SYM_NDESC): New macros. + (bfd_mach_o_i386_thread_flavour): Define according to the latest + definition from system header. + (bfd_mach_o_load_command_type): Add BFD_MACH_O_LC_RPATH, + BFD_MACH_O_LC_CODE_SIGNATURE. + (BFD_MACH_O_SECTION_TYPE_MASK, BFD_MACH_O_SECTION_ATTRIBUTES_MASK, + BFD_MACH_O_SECTION_ATTRIBUTES_SYS, BFD_MACH_O_SECTION_ATTRIBUTES_USR, + BFD_MACH_O_S_ATTR_LOC_RELOC, BFD_MACH_O_S_ATTR_EXT_RELOC, + BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS, BFD_MACH_O_S_ATTR_DEBUG, + BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS): Add. + (bfd_mach_o_segment_command): Add room for a nul terminator in + segname field. + (BFD_MACH_O_PROT_READ, BFD_MACH_O_PROT_WRITE, + BFD_MACH_O_PROT_EXECUTE): Add. + (INDIRECT_SYMBOL_LOCAL): Renames to BFD_MACH_O_INDIRECT_SYMBOL_LOCAL. + (INDIRECT_SYMBOL_ABS): Renames to BFD_MACH_O_INDIRECT_SYMBOL_ABS. + (bfd_mach_o_uuid_command): Add the structure. + (bfd_mach_o_load_command): Add uuid field. + (bfd_get_mach_o_data): New macro. + * mach-o.c (bfd_mach_o_bfd_print_private_bfd_data): New function which + replaces the macro. + (SECTION_TYPE, SECTION_ATTRIBUTES, SECTION_ATTRIBUTES_USR, + S_ATTR_PURE_INSTRUCTIONS, SECTION_ATTRIBUTES_SYS, + S_ATTR_SOME_INSTRUCTIONS, S_ATTR_EXT_RELOC, S_ATTR_LOC_RELOC): Renamed + and moved to mach-o.h. + (N_STAB, N_TYPE, N_EXT, N_UNDF, N_ABS, N_TEXT, N_DATA, N_BSS, + N_SECT, N_INDR): Removed as they duplicated macros in mach-o.h. + (bfd_mach_o_print_symbol): Print much more details. + (bfd_mach_o_make_bfd_section): Add prot argument, use canonical + dwarf name for dwarf sections. Precisely set section flags. + (bfd_mach_o_scan_read_section_32): Add prot argument. + (bfd_mach_o_scan_read_section_64): Ditto. + (bfd_mach_o_scan_read_section): Ditto. + (bfd_mach_o_scan_read_symtab_symbol): Set section for debugging + stabs, set BSF_GLOBAL and LOCAL flags correctly. Fix section + for N_SECT symbols. + (bfd_mach_o_i386_flavour_string): Reindent and adjust for new + names. + (bfd_mach_o_scan_read_symtab): Set HAS_SYMS flags on bfd if there + are symbols. + (bfd_mach_o_scan_read_uuid): New function. + (bfd_mach_o_scan_read_segment): Add a trailing nul. Segments + flags are now simply HAS_CONTENTS. Pass protection to + bfd_mach_o_scan_read_section. + (bfd_mach_o_scan_read_command): Decode UUID command. + (bfd_mach_o_flatten_sections): Add comments. Fix flavour names. + (bfd_mach_o_scan): Set flags according to file type. + (mach_o_fat_archentry): Remove abfd field. + (bfd_mach_o_archive_p): Remove initialization of abfd field. + (bfd_mach_o_openr_next_archived_file): Find previous archive + by position and not by bfd (as former bfds may have been freed). + Give architecture name to archived file. + * mach-o-target.c (TARGET_NAME): Use generic archive for non fat + targets. + + 2008-10-30 Jay Krell * cache.c (cache_bread): Cast void * pointer before performing diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c index fd4d1e1a753..a435e6ed328 100644 --- a/bfd/mach-o-target.c +++ b/bfd/mach-o-target.c @@ -84,27 +84,31 @@ const bfd_target TARGET_NAME = #else _bfd_dummy_target, bfd_mach_o_object_p, - _bfd_dummy_target, + bfd_generic_archive_p, bfd_mach_o_core_p #endif }, { /* bfd_set_format. */ bfd_false, bfd_mach_o_mkobject, - bfd_false, + _bfd_generic_mkarchive, bfd_mach_o_mkobject, }, { /* bfd_write_contents. */ bfd_false, bfd_mach_o_write_contents, - bfd_false, + _bfd_write_archive_contents, bfd_mach_o_write_contents, }, BFD_JUMP_TABLE_GENERIC (bfd_mach_o), BFD_JUMP_TABLE_COPY (bfd_mach_o), BFD_JUMP_TABLE_CORE (bfd_mach_o), +#if TARGET_ARCHIVE BFD_JUMP_TABLE_ARCHIVE (bfd_mach_o), +#else + BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd), +#endif BFD_JUMP_TABLE_SYMBOLS (bfd_mach_o), BFD_JUMP_TABLE_RELOCS (_bfd_norelocs), BFD_JUMP_TABLE_WRITE (bfd_mach_o), diff --git a/bfd/mach-o.c b/bfd/mach-o.c index d3d3abc365b..afad9fdc120 100644 --- a/bfd/mach-o.c +++ b/bfd/mach-o.c @@ -24,6 +24,7 @@ #include "bfd.h" #include "libbfd.h" #include "libiberty.h" +#include "aout/stab_gnu.h" #include #ifndef BFD_IO_FUNCS @@ -64,7 +65,6 @@ #define bfd_mach_o_set_arch_mach bfd_default_set_arch_mach #define bfd_mach_o_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data #define bfd_mach_o_bfd_set_private_flags _bfd_generic_bfd_set_private_flags -#define bfd_mach_o_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data #define bfd_mach_o_get_section_contents _bfd_generic_get_section_contents #define bfd_mach_o_set_section_contents _bfd_generic_set_section_contents #define bfd_mach_o_bfd_gc_sections bfd_generic_gc_sections @@ -75,37 +75,6 @@ #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 - -/* The flags field of a section structure is separated into two parts a section - type and section attributes. The section types are mutually exclusive (it - can only have one type) but the section attributes are not (it may have more - than one attribute). */ - -#define SECTION_TYPE 0x000000ff /* 256 section types. */ -#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes. */ - -/* Constants for the section attributes part of the flags field of a section - structure. */ - -#define SECTION_ATTRIBUTES_USR 0xff000000 /* User-settable attributes. */ -#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* Section contains only true machine instructions. */ -#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* System setable attributes. */ -#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* Section contains some machine instructions. */ -#define S_ATTR_EXT_RELOC 0x00000200 /* Section has external relocation entries. */ -#define S_ATTR_LOC_RELOC 0x00000100 /* Section has local relocation entries. */ - -#define N_STAB 0xe0 -#define N_TYPE 0x1e -#define N_EXT 0x01 - -#define N_UNDF 0x0 -#define N_ABS 0x2 -#define N_TEXT 0x4 -#define N_DATA 0x6 -#define N_BSS 0x8 -#define N_SECT 0xe -#define N_INDR 0xa - static unsigned int bfd_mach_o_version (bfd *abfd) { @@ -255,6 +224,10 @@ bfd_mach_o_print_symbol (bfd *abfd, bfd_print_symbol_type how) { FILE *file = (FILE *) afile; + unsigned char ntype; + unsigned char nsect; + unsigned int ndesc; + const char *name; switch (how) { @@ -263,7 +236,40 @@ bfd_mach_o_print_symbol (bfd *abfd, break; default: bfd_print_symbol_vandf (abfd, (PTR) file, symbol); - fprintf (file, " %-5s %s", symbol->section->name, symbol->name); + ntype = BFD_MACH_O_SYM_NTYPE (symbol); + nsect = BFD_MACH_O_SYM_NSECT (symbol); + ndesc = BFD_MACH_O_SYM_NDESC (symbol); + if (ntype & BFD_MACH_O_N_STAB) + name = bfd_get_stab_name (ntype); + else + switch (ntype & BFD_MACH_O_N_TYPE) + { + case BFD_MACH_O_N_UNDF: + name = "UND"; + break; + case BFD_MACH_O_N_ABS: + name = "ABS"; + break; + case BFD_MACH_O_N_INDR: + name = "INDR"; + break; + case BFD_MACH_O_N_PBUD: + name = "PBUD"; + break; + case BFD_MACH_O_N_SECT: + name = "SECT"; + break; + default: + name = "???"; + break; + } + if (name == NULL) + name = ""; + fprintf (file, " %02x %-6s %02x %04x", ntype, name, nsect, ndesc); + if ((ntype & BFD_MACH_O_N_STAB) == 0 + && (ntype & BFD_MACH_O_N_TYPE) == BFD_MACH_O_N_SECT) + fprintf (file, " %-5s", symbol->section->name); + fprintf (file, " %s", symbol->name); } } @@ -554,9 +560,9 @@ bfd_mach_o_scan_write_symtab_symbols (bfd *abfd, bfd_mach_o_load_command *comman s = &sym->symbols[i]; /* Instead just set from the stored values. */ - ntype = (s->udata.i >> 24) & 0xff; - nsect = (s->udata.i >> 16) & 0xff; - ndesc = s->udata.i & 0xffff; + ntype = BFD_MACH_O_SYM_NTYPE (s); + nsect = BFD_MACH_O_SYM_NSECT (s); + ndesc = BFD_MACH_O_SYM_NDESC (s); bfd_h_put_32 (abfd, s->name - sym->strtab, buf); bfd_h_put_8 (abfd, ntype, buf + 4); @@ -769,7 +775,8 @@ bfd_mach_o_read_header (bfd *abfd, bfd_mach_o_header *header) } static asection * -bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section) +bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section, + unsigned long prot) { asection *bfdsec; char *sname; @@ -784,11 +791,31 @@ bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section) sname = bfd_alloc (abfd, snamelen); if (sname == NULL) return NULL; - sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname); - flags = SEC_ALLOC; - if ((section->flags & SECTION_TYPE) != BFD_MACH_O_S_ZEROFILL) - flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE; + /* Use canonical dwarf section names for dwarf sections. */ + if (strcmp (section->segname, "__DWARF") == 0 + && strncmp (section->sectname, "__", 2) == 0) + sprintf (sname, ".%s", section->sectname + 2); + else + sprintf (sname, "%s.%s.%s", prefix, section->segname, section->sectname); + + if (section->flags & BFD_MACH_O_S_ATTR_DEBUG) + flags = SEC_HAS_CONTENTS | SEC_DEBUGGING; + else + { + flags = SEC_ALLOC; + if ((section->flags & BFD_MACH_O_SECTION_TYPE_MASK) + != BFD_MACH_O_S_ZEROFILL) + { + flags |= SEC_HAS_CONTENTS | SEC_LOAD; + if (prot & BFD_MACH_O_PROT_EXECUTE) + flags |= SEC_CODE; + if (prot & BFD_MACH_O_PROT_WRITE) + flags |= SEC_DATA; + else if (prot & BFD_MACH_O_PROT_READ) + flags |= SEC_READONLY; + } + } bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, flags); if (bfdsec == NULL) return NULL; @@ -806,7 +833,8 @@ bfd_mach_o_make_bfd_section (bfd *abfd, bfd_mach_o_section *section) static int bfd_mach_o_scan_read_section_32 (bfd *abfd, bfd_mach_o_section *section, - bfd_vma offset) + bfd_vma offset, + unsigned long prot) { unsigned char buf[68]; @@ -828,7 +856,7 @@ bfd_mach_o_scan_read_section_32 (bfd *abfd, section->reserved1 = bfd_h_get_32 (abfd, buf + 60); section->reserved2 = bfd_h_get_32 (abfd, buf + 64); section->reserved3 = 0; - section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section); + section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot); if (section->bfdsection == NULL) return -1; @@ -839,7 +867,8 @@ bfd_mach_o_scan_read_section_32 (bfd *abfd, static int bfd_mach_o_scan_read_section_64 (bfd *abfd, bfd_mach_o_section *section, - bfd_vma offset) + bfd_vma offset, + unsigned long prot) { unsigned char buf[80]; @@ -861,7 +890,7 @@ bfd_mach_o_scan_read_section_64 (bfd *abfd, section->reserved1 = bfd_h_get_32 (abfd, buf + 68); section->reserved2 = bfd_h_get_32 (abfd, buf + 72); section->reserved3 = bfd_h_get_32 (abfd, buf + 76); - section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section); + section->bfdsection = bfd_mach_o_make_bfd_section (abfd, section, prot); if (section->bfdsection == NULL) return -1; @@ -873,12 +902,13 @@ static int bfd_mach_o_scan_read_section (bfd *abfd, bfd_mach_o_section *section, bfd_vma offset, + unsigned long prot, unsigned int wide) { if (wide) - return bfd_mach_o_scan_read_section_64 (abfd, section, offset); + return bfd_mach_o_scan_read_section_64 (abfd, section, offset, prot); else - return bfd_mach_o_scan_read_section_32 (abfd, section, offset); + return bfd_mach_o_scan_read_section_32 (abfd, section, offset, prot); } int @@ -912,7 +942,7 @@ bfd_mach_o_scan_read_symtab_symbol (bfd *abfd, stroff = bfd_h_get_32 (abfd, buf); type = bfd_h_get_8 (abfd, buf + 4); symtype = (type & 0x0e); - section = bfd_h_get_8 (abfd, buf + 5) - 1; + section = bfd_h_get_8 (abfd, buf + 5); desc = bfd_h_get_16 (abfd, buf + 6); if (wide) value = bfd_h_get_64 (abfd, buf + 8); @@ -936,20 +966,35 @@ bfd_mach_o_scan_read_symtab_symbol (bfd *abfd, { s->flags |= BSF_DEBUGGING; s->section = bfd_und_section_ptr; + switch (type) + { + case N_FUN: + case N_STSYM: + case N_LCSYM: + case N_BNSYM: + case N_SLINE: + case N_ENSYM: + case N_ECOMM: + case N_ECOML: + case N_GSYM: + if ((section > 0) && (section <= mdata->nsects)) + { + s->section = mdata->sections[section - 1]->bfdsection; + s->value = s->value - mdata->sections[section - 1]->addr; + } + break; + } } else { if (type & BFD_MACH_O_N_PEXT) - { - type &= ~BFD_MACH_O_N_PEXT; - s->flags |= BSF_GLOBAL; - } - + s->flags |= BSF_GLOBAL; + if (type & BFD_MACH_O_N_EXT) - { - type &= ~BFD_MACH_O_N_EXT; - s->flags |= BSF_GLOBAL; - } + s->flags |= BSF_GLOBAL; + + if (!(type & (BFD_MACH_O_N_PEXT | BFD_MACH_O_N_EXT))) + s->flags |= BSF_LOCAL; switch (symtype) { @@ -965,8 +1010,8 @@ bfd_mach_o_scan_read_symtab_symbol (bfd *abfd, case BFD_MACH_O_N_SECT: if ((section > 0) && (section <= mdata->nsects)) { - s->section = mdata->sections[section]->bfdsection; - s->value = s->value - mdata->sections[section]->addr; + s->section = mdata->sections[section - 1]->bfdsection; + s->value = s->value - mdata->sections[section - 1]->addr; } else { @@ -1094,18 +1139,19 @@ bfd_mach_o_i386_flavour_string (unsigned int flavour) { switch ((int) flavour) { - case BFD_MACH_O_i386_NEW_THREAD_STATE: return "i386_NEW_THREAD_STATE"; - case BFD_MACH_O_i386_FLOAT_STATE: return "i386_FLOAT_STATE"; - case BFD_MACH_O_i386_ISA_PORT_MAP_STATE: return "i386_ISA_PORT_MAP_STATE"; - case BFD_MACH_O_i386_V86_ASSIST_STATE: return "i386_V86_ASSIST_STATE"; - case BFD_MACH_O_i386_REGS_SEGS_STATE: return "i386_REGS_SEGS_STATE"; - case BFD_MACH_O_i386_THREAD_SYSCALL_STATE: return "i386_THREAD_SYSCALL_STATE"; - case BFD_MACH_O_i386_THREAD_STATE_NONE: return "i386_THREAD_STATE_NONE"; - case BFD_MACH_O_i386_SAVED_STATE: return "i386_SAVED_STATE"; - case BFD_MACH_O_i386_THREAD_STATE: return "i386_THREAD_STATE"; - case BFD_MACH_O_i386_THREAD_FPSTATE: return "i386_THREAD_FPSTATE"; - case BFD_MACH_O_i386_THREAD_EXCEPTSTATE: return "i386_THREAD_EXCEPTSTATE"; - case BFD_MACH_O_i386_THREAD_CTHREADSTATE: return "i386_THREAD_CTHREADSTATE"; + case BFD_MACH_O_x86_THREAD_STATE32: return "x86_THREAD_STATE32"; + case BFD_MACH_O_x86_FLOAT_STATE32: return "x86_FLOAT_STATE32"; + case BFD_MACH_O_x86_EXCEPTION_STATE32: return "x86_EXCEPTION_STATE32"; + case BFD_MACH_O_x86_THREAD_STATE64: return "x86_THREAD_STATE64"; + case BFD_MACH_O_x86_FLOAT_STATE64: return "x86_FLOAT_STATE64"; + case BFD_MACH_O_x86_EXCEPTION_STATE64: return "x86_EXCEPTION_STATE64"; + case BFD_MACH_O_x86_THREAD_STATE: return "x86_THREAD_STATE"; + case BFD_MACH_O_x86_FLOAT_STATE: return "x86_FLOAT_STATE"; + case BFD_MACH_O_x86_EXCEPTION_STATE: return "x86_EXCEPTION_STATE"; + 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"; default: return "UNKNOWN"; } } @@ -1422,6 +1468,9 @@ bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command) seg->stabs_segment = bfdsec; + if (seg->nsyms != 0) + abfd->flags |= HAS_SYMS; + prefix = "LC_SYMTAB.stabstr"; sname = bfd_alloc (abfd, strlen (prefix) + 1); if (sname == NULL) @@ -1443,6 +1492,40 @@ bfd_mach_o_scan_read_symtab (bfd *abfd, bfd_mach_o_load_command *command) return 0; } +static int +bfd_mach_o_scan_read_uuid (bfd *abfd, bfd_mach_o_load_command *command) +{ + bfd_mach_o_uuid_command *cmd = &command->command.uuid; + asection *bfdsec; + char *sname; + static const char prefix[] = "LC_UUID"; + + BFD_ASSERT (command->type == BFD_MACH_O_LC_UUID); + + bfd_seek (abfd, command->offset + 8, SEEK_SET); + if (bfd_bread ((PTR) cmd->uuid, 16, abfd) != 16) + return -1; + + sname = bfd_alloc (abfd, strlen (prefix) + 1); + if (sname == NULL) + return -1; + strcpy (sname, prefix); + + bfdsec = bfd_make_section_anyway_with_flags (abfd, sname, SEC_HAS_CONTENTS); + if (bfdsec == NULL) + 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; +} + static int bfd_mach_o_scan_read_segment (bfd *abfd, bfd_mach_o_load_command *command, @@ -1465,6 +1548,7 @@ bfd_mach_o_scan_read_segment (bfd *abfd, return -1; memcpy (seg->segname, buf, 16); + seg->segname[16] = '\0'; seg->vmaddr = bfd_h_get_64 (abfd, buf + 16); seg->vmsize = bfd_h_get_64 (abfd, buf + 24); @@ -1484,6 +1568,7 @@ bfd_mach_o_scan_read_segment (bfd *abfd, return -1; memcpy (seg->segname, buf, 16); + seg->segname[16] = '\0'; seg->vmaddr = bfd_h_get_32 (abfd, buf + 16); seg->vmsize = bfd_h_get_32 (abfd, buf + 20); @@ -1510,7 +1595,7 @@ bfd_mach_o_scan_read_segment (bfd *abfd, bfdsec->size = seg->filesize; bfdsec->filepos = seg->fileoff; bfdsec->alignment_power = 0x0; - bfdsec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE; + bfdsec->flags = SEC_HAS_CONTENTS; bfdsec->segment_mark = 1; seg->segment = bfdsec; @@ -1530,7 +1615,7 @@ bfd_mach_o_scan_read_segment (bfd *abfd, segoff = command->offset + 48 + 8 + (i * 68); if (bfd_mach_o_scan_read_section - (abfd, &seg->sections[i], segoff, wide) != 0) + (abfd, &seg->sections[i], segoff, seg->initprot, wide) != 0) return -1; } } @@ -1618,6 +1703,12 @@ bfd_mach_o_scan_read_command (bfd *abfd, bfd_mach_o_load_command *command) case BFD_MACH_O_LC_TWOLEVEL_HINTS: case BFD_MACH_O_LC_PREBIND_CKSUM: break; + case BFD_MACH_O_LC_UUID: + if (bfd_mach_o_scan_read_uuid (abfd, command) != 0) + return -1; + break; + case BFD_MACH_O_LC_CODE_SIGNATURE: + break; default: fprintf (stderr, "unable to read unknown load command 0x%lx\n", (unsigned long) command->type); @@ -1634,6 +1725,7 @@ bfd_mach_o_flatten_sections (bfd *abfd) long csect = 0; unsigned long i, j; + /* Count total number of sections. */ mdata->nsects = 0; for (i = 0; i < mdata->header.ncmds; i++) @@ -1648,8 +1740,11 @@ bfd_mach_o_flatten_sections (bfd *abfd) } } + /* Allocate sections array. */ mdata->sections = bfd_alloc (abfd, mdata->nsects * sizeof (bfd_mach_o_section *)); + + /* Fill the array. */ csect = 0; for (i = 0; i < mdata->header.ncmds; i++) @@ -1694,7 +1789,7 @@ bfd_mach_o_scan_start_address (bfd *abfd) { if ((mdata->header.cputype == BFD_MACH_O_CPU_TYPE_I386) && (cmd->flavours[i].flavour - == (unsigned long) BFD_MACH_O_i386_THREAD_STATE)) + == (unsigned long) BFD_MACH_O_x86_THREAD_STATE32)) { unsigned char buf[4]; @@ -1761,8 +1856,21 @@ bfd_mach_o_scan (bfd *abfd, mdata->header = *header; mdata->symbols = NULL; - abfd->flags = (abfd->xvec->object_flags - | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS))); + abfd->flags = abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS); + switch (header->filetype) + { + case BFD_MACH_O_MH_OBJECT: + abfd->flags |= HAS_RELOC; + break; + case BFD_MACH_O_MH_EXECUTE: + abfd->flags |= EXEC_P; + break; + case BFD_MACH_O_MH_DYLIB: + case BFD_MACH_O_MH_BUNDLE: + abfd->flags |= DYNAMIC; + break; + } + abfd->tdata.mach_o_data = mdata; bfd_mach_o_convert_architecture (header->cputype, header->cpusubtype, @@ -1938,7 +2046,6 @@ typedef struct mach_o_fat_archentry unsigned long offset; unsigned long size; unsigned long align; - bfd *abfd; } mach_o_fat_archentry; typedef struct mach_o_fat_data_struct @@ -1984,7 +2091,6 @@ bfd_mach_o_archive_p (bfd *abfd) adata->archentries[i].offset = bfd_getb32 (buf + 8); adata->archentries[i].size = bfd_getb32 (buf + 12); adata->archentries[i].align = bfd_getb32 (buf + 16); - adata->archentries[i].abfd = NULL; } abfd->tdata.mach_o_fat_data = adata; @@ -2003,6 +2109,11 @@ bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev) mach_o_fat_data_struct *adata; mach_o_fat_archentry *entry = NULL; unsigned long i; + bfd *nbfd; + const char *arch_name; + enum bfd_architecture arch_type; + unsigned long arch_subtype; + char *s = NULL; adata = (mach_o_fat_data_struct *) archive->tdata.mach_o_fat_data; BFD_ASSERT (adata != NULL); @@ -2014,7 +2125,7 @@ bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev) { for (i = 0; i < adata->nfat_arch; i++) { - if (adata->archentries[i].abfd == prev) + if (adata->archentries[i].offset == prev->origin) break; } @@ -2034,25 +2145,23 @@ bfd_mach_o_openr_next_archived_file (bfd *archive, bfd *prev) } entry = &adata->archentries[i]; - if (entry->abfd == NULL) - { - bfd *nbfd = _bfd_new_bfd_contained_in (archive); - char *s = NULL; - - if (nbfd == NULL) - return NULL; - - nbfd->origin = entry->offset; - s = bfd_malloc (strlen (archive->filename) + 1); - if (s == NULL) - return NULL; - strcpy (s, archive->filename); - nbfd->filename = s; - nbfd->iostream = NULL; - entry->abfd = nbfd; - } + nbfd = _bfd_new_bfd_contained_in (archive); + if (nbfd == NULL) + return NULL; + + nbfd->origin = entry->offset; + + bfd_mach_o_convert_architecture (entry->cputype, entry->cpusubtype, + &arch_type, &arch_subtype); + arch_name = bfd_printable_arch_mach (arch_type, arch_subtype); + s = bfd_malloc (strlen (arch_name) + 1); + if (s == NULL) + return NULL; + strcpy (s, arch_name); + nbfd->filename = s; + nbfd->iostream = NULL; - return entry->abfd; + return nbfd; } int @@ -2161,6 +2270,147 @@ bfd_mach_o_stack_addr (enum bfd_mach_o_cpu_type type) } } +static bfd_boolean +bfd_mach_o_bfd_print_private_bfd_data (bfd *abfd, PTR ptr) +{ + bfd_mach_o_data_struct *mdata = abfd->tdata.mach_o_data; + FILE *file = (FILE *) ptr; + unsigned int i, j; + unsigned int sec_nbr = 0; + + fprintf (file, _("Segments and Sections:\n")); + fprintf (file, _(" #: Segment name Section name Address\n")); + + for (i = 0; i < mdata->header.ncmds; i++) + { + bfd_mach_o_segment_command *seg; + + if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT + && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64) + continue; + + seg = &mdata->commands[i].command.segment; + + fprintf (file, "[Segment %-16s ", seg->segname); + fprintf_vma (file, seg->vmaddr); + fprintf (file, "-"); + fprintf_vma (file, seg->vmaddr + seg->vmsize - 1); + fputc (' ', file); + fputc (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-', file); + fputc (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-', file); + fputc (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-', file); + fprintf (file, "]\n"); + for (j = 0; j < seg->nsects; j++) + { + bfd_mach_o_section *sec = &seg->sections[j]; + fprintf (file, "%02u: %-16s %-16s ", ++sec_nbr, + sec->segname, sec->sectname); + fprintf_vma (file, sec->addr); + fprintf (file, " "); + fprintf_vma (file, sec->size); + fprintf (file, " %08lx\n", sec->flags); + } + } + + for (i = 0; i < mdata->header.ncmds; i++) + { + bfd_mach_o_load_command *cmd = &mdata->commands[i]; + + switch (cmd->type) + { + case BFD_MACH_O_LC_SEGMENT: + case BFD_MACH_O_LC_SEGMENT_64: + break; + case BFD_MACH_O_LC_UUID: + { + bfd_mach_o_uuid_command *uuid = &cmd->command.uuid; + unsigned int i; + + fprintf (file, "\n" + "UUID:"); + for (i = 0; i < sizeof (uuid->uuid); i++) + fprintf (file, " %02x", uuid->uuid[i]); + fputc ('\n', file); + } + break; + case BFD_MACH_O_LC_LOAD_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, "\n" + "LOAD_DYLIB: %s\n", + data + dylib->name_offset - cmd->offset - 8); + 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, "\n" + "LOAD_DYLINKER: %s\n", + data + linker->name_offset - cmd->offset - 8); + free (data); + break; + } + case BFD_MACH_O_LC_SYMTAB: + { + bfd_mach_o_symtab_command *symtab = &cmd->command.symtab; + fprintf (file, "\n" + "LC_SYMTAB: nsyms: %lu, strsize: %lu\n", + symtab->nsyms, symtab->strsize); + break; + } + case BFD_MACH_O_LC_DYSYMTAB: + { + bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab; + fprintf (file, "\n" + "LC_DYSYMTAB:\n" + " local symbols: index: %lu number: %lu\n", + dysymtab->ilocalsym, dysymtab->nlocalsym); + fprintf (file, + " external symbols: index: %lu number: %lu\n", + dysymtab->iextdefsym, dysymtab->nextdefsym); + fprintf (file, + " undefined symbols: index: %lu number: %lu\n", + dysymtab->iundefsym, dysymtab->nundefsym); + fprintf (file, + " ntoc: offset: %lu number: %lu\n", + dysymtab->tocoff, dysymtab->ntoc); + fprintf (file, + " module table: offset: %lu number: %lu\n", + dysymtab->modtaboff, dysymtab->nmodtab); + break; + } + default: + fprintf (file, "LC_%d\n", cmd->type); + break; + } + } + + return TRUE; +} + int bfd_mach_o_core_fetch_environment (bfd *abfd, unsigned char **rbuf, diff --git a/bfd/mach-o.h b/bfd/mach-o.h index d73f205e6de..8ffb1b242ea 100644 --- a/bfd/mach-o.h +++ b/bfd/mach-o.h @@ -30,9 +30,15 @@ #define BFD_MACH_O_N_EXT 0x01 /* External symbol bit, set for external symbols. */ #define BFD_MACH_O_N_UNDF 0x00 /* Undefined, n_sect == NO_SECT. */ #define BFD_MACH_O_N_ABS 0x02 /* Absolute, n_sect == NO_SECT. */ -#define BFD_MACH_O_N_SECT 0x0e /* Defined in section number n_sect. */ -#define BFD_MACH_O_N_PBUD 0x0c /* Prebound undefined (defined in a dylib). */ #define BFD_MACH_O_N_INDR 0x0a /* Indirect. */ +#define BFD_MACH_O_N_PBUD 0x0c /* Prebound undefined (defined in a dylib). */ +#define BFD_MACH_O_N_SECT 0x0e /* Defined in section number n_sect. */ + +#define BFD_MACH_O_NO_SECT 0 + +#define BFD_MACH_O_SYM_NTYPE(SYM) (((SYM)->udata.i >> 24) & 0xff) +#define BFD_MACH_O_SYM_NSECT(SYM) (((SYM)->udata.i >> 16) & 0xff) +#define BFD_MACH_O_SYM_NDESC(SYM) ((SYM)->udata.i & 0xffff) typedef enum bfd_mach_o_ppc_thread_flavour { @@ -44,26 +50,22 @@ typedef enum bfd_mach_o_ppc_thread_flavour } bfd_mach_o_ppc_thread_flavour; +/* Defined in */ typedef enum bfd_mach_o_i386_thread_flavour { - BFD_MACH_O_i386_NEW_THREAD_STATE = 1, - BFD_MACH_O_i386_FLOAT_STATE = 2, - BFD_MACH_O_i386_ISA_PORT_MAP_STATE = 3, - BFD_MACH_O_i386_V86_ASSIST_STATE = 4, - BFD_MACH_O_i386_REGS_SEGS_STATE = 5, - BFD_MACH_O_i386_THREAD_SYSCALL_STATE = 6, - BFD_MACH_O_i386_SAVED_STATE = 8, - BFD_MACH_O_i386_THREAD_STATE = -1, - BFD_MACH_O_i386_THREAD_FPSTATE = -2, - BFD_MACH_O_i386_THREAD_EXCEPTSTATE = -3, - BFD_MACH_O_i386_THREAD_CTHREADSTATE = -4, + 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_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_i386_THREAD_STATE_NONE = 10, + 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_i386_thread_flavour; @@ -99,9 +101,11 @@ typedef enum bfd_mach_o_load_command_type BFD_MACH_O_LC_LOAD_WEAK_DYLIB = 0x18, BFD_MACH_O_LC_SEGMENT_64 = 0x19, /* 64-bit segment of this file to be mapped. */ - BFD_MACH_O_LC_ROUTINES_64 = 0x1a, /* Address of the dyld init routine - in a dylib. */ - BFD_MACH_O_LC_UUID = 0x1b /* 128-bit UUID of the executable. */ + BFD_MACH_O_LC_ROUTINES_64 = 0x1a, /* Address of the dyld init routine + in a dylib. */ + BFD_MACH_O_LC_UUID = 0x1b, /* 128-bit UUID of the executable. */ + BFD_MACH_O_LC_RPATH = 0x1c, /* Run path addiions. */ + BFD_MACH_O_LC_CODE_SIGNATURE = 0x1d /* Local of code signature. */ } bfd_mach_o_load_command_type; @@ -188,6 +192,35 @@ typedef enum bfd_mach_o_section_type } bfd_mach_o_section_type; +/* The flags field of a section structure is separated into two parts a section + type and section attributes. The section types are mutually exclusive (it + can only have one type) but the section attributes are not (it may have more + than one attribute). */ + +#define BFD_MACH_O_SECTION_TYPE_MASK 0x000000ff + +/* Constants for the section attributes part of the flags field of a section + structure. */ +#define BFD_MACH_O_SECTION_ATTRIBUTES_MASK 0xffffff00 +/* System setable attributes. */ +#define BFD_MACH_O_SECTION_ATTRIBUTES_SYS 0x00ffff00 +/* User attributes. */ +#define BFD_MACH_O_SECTION_ATTRIBUTES_USR 0xff000000 + +/* Section has local relocation entries. */ +#define BFD_MACH_O_S_ATTR_LOC_RELOC 0x00000100 + +/* Section has external relocation entries. */ +#define BFD_MACH_O_S_ATTR_EXT_RELOC 0x00000200 + +/* Section contains some machine instructions. */ +#define BFD_MACH_O_S_ATTR_SOME_INSTRUCTIONS 0x00004000 + +#define BFD_MACH_O_S_ATTR_DEBUG 0x02000000 + +/* Section contains only true machine instructions. */ +#define BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS 0x80000000 + typedef unsigned long bfd_mach_o_cpu_subtype; typedef struct bfd_mach_o_header @@ -226,13 +259,13 @@ bfd_mach_o_section; typedef struct bfd_mach_o_segment_command { - char segname[16]; + char segname[16 + 1]; bfd_vma vmaddr; bfd_vma vmsize; bfd_vma fileoff; unsigned long filesize; - unsigned long maxprot; - unsigned long initprot; + unsigned long maxprot; /* Maximum permitted protection. */ + unsigned long initprot; /* Initial protection. */ unsigned long nsects; unsigned long flags; bfd_mach_o_section *sections; @@ -240,6 +273,11 @@ typedef struct bfd_mach_o_segment_command } bfd_mach_o_segment_command; +/* Protection flags. */ +#define BFD_MACH_O_PROT_READ 0x01 +#define BFD_MACH_O_PROT_WRITE 0x02 +#define BFD_MACH_O_PROT_EXECUTE 0x04 + typedef struct bfd_mach_o_symtab_command { unsigned long symoff; @@ -399,8 +437,8 @@ bfd_mach_o_dysymtab_command; removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. */ -#define INDIRECT_SYMBOL_LOCAL 0x80000000 -#define INDIRECT_SYMBOL_ABS 0x40000000 +#define BFD_MACH_O_INDIRECT_SYMBOL_LOCAL 0x80000000 +#define BFD_MACH_O_INDIRECT_SYMBOL_ABS 0x40000000 typedef struct bfd_mach_o_thread_flavour { @@ -452,6 +490,15 @@ typedef struct bfd_mach_o_prebound_dylib_command } bfd_mach_o_prebound_dylib_command; +typedef struct bfd_mach_o_uuid_command +{ + unsigned long cmd; /* LC_PREBOUND_DYLIB. */ + unsigned long cmdsize; /* Includes uuid. */ + unsigned char uuid[16]; /* Uuid. */ + asection *section; +} +bfd_mach_o_uuid_command; + typedef struct bfd_mach_o_load_command { bfd_mach_o_load_command_type type; @@ -467,6 +514,7 @@ typedef struct bfd_mach_o_load_command bfd_mach_o_dylib_command dylib; bfd_mach_o_dylinker_command dylinker; bfd_mach_o_prebound_dylib_command prebound_dylib; + bfd_mach_o_uuid_command uuid; } command; } @@ -484,6 +532,8 @@ typedef struct mach_o_data_struct } mach_o_data_struct; +#define bfd_get_mach_o_data(abfd) ((abfd)->tdata.mach_o_data) + typedef struct mach_o_data_struct bfd_mach_o_data_struct; bfd_boolean bfd_mach_o_valid (bfd *); -- 2.30.2