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;
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
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;
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,
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;
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);
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;
}
}
+ if (bfd_get_format (abfd) == bfd_archive
+ && abfd->xvec == &mach_o_fat_vec)
+ return TRUE;
return _bfd_generic_close_and_cleanup (abfd);
}