Index: bfd/mach-o.c |
diff --git a/bfd/mach-o.c b/bfd/mach-o.c |
index 1f9fc17608539692303a4c1c4c181d047355b730..ffe7332a674063310989412fdd5e08aabc7cfce8 100644 |
--- a/bfd/mach-o.c |
+++ b/bfd/mach-o.c |
@@ -1,7 +1,5 @@ |
/* Mach-O support for BFD. |
- Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
- 2009, 2010, 2011, 2012 |
- Free Software Foundation, Inc. |
+ Copyright 1999-2013 Free Software Foundation, Inc. |
This file is part of BFD, the Binary File Descriptor library. |
@@ -84,7 +82,7 @@ bfd_mach_o_wide_p (bfd *abfd) |
{ |
return mach_o_wide_p (&bfd_mach_o_get_data (abfd)->header); |
} |
- |
+ |
/* Tables to translate well known Mach-O segment/section names to bfd |
names. Use of canonical names (such as .text or .debug_frame) is required |
by gdb. */ |
@@ -92,7 +90,7 @@ bfd_mach_o_wide_p (bfd *abfd) |
/* __TEXT Segment. */ |
static const mach_o_section_name_xlat text_section_names_xlat[] = |
{ |
- { ".text", "__text", |
+ { ".text", "__text", |
SEC_CODE | SEC_LOAD, BFD_MACH_O_S_REGULAR, |
BFD_MACH_O_S_ATTR_PURE_INSTRUCTIONS, 0}, |
{ ".const", "__const", |
@@ -197,6 +195,9 @@ static const mach_o_section_name_xlat dwarf_section_names_xlat[] = |
{ ".debug_macro", "__debug_macro", |
SEC_DEBUGGING, BFD_MACH_O_S_REGULAR, |
BFD_MACH_O_S_ATTR_DEBUG, 0}, |
+ { ".debug_gdb_scripts", "__debug_gdb_scri", |
+ SEC_DEBUGGING, BFD_MACH_O_S_REGULAR, |
+ BFD_MACH_O_S_ATTR_DEBUG, 0}, |
{ NULL, NULL, 0, 0, 0, 0} |
}; |
@@ -287,7 +288,7 @@ static const char dsym_subdir[] = ".dSYM/Contents/Resources/DWARF"; |
/* Fetch the translation from a Mach-O section designation (segment, section) |
as a bfd short name, if one exists. Otherwise return NULL. |
- |
+ |
Allow the segment and section names to be unterminated 16 byte arrays. */ |
const mach_o_section_name_xlat * |
@@ -315,11 +316,11 @@ bfd_mach_o_section_data_for_mach_sect (bfd *abfd, const char *segname, |
BFD_MACH_O_SECTNAME_SIZE) == 0) |
return sec; |
- return NULL; |
+ return NULL; |
} |
/* If the bfd_name for this section is a 'canonical' form for which we |
- know the Mach-O data, return the segment name and the data for the |
+ know the Mach-O data, return the segment name and the data for the |
Mach-O equivalent. Otherwise return NULL. */ |
const mach_o_section_name_xlat * |
@@ -353,12 +354,12 @@ bfd_mach_o_section_data_for_bfd_name (bfd *abfd, const char *bfd_name, |
return sec; |
} |
- return NULL; |
+ return NULL; |
} |
/* Convert Mach-O section name to BFD. |
- Try to use standard/canonical names, for which we have tables including |
+ Try to use standard/canonical names, for which we have tables including |
default flag settings - which are returned. Otherwise forge a new name |
in the form "<segmentname>.<sectionname>" this will be prefixed with |
LC_SEGMENT. if the segment name does not begin with an underscore. |
@@ -380,7 +381,7 @@ bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, const char *segname, |
*name = NULL; |
*flags = SEC_NO_FLAGS; |
- /* First search for a canonical name... |
+ /* First search for a canonical name... |
xlat will be non-null if there is an entry for segname, secname. */ |
xlat = bfd_mach_o_section_data_for_mach_sect (abfd, segname, secname); |
if (xlat) |
@@ -423,7 +424,7 @@ bfd_mach_o_convert_section_name_to_bfd (bfd *abfd, const char *segname, |
return the translation table - which contains defaults for flags, |
type, attribute and default alignment data. |
- Otherwise, expand the bfd_name (assumed to be in the form |
+ Otherwise, expand the bfd_name (assumed to be in the form |
"[LC_SEGMENT.]<segmentname>.<sectionname>") and return NULL. */ |
static const mach_o_section_name_xlat * |
@@ -558,11 +559,11 @@ bfd_mach_o_bfd_copy_private_section_data (bfd *ibfd ATTRIBUTE_UNUSED, |
{ |
if (osection->used_by_bfd == NULL) |
osection->used_by_bfd = isection->used_by_bfd; |
- else |
+ else |
if (isection->used_by_bfd != NULL) |
- memcpy (osection->used_by_bfd, isection->used_by_bfd, |
+ memcpy (osection->used_by_bfd, isection->used_by_bfd, |
sizeof (bfd_mach_o_section)); |
- |
+ |
if (osection->used_by_bfd != NULL) |
((bfd_mach_o_section *)osection->used_by_bfd)->bfdsection = osection; |
@@ -590,7 +591,7 @@ bfd_mach_o_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) |
/* This allows us to set up to 32 bits of flags (unless we invent some |
fiendish scheme to subdivide). For now, we'll just set the file flags |
without error checking - just overwrite. */ |
- |
+ |
bfd_boolean |
bfd_mach_o_bfd_set_private_flags (bfd *abfd, flagword flags) |
{ |
@@ -706,7 +707,7 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd, |
names = (char *) (s + count); |
nul_name = names; |
*names++ = 0; |
- |
+ |
n = 0; |
for (i = 0; i < mdata->nsects; i++) |
{ |
@@ -714,7 +715,7 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd, |
unsigned int first, last; |
bfd_vma addr; |
bfd_vma entry_size; |
- |
+ |
switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK) |
{ |
case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS: |
@@ -733,7 +734,7 @@ bfd_mach_o_get_synthetic_symtab (bfd *abfd, |
s->section = sec->bfdsection; |
s->value = addr - sec->addr; |
s->udata.p = NULL; |
- |
+ |
if (isym < symtab->nsyms |
&& symtab->symbols[isym].symbol.name) |
{ |
@@ -989,7 +990,7 @@ bfd_mach_o_swap_in_non_scattered_reloc (bfd *abfd, bfd_mach_o_reloc_info *rel, |
rel->r_value = (fields[0] << 16) | (fields[1] << 8) | fields[2]; |
rel->r_type = (info >> BFD_MACH_O_BE_TYPE_SHIFT) & BFD_MACH_O_TYPE_MASK; |
rel->r_pcrel = (info & BFD_MACH_O_BE_PCREL) ? 1 : 0; |
- rel->r_length = (info >> BFD_MACH_O_BE_LENGTH_SHIFT) |
+ rel->r_length = (info >> BFD_MACH_O_BE_LENGTH_SHIFT) |
& BFD_MACH_O_LENGTH_MASK; |
rel->r_extern = (info & BFD_MACH_O_BE_EXTERN) ? 1 : 0; |
} |
@@ -998,7 +999,7 @@ bfd_mach_o_swap_in_non_scattered_reloc (bfd *abfd, bfd_mach_o_reloc_info *rel, |
rel->r_value = (fields[2] << 16) | (fields[1] << 8) | fields[0]; |
rel->r_type = (info >> BFD_MACH_O_LE_TYPE_SHIFT) & BFD_MACH_O_TYPE_MASK; |
rel->r_pcrel = (info & BFD_MACH_O_LE_PCREL) ? 1 : 0; |
- rel->r_length = (info >> BFD_MACH_O_LE_LENGTH_SHIFT) |
+ rel->r_length = (info >> BFD_MACH_O_LE_LENGTH_SHIFT) |
& BFD_MACH_O_LENGTH_MASK; |
rel->r_extern = (info & BFD_MACH_O_LE_EXTERN) ? 1 : 0; |
} |
@@ -1018,7 +1019,7 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd, |
addr = bfd_get_32 (abfd, raw->r_address); |
res->sym_ptr_ptr = NULL; |
res->addend = 0; |
- |
+ |
if (addr & BFD_MACH_O_SR_SCATTERED) |
{ |
unsigned int j; |
@@ -1056,22 +1057,35 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd, |
else |
{ |
unsigned int num; |
- |
+ |
/* Non-scattered relocation. */ |
reloc.r_scattered = 0; |
- |
+ |
/* The value and info fields have to be extracted dependent on target |
endian-ness. */ |
bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum); |
num = reloc.r_value; |
if (reloc.r_extern) |
- sym = syms + num; |
- else if (reloc.r_scattered |
- || (reloc.r_type != BFD_MACH_O_GENERIC_RELOC_PAIR)) |
+ { |
+ /* An external symbol number. */ |
+ sym = syms + num; |
+ } |
+ else if (num == 0x00ffffff) |
+ { |
+ /* The 'symnum' in a non-scattered PAIR is 0x00ffffff. But as this |
+ is generic code, we don't know wether this is really a PAIR. |
+ This value is almost certainly not a valid section number, hence |
+ this specific case to avoid an assertion failure. |
+ Target specific swap_reloc_in routine should adjust that. */ |
+ sym = bfd_abs_section_ptr->symbol_ptr_ptr; |
+ } |
+ else |
{ |
+ /* A section number. */ |
BFD_ASSERT (num != 0); |
BFD_ASSERT (num <= mdata->nsects); |
+ |
sym = mdata->sections[num - 1]->bfdsection->symbol_ptr_ptr; |
/* For a symbol defined in section S, the addend (stored in the |
binary) contains the address of the section. To comply with |
@@ -1080,26 +1094,23 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd, |
the vma of the section. */ |
res->addend = -mdata->sections[num - 1]->addr; |
} |
- else /* ... The 'symnum' in a non-scattered PAIR will be 0x00ffffff. */ |
- { |
- /* Pairs for PPC LO/HI/HA are not scattered, but contain the offset |
- in the lower 16bits of the address value. So we have to find the |
- 'symbol' from the preceding reloc. We do this even thoough the |
- section symbol is probably not needed here, because NULL symbol |
- values cause an assert in generic BFD code. */ |
- sym = (res - 1)->sym_ptr_ptr; |
- } |
+ /* Note: Pairs for PPC LO/HI/HA are not scattered, but contain the offset |
+ in the lower 16bits of the address value. So we have to find the |
+ 'symbol' from the preceding reloc. We do this even though the |
+ section symbol is probably not needed here, because NULL symbol |
+ values cause an assert in generic BFD code. This must be done in |
+ the PPC swap_reloc_in routine. */ |
res->sym_ptr_ptr = sym; |
- |
+ |
/* The 'address' is just r_address. |
??? maybe this should be masked with 0xffffff for safety. */ |
res->address = addr; |
reloc.r_address = addr; |
} |
- |
- /* We have set up a reloc with all the information present, so the swapper can |
- modify address, value and addend fields, if necessary, to convey information |
- in the generic BFD reloc that is mach-o specific. */ |
+ |
+ /* We have set up a reloc with all the information present, so the swapper |
+ can modify address, value and addend fields, if necessary, to convey |
+ information in the generic BFD reloc that is mach-o specific. */ |
if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc)) |
return -1; |
@@ -1403,7 +1414,7 @@ bfd_mach_o_write_segment_32 (bfd *abfd, bfd_mach_o_load_command *command) |
bfd_h_put_32 (abfd, seg->initprot, raw.initprot); |
bfd_h_put_32 (abfd, seg->nsects, raw.nsects); |
bfd_h_put_32 (abfd, seg->flags, raw.flags); |
- |
+ |
if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0 |
|| bfd_bwrite (&raw, sizeof (raw), abfd) != sizeof (raw)) |
return -1; |
@@ -1485,7 +1496,7 @@ bfd_mach_o_write_symtab (bfd *abfd, bfd_mach_o_load_command *command) |
{ |
bfd_size_type str_index; |
bfd_mach_o_asymbol *s = (bfd_mach_o_asymbol *)symbols[i]; |
- |
+ |
if (s->symbol.name == 0 || s->symbol.name[0] == '\0') |
/* An index of 0 always means the empty string. */ |
str_index = 0; |
@@ -1652,7 +1663,7 @@ bfd_mach_o_write_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) |
return FALSE; |
} |
} |
- |
+ |
if (cmd->nindirectsyms > 0) |
{ |
unsigned int i; |
@@ -1667,7 +1678,7 @@ bfd_mach_o_write_dysymtab (bfd *abfd, bfd_mach_o_load_command *command) |
bfd_h_put_32 (abfd, cmd->indirect_syms[i], &raw); |
if (bfd_bwrite (raw, sizeof (raw), abfd) != sizeof (raw)) |
return FALSE; |
- } |
+ } |
} |
if (cmd->nextrefsyms != 0) |
@@ -1848,7 +1859,7 @@ bfd_mach_o_mangle_symbols (bfd *abfd) |
} |
else |
s->n_type = BFD_MACH_O_N_SECT; |
- |
+ |
if (s->symbol.flags & BSF_GLOBAL) |
s->n_type |= BFD_MACH_O_N_EXT; |
} |
@@ -1889,7 +1900,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) |
unsigned nsect; |
nsect = bfd_count_sections (abfd); |
- |
+ |
/* Don't do it if it's already set - assume the application knows what it's |
doing. */ |
if (mdata->nsects == nsect |
@@ -1897,7 +1908,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) |
return TRUE; |
mdata->nsects = nsect; |
- mdata->sections = bfd_alloc (abfd, |
+ mdata->sections = bfd_alloc (abfd, |
mdata->nsects * sizeof (bfd_mach_o_section *)); |
if (mdata->sections == NULL) |
return FALSE; |
@@ -1908,7 +1919,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) |
" maximum is 255,\n"), nsect); |
/* Create Mach-O sections. |
- Section type, attribute and align should have been set when the |
+ Section type, attribute and align should have been set when the |
section was created - either read in or specified. */ |
target_index = 0; |
for (sec = abfd->sections; sec; sec = sec->next) |
@@ -1921,7 +1932,7 @@ bfd_mach_o_mangle_sections (bfd *abfd, bfd_mach_o_data_struct *mdata) |
msect->addr = bfd_get_section_vma (abfd, sec); |
msect->size = bfd_get_section_size (sec); |
- /* Use the largest alignment set, in case it was bumped after the |
+ /* Use the largest alignment set, in case it was bumped after the |
section was created. */ |
msect->align = msect->align > bfd_align ? msect->align : bfd_align; |
@@ -2049,15 +2060,15 @@ bfd_mach_o_set_section_flags_from_bfd (bfd *abfd ATTRIBUTE_UNUSED, asection *sec |
/* Count the number of sections in the list for the segment named. |
The special case of NULL or "" for the segment name is valid for |
- an MH_OBJECT file and means 'all sections available'. |
- |
- Requires that the sections table in mdata be filled in. |
+ an MH_OBJECT file and means 'all sections available'. |
+ |
+ Requires that the sections table in mdata be filled in. |
Returns the number of sections (0 is valid). |
Any number > 255 signals an invalid section count, although we will, |
perhaps, allow the file to be written (in line with Darwin tools up |
- to XCode 4). |
- |
+ to XCode 4). |
+ |
A section count of (unsigned long) -1 signals a definite error. */ |
static unsigned long |
@@ -2112,11 +2123,11 @@ bfd_mach_o_build_seg_command (const char *segment, |
seg->sect_head = NULL; |
seg->sect_tail = NULL; |
- /* Append sections to the segment. |
+ /* Append sections to the segment. |
This is a little tedious, we have to honor the need to account zerofill |
sections after all the rest. This forces us to do the calculation of |
- total vmsize in three passes so that any alignment increments are |
+ total vmsize in three passes so that any alignment increments are |
properly accounted. */ |
for (i = 0; i < mdata->nsects; ++i) |
@@ -2126,7 +2137,7 @@ bfd_mach_o_build_seg_command (const char *segment, |
/* If we're not making an MH_OBJECT, check whether this section is from |
our segment, and skip if not. Otherwise, just add all sections. */ |
- if (! is_mho |
+ if (! is_mho |
&& strncmp (segment, s->segname, BFD_MACH_O_SEGNAME_SIZE) != 0) |
continue; |
@@ -2134,11 +2145,11 @@ bfd_mach_o_build_seg_command (const char *segment, |
placed in the file in source sequence. */ |
bfd_mach_o_append_section_to_segment (seg, sec); |
s->offset = 0; |
- |
- /* Zerofill sections have zero file size & offset, |
+ |
+ /* Zerofill sections have zero file size & offset, |
and are not written. */ |
if ((s->flags & BFD_MACH_O_SECTION_TYPE_MASK) == BFD_MACH_O_S_ZEROFILL |
- || (s->flags & BFD_MACH_O_SECTION_TYPE_MASK) |
+ || (s->flags & BFD_MACH_O_SECTION_TYPE_MASK) |
== BFD_MACH_O_S_GB_ZEROFILL) |
continue; |
@@ -2166,7 +2177,7 @@ bfd_mach_o_build_seg_command (const char *segment, |
if ((s->flags & BFD_MACH_O_SECTION_TYPE_MASK) != BFD_MACH_O_S_ZEROFILL) |
continue; |
- if (! is_mho |
+ if (! is_mho |
&& strncmp (segment, s->segname, BFD_MACH_O_SEGNAME_SIZE) != 0) |
continue; |
@@ -2181,11 +2192,11 @@ bfd_mach_o_build_seg_command (const char *segment, |
for (i = 0; i < mdata->nsects; ++i) |
{ |
bfd_mach_o_section *s = mdata->sections[i]; |
- |
+ |
if ((s->flags & BFD_MACH_O_SECTION_TYPE_MASK) != BFD_MACH_O_S_GB_ZEROFILL) |
continue; |
- if (! is_mho |
+ if (! is_mho |
&& strncmp (segment, s->segname, BFD_MACH_O_SEGNAME_SIZE) != 0) |
continue; |
@@ -2203,7 +2214,7 @@ bfd_mach_o_build_seg_command (const char *segment, |
{ |
bfd_mach_o_section *ms = mdata->sections[i]; |
asection *sec = ms->bfdsection; |
- |
+ |
if ((ms->nreloc = sec->reloc_count) == 0) |
{ |
ms->reloff = 0; |
@@ -2287,8 +2298,8 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, |
} |
dsym->nextdefsym = i - dsym->nlocalsym; |
dsym->iundefsym = dsym->nextdefsym + dsym->iextdefsym; |
- dsym->nundefsym = bfd_get_symcount (abfd) |
- - dsym->nlocalsym |
+ dsym->nundefsym = bfd_get_symcount (abfd) |
+ - dsym->nlocalsym |
- dsym->nextdefsym; |
} |
else |
@@ -2309,11 +2320,11 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, |
mdata->filelen = FILE_ALIGN (mdata->filelen, 2); |
dsym->indirectsymoff = mdata->filelen; |
mdata->filelen += dsym->nindirectsyms * 4; |
- |
+ |
dsym->indirect_syms = bfd_zalloc (abfd, dsym->nindirectsyms * 4); |
if (dsym->indirect_syms == NULL) |
return FALSE; |
- |
+ |
n = 0; |
for (i = 0; i < mdata->nsects; ++i) |
{ |
@@ -2327,7 +2338,7 @@ bfd_mach_o_build_dysymtab_command (bfd *abfd, |
{ |
unsigned j, num; |
bfd_mach_o_asymbol **isyms = sec->indirect_syms; |
- |
+ |
num = bfd_mach_o_section_get_nbr_indirect (abfd, sec); |
if (isyms == NULL || num == 0) |
break; |
@@ -2403,7 +2414,7 @@ bfd_mach_o_build_commands (bfd *abfd) |
a command (segment) to contain all the sections, |
command for the symbol table, |
- a command for the dysymtab. |
+ a command for the dysymtab. |
??? maybe we should assert that this is an MH_OBJECT? */ |
@@ -2449,7 +2460,7 @@ bfd_mach_o_build_commands (bfd *abfd) |
return FALSE; |
if (segcmd_idx >= 0) |
- { |
+ { |
bfd_mach_o_load_command *cmd = &mdata->commands[segcmd_idx]; |
bfd_mach_o_segment_command *seg = &cmd->command.segment; |
@@ -2482,7 +2493,7 @@ bfd_mach_o_build_commands (bfd *abfd) |
{ |
/* Init symtab command. */ |
bfd_mach_o_load_command *cmd = &mdata->commands[symtab_idx]; |
- |
+ |
cmd->type = BFD_MACH_O_LC_SYMTAB; |
cmd->offset = base_offset; |
if (segcmd_idx >= 0) |
@@ -2503,10 +2514,10 @@ bfd_mach_o_build_commands (bfd *abfd) |
cmd->type = BFD_MACH_O_LC_DYSYMTAB; |
if (symtab_idx >= 0) |
- cmd->offset = mdata->commands[symtab_idx].offset |
+ cmd->offset = mdata->commands[symtab_idx].offset |
+ mdata->commands[symtab_idx].len; |
else if (segcmd_idx >= 0) |
- cmd->offset = mdata->commands[segcmd_idx].offset |
+ cmd->offset = mdata->commands[segcmd_idx].offset |
+ mdata->commands[segcmd_idx].len; |
else |
cmd->offset = base_offset; |
@@ -2522,13 +2533,13 @@ bfd_mach_o_build_commands (bfd *abfd) |
/* So, now we have sized the commands and the filelen set to that. |
Now we can build the segment command and set the section file offsets. */ |
if (segcmd_idx >= 0 |
- && ! bfd_mach_o_build_seg_command |
+ && ! bfd_mach_o_build_seg_command |
(NULL, mdata, &mdata->commands[segcmd_idx].command.segment)) |
return FALSE; |
/* If we're doing a dysymtab, cmd points to its load command. */ |
if (dysymtab_idx >= 0 |
- && ! bfd_mach_o_build_dysymtab_command (abfd, mdata, |
+ && ! bfd_mach_o_build_dysymtab_command (abfd, mdata, |
&mdata->commands[dysymtab_idx])) |
return FALSE; |
@@ -2681,9 +2692,9 @@ bfd_mach_o_new_section_hook (bfd *abfd, asection *sec) |
if (xlat != NULL) |
{ |
s->flags = xlat->macho_sectype | xlat->macho_secattr; |
- s->align = xlat->sectalign > bfdalign ? xlat->sectalign |
+ s->align = xlat->sectalign > bfdalign ? xlat->sectalign |
: bfdalign; |
- bfd_set_section_alignment (abfd, sec, s->align); |
+ (void) bfd_set_section_alignment (abfd, sec, s->align); |
bfd_flags = bfd_get_section_flags (abfd, sec); |
if (bfd_flags == SEC_NO_FLAGS) |
bfd_set_section_flags (abfd, sec, xlat->bfd_flags); |
@@ -3656,6 +3667,48 @@ bfd_mach_o_read_encryption_info (bfd *abfd, bfd_mach_o_load_command *command) |
return TRUE; |
} |
+static bfd_boolean |
+bfd_mach_o_read_main (bfd *abfd, bfd_mach_o_load_command *command) |
+{ |
+ bfd_mach_o_main_command *cmd = &command->command.main; |
+ struct mach_o_entry_point_command_external raw; |
+ |
+ if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0 |
+ || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw)) |
+ return FALSE; |
+ |
+ cmd->entryoff = bfd_get_64 (abfd, raw.entryoff); |
+ cmd->stacksize = bfd_get_64 (abfd, raw.stacksize); |
+ return TRUE; |
+} |
+ |
+static bfd_boolean |
+bfd_mach_o_read_source_version (bfd *abfd, bfd_mach_o_load_command *command) |
+{ |
+ bfd_mach_o_source_version_command *cmd = &command->command.source_version; |
+ struct mach_o_source_version_command_external raw; |
+ bfd_uint64_t ver; |
+ |
+ if (bfd_seek (abfd, command->offset + BFD_MACH_O_LC_SIZE, SEEK_SET) != 0 |
+ || bfd_bread (&raw, sizeof (raw), abfd) != sizeof (raw)) |
+ return FALSE; |
+ |
+ ver = bfd_get_64 (abfd, raw.version); |
+ /* Note: we use a serie of shift to avoid shift > 32 (for which gcc |
+ generates warnings) in case of the host doesn't support 64 bit |
+ integers. */ |
+ cmd->e = ver & 0x3ff; |
+ ver >>= 10; |
+ cmd->d = ver & 0x3ff; |
+ ver >>= 10; |
+ cmd->c = ver & 0x3ff; |
+ ver >>= 10; |
+ cmd->b = ver & 0x3ff; |
+ ver >>= 10; |
+ cmd->a = ver & 0xffffff; |
+ return TRUE; |
+} |
+ |
static int |
bfd_mach_o_read_segment (bfd *abfd, |
bfd_mach_o_load_command *command, |
@@ -3832,6 +3885,8 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command) |
case BFD_MACH_O_LC_CODE_SIGNATURE: |
case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO: |
case BFD_MACH_O_LC_FUNCTION_STARTS: |
+ case BFD_MACH_O_LC_DATA_IN_CODE: |
+ case BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS: |
if (bfd_mach_o_read_linkedit (abfd, command) != 0) |
return -1; |
break; |
@@ -3848,6 +3903,14 @@ bfd_mach_o_read_command (bfd *abfd, bfd_mach_o_load_command *command) |
if (!bfd_mach_o_read_version_min (abfd, command)) |
return -1; |
break; |
+ case BFD_MACH_O_LC_MAIN: |
+ if (!bfd_mach_o_read_main (abfd, command)) |
+ return -1; |
+ break; |
+ case BFD_MACH_O_LC_SOURCE_VERSION: |
+ if (!bfd_mach_o_read_source_version (abfd, command)) |
+ return -1; |
+ break; |
default: |
(*_bfd_error_handler)(_("%B: unknown load command 0x%lx"), |
abfd, (unsigned long) command->type); |
@@ -3917,9 +3980,22 @@ bfd_mach_o_scan_start_address (bfd *abfd) |
cmd = &mdata->commands[i].command.thread; |
break; |
} |
+ else if (mdata->commands[i].type == BFD_MACH_O_LC_MAIN |
+ && mdata->nsects > 1) |
+ { |
+ bfd_mach_o_main_command *main_cmd = &mdata->commands[i].command.main; |
+ bfd_mach_o_section *text_sect = mdata->sections[0]; |
+ if (text_sect) |
+ { |
+ abfd->start_address = main_cmd->entryoff |
+ + (text_sect->addr - text_sect->offset); |
+ return TRUE; |
+ } |
+ } |
+ /* An object file has no start address, so do not fail if not found. */ |
if (cmd == NULL) |
- return FALSE; |
+ return TRUE; |
/* FIXME: create a subtarget hook ? */ |
for (i = 0; i < cmd->nflavours; i++) |
@@ -4059,10 +4135,11 @@ bfd_mach_o_scan (bfd *abfd, |
} |
} |
- if (bfd_mach_o_scan_start_address (abfd) < 0) |
+ /* Sections should be flatten before scanning start address. */ |
+ bfd_mach_o_flatten_sections (abfd); |
+ if (!bfd_mach_o_scan_start_address (abfd)) |
return FALSE; |
- bfd_mach_o_flatten_sections (abfd); |
return TRUE; |
} |
@@ -4071,7 +4148,7 @@ bfd_mach_o_mkobject_init (bfd *abfd) |
{ |
bfd_mach_o_data_struct *mdata = NULL; |
- mdata = bfd_alloc (abfd, sizeof (bfd_mach_o_data_struct)); |
+ mdata = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct)); |
if (mdata == NULL) |
return FALSE; |
abfd->tdata.mach_o_data = mdata; |
@@ -4115,10 +4192,9 @@ bfd_mach_o_header_p (bfd *abfd, |
bfd_mach_o_filetype filetype, |
bfd_mach_o_cpu_type cputype) |
{ |
- struct bfd_preserve preserve; |
bfd_mach_o_header header; |
+ bfd_mach_o_data_struct *mdata; |
- preserve.marker = NULL; |
if (!bfd_mach_o_read_header (abfd, &header)) |
goto wrong; |
@@ -4164,24 +4240,19 @@ bfd_mach_o_header_p (bfd *abfd, |
} |
} |
- preserve.marker = bfd_zalloc (abfd, sizeof (bfd_mach_o_data_struct)); |
- if (preserve.marker == NULL |
- || !bfd_preserve_save (abfd, &preserve)) |
+ mdata = (bfd_mach_o_data_struct *) bfd_zalloc (abfd, sizeof (*mdata)); |
+ if (mdata == NULL) |
goto fail; |
- if (!bfd_mach_o_scan (abfd, &header, |
- (bfd_mach_o_data_struct *) preserve.marker)) |
+ if (!bfd_mach_o_scan (abfd, &header, mdata)) |
goto wrong; |
- bfd_preserve_finish (abfd, &preserve); |
return abfd->xvec; |
wrong: |
bfd_set_error (bfd_error_wrong_format); |
fail: |
- if (preserve.marker != NULL) |
- bfd_preserve_restore (abfd, &preserve); |
return NULL; |
} |
@@ -4294,7 +4365,7 @@ bfd_mach_o_fat_member_init (bfd *abfd, |
abfd->filename = name; |
} |
- areltdata = bfd_zalloc (abfd, sizeof (struct areltdata)); |
+ areltdata = bfd_zmalloc (sizeof (struct areltdata)); |
areltdata->parsed_size = entry->size; |
abfd->arelt_data = areltdata; |
abfd->iostream = NULL; |
@@ -4836,7 +4907,7 @@ bfd_mach_o_find_nearest_line (bfd *abfd, |
if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, |
section, symbols, offset, |
filename_ptr, functionname_ptr, |
- line_ptr, 0, |
+ line_ptr, NULL, 0, |
&mdata->dwarf2_find_line_info)) |
return TRUE; |
return FALSE; |
@@ -4864,6 +4935,9 @@ bfd_mach_o_close_and_cleanup (bfd *abfd) |
} |
} |
+ if (bfd_get_format (abfd) == bfd_archive |
+ && abfd->xvec == &mach_o_fat_vec) |
+ return TRUE; |
return _bfd_generic_close_and_cleanup (abfd); |
} |
@@ -4882,7 +4956,7 @@ bfd_boolean bfd_mach_o_free_cached_info (bfd *abfd) |
return TRUE; |
} |
-#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup |
+#define bfd_mach_o_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup |
#define bfd_mach_o_bfd_reloc_name_lookup _bfd_norelocs_bfd_reloc_name_lookup |
#define bfd_mach_o_swap_reloc_in NULL |