aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog26
-rw-r--r--bfd/mach-o-i386.c31
-rw-r--r--bfd/mach-o-target.c2
-rw-r--r--bfd/mach-o-x86-64.c39
-rw-r--r--bfd/mach-o.c175
-rw-r--r--bfd/mach-o.h8
6 files changed, 175 insertions, 106 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b70456d..b580b89 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -7,6 +7,32 @@
2015-11-18 Tristan Gingold <gingold@adacore.com>
+ * mach-o.h (bfd_mach_o_swap_in_non_scattered_reloc)
+ (bfd_mach_o_canonicalize_non_scattered_reloc)
+ (bfd_mach_o_pre_canonicalize_one_reloc): Declare.
+ (bfd_mach_o_backend_data): Rename field
+ _bfd_mach_o_swap_reloc_in to _bfd_mach_o_canonicalize_one_reloc.
+ * mach-o.c (bfd_mach_o_swap_in_non_scattered_reloc): Now public.
+ (bfd_mach_o_canonicalize_non_scattered_reloc): Renames from
+ bfd_mach_o_canonicalize_one_reloc.
+ (bfd_mach_o_pre_canonicalize_one_reloc): New function.
+ (bfd_mach_o_canonicalize_relocs): Adjust.
+ (bfd_mach_o_canonicalize_relocs): Rename define from
+ bfd_mach_o_swap_reloc_in.
+ * mach-o-target.c (TARGET_NAME_BACKEND): Use
+ bfd_mach_o_canonicalize_one_reloc instead of
+ bfd_mach_o_swap_reloc_in.
+ * mach-o-i386.c (bfd_mach_o_i386_canonicalize_one_reloc): Renames
+ from bfd_mach_o_i386_swap_reloc_in and adjust.
+ (bfd_mach_o_canonicalize_one_reloc): Renames from
+ bfd_mach_o_i386_canonicalize_one_reloc.
+ * mach-o-x86_64.c (bfd_mach_o_x86_64_canonicalize_one_reloc): Renames
+ from bfd_mach_o_x86_64_swap_reloc_in and adjust.
+ (bfd_mach_o_canonicalize_one_reloc): Renames from
+ bfd_mach_o_x86_64_canonicalize_one_reloc.
+
+2015-11-18 Tristan Gingold <gingold@adacore.com>
+
* mach-o.h (struct mach_o_data_struct): Add hdr_offset field.
(bfd_mach_o_fat_archive_p): Renames prototype.
(bfd_mach_o_fat_openr_next_archived_file): Renames.
diff --git a/bfd/mach-o-i386.c b/bfd/mach-o-i386.c
index b409022..41b2976 100644
--- a/bfd/mach-o-i386.c
+++ b/bfd/mach-o-i386.c
@@ -112,20 +112,27 @@ static reloc_howto_type i386_howto_table[]=
};
static bfd_boolean
-bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
+bfd_mach_o_i386_canonicalize_one_reloc (bfd *abfd,
+ struct mach_o_reloc_info_external *raw,
+ arelent *res, asymbol **syms)
{
- if (reloc->r_scattered)
+ bfd_mach_o_reloc_info reloc;
+
+ if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
+ return FALSE;
+
+ if (reloc.r_scattered)
{
- switch (reloc->r_type)
+ switch (reloc.r_type)
{
case BFD_MACH_O_GENERIC_RELOC_PAIR:
- if (reloc->r_length == 2)
+ if (reloc.r_length == 2)
{
res->howto = &i386_howto_table[7];
res->address = res[-1].address;
return TRUE;
}
- else if (reloc->r_length == 1)
+ else if (reloc.r_length == 1)
{
res->howto = &i386_howto_table[10];
res->address = res[-1].address;
@@ -133,24 +140,24 @@ bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
}
return FALSE;
case BFD_MACH_O_GENERIC_RELOC_SECTDIFF:
- if (reloc->r_length == 2)
+ if (reloc.r_length == 2)
{
res->howto = &i386_howto_table[5];
return TRUE;
}
- else if (reloc->r_length == 1)
+ else if (reloc.r_length == 1)
{
res->howto = &i386_howto_table[8];
return TRUE;
}
return FALSE;
case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF:
- if (reloc->r_length == 2)
+ if (reloc.r_length == 2)
{
res->howto = &i386_howto_table[6];
return TRUE;
}
- else if (reloc->r_length == 1)
+ else if (reloc.r_length == 1)
{
res->howto = &i386_howto_table[9];
return TRUE;
@@ -162,10 +169,10 @@ bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
}
else
{
- switch (reloc->r_type)
+ switch (reloc.r_type)
{
case BFD_MACH_O_GENERIC_RELOC_VANILLA:
- switch ((reloc->r_length << 1) | reloc->r_pcrel)
+ switch ((reloc.r_length << 1) | reloc.r_pcrel)
{
case 0: /* len = 0, pcrel = 0 */
res->howto = &i386_howto_table[2];
@@ -384,7 +391,7 @@ const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] =
{ NULL, NULL }
};
-#define bfd_mach_o_swap_reloc_in bfd_mach_o_i386_swap_reloc_in
+#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_i386_canonicalize_one_reloc
#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
diff --git a/bfd/mach-o-target.c b/bfd/mach-o-target.c
index 3915dc0..9977db1 100644
--- a/bfd/mach-o-target.c
+++ b/bfd/mach-o-target.c
@@ -104,7 +104,7 @@ static const bfd_mach_o_backend_data TARGET_NAME_BACKEND =
{
TARGET_ARCHITECTURE,
TARGET_PAGESIZE,
- bfd_mach_o_swap_reloc_in,
+ bfd_mach_o_canonicalize_one_reloc,
bfd_mach_o_swap_reloc_out,
bfd_mach_o_print_thread,
bfd_mach_o_tgt_seg_table,
diff --git a/bfd/mach-o-x86-64.c b/bfd/mach-o-x86-64.c
index b0eef2c..5914ae8 100644
--- a/bfd/mach-o-x86-64.c
+++ b/bfd/mach-o-x86-64.c
@@ -120,18 +120,25 @@ static reloc_howto_type x86_64_howto_table[]=
};
static bfd_boolean
-bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
+bfd_mach_o_x86_64_canonicalize_one_reloc (bfd *abfd,
+ struct mach_o_reloc_info_external *raw,
+ arelent *res, asymbol **syms)
{
+ bfd_mach_o_reloc_info reloc;
+
+ if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
+ return FALSE;
+
/* On x86-64, scattered relocs are not used. */
- if (reloc->r_scattered)
+ if (reloc.r_scattered)
return FALSE;
- switch (reloc->r_type)
+ switch (reloc.r_type)
{
case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
- if (reloc->r_pcrel)
+ if (reloc.r_pcrel)
return FALSE;
- switch (reloc->r_length)
+ switch (reloc.r_length)
{
case 2:
res->howto = &x86_64_howto_table[1];
@@ -143,16 +150,16 @@ bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
return FALSE;
}
case BFD_MACH_O_X86_64_RELOC_SIGNED:
- if (reloc->r_length == 2 && reloc->r_pcrel)
+ if (reloc.r_length == 2 && reloc.r_pcrel)
{
res->howto = &x86_64_howto_table[2];
return TRUE;
}
break;
case BFD_MACH_O_X86_64_RELOC_BRANCH:
- if (!reloc->r_pcrel)
+ if (!reloc.r_pcrel)
return FALSE;
- switch (reloc->r_length)
+ switch (reloc.r_length)
{
case 2:
res->howto = &x86_64_howto_table[6];
@@ -162,23 +169,23 @@ bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
}
break;
case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
- if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
+ if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
{
res->howto = &x86_64_howto_table[7];
return TRUE;
}
break;
case BFD_MACH_O_X86_64_RELOC_GOT:
- if (reloc->r_length == 2 && reloc->r_pcrel && reloc->r_extern)
+ if (reloc.r_length == 2 && reloc.r_pcrel && reloc.r_extern)
{
res->howto = &x86_64_howto_table[10];
return TRUE;
}
break;
case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
- if (reloc->r_pcrel)
+ if (reloc.r_pcrel)
return FALSE;
- switch (reloc->r_length)
+ switch (reloc.r_length)
{
case 2:
res->howto = &x86_64_howto_table[8];
@@ -191,21 +198,21 @@ bfd_mach_o_x86_64_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
}
break;
case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
- if (reloc->r_length == 2 && reloc->r_pcrel)
+ if (reloc.r_length == 2 && reloc.r_pcrel)
{
res->howto = &x86_64_howto_table[3];
return TRUE;
}
break;
case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
- if (reloc->r_length == 2 && reloc->r_pcrel)
+ if (reloc.r_length == 2 && reloc.r_pcrel)
{
res->howto = &x86_64_howto_table[4];
return TRUE;
}
break;
case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
- if (reloc->r_length == 2 && reloc->r_pcrel)
+ if (reloc.r_length == 2 && reloc.r_pcrel)
{
res->howto = &x86_64_howto_table[5];
return TRUE;
@@ -344,7 +351,7 @@ const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
{ NULL, NULL }
};
-#define bfd_mach_o_swap_reloc_in bfd_mach_o_x86_64_swap_reloc_in
+#define bfd_mach_o_canonicalize_one_reloc bfd_mach_o_x86_64_canonicalize_one_reloc
#define bfd_mach_o_swap_reloc_out bfd_mach_o_x86_64_swap_reloc_out
#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index b1bac05..bbd8d1e 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -1299,7 +1299,7 @@ bfd_mach_o_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
/* In addition to the need to byte-swap the symbol number, the bit positions
of the fields in the relocation information vary per target endian-ness. */
-static void
+void
bfd_mach_o_swap_in_non_scattered_reloc (bfd *abfd, bfd_mach_o_reloc_info *rel,
unsigned char *fields)
{
@@ -1325,17 +1325,87 @@ bfd_mach_o_swap_in_non_scattered_reloc (bfd *abfd, bfd_mach_o_reloc_info *rel,
}
}
-static int
-bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
- struct mach_o_reloc_info_external *raw,
- arelent *res, asymbol **syms)
+/* Set syms_ptr_ptr and addend of RES. */
+
+bfd_boolean
+bfd_mach_o_canonicalize_non_scattered_reloc (bfd *abfd,
+ bfd_mach_o_reloc_info *reloc,
+ 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;
+ unsigned int num;
asymbol **sym;
+ /* Non-scattered relocation. */
+ reloc->r_scattered = 0;
+ res->addend = 0;
+
+ num = reloc->r_value;
+
+ if (reloc->r_extern)
+ {
+ /* PR 17512: file: 8396-1185-0.004. */
+ if (num >= (unsigned) bfd_mach_o_count_symbols (abfd))
+ sym = bfd_und_section_ptr->symbol_ptr_ptr;
+ else if (syms == NULL)
+ sym = bfd_und_section_ptr->symbol_ptr_ptr;
+ else
+ /* An external symbol number. */
+ sym = syms + num;
+ }
+ else if (num == 0x00ffffff || num == 0)
+ {
+ /* 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
+ {
+ /* PR 17512: file: 006-2964-0.004. */
+ if (num > mdata->nsects)
+ return FALSE;
+
+ /* A section number. */
+ 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
+ bfd convention, subtract the section address.
+ Use the address from the header, so that the user can modify
+ the vma of the section. */
+ res->addend = -mdata->sections[num - 1]->addr;
+ }
+
+ /* 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;
+
+ return TRUE;
+}
+
+/* Do most of the work for canonicalize_relocs on RAW: create internal
+ representation RELOC and set most fields of RES using symbol table SYMS.
+ Each target still has to set the howto of RES and possibly adjust other
+ fields.
+ Previously the Mach-O hook point was simply swap_in, but some targets
+ (like arm64) don't follow the generic rules (symnum is a value for the
+ non-scattered relocation ADDEND). */
+
+bfd_boolean
+bfd_mach_o_pre_canonicalize_one_reloc (bfd *abfd,
+ struct mach_o_reloc_info_external *raw,
+ bfd_mach_o_reloc_info *reloc,
+ arelent *res, asymbol **syms)
+{
+ bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
+ bfd_vma addr;
+
addr = bfd_get_32 (abfd, raw->r_address);
res->sym_ptr_ptr = NULL;
res->addend = 0;
@@ -1346,11 +1416,11 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
bfd_vma symnum = bfd_get_32 (abfd, raw->r_symbolnum);
/* Scattered relocation, can't be extern. */
- reloc.r_scattered = 1;
- reloc.r_extern = 0;
+ reloc->r_scattered = 1;
+ reloc->r_extern = 0;
/* Extract section and offset from r_value (symnum). */
- reloc.r_value = symnum;
+ reloc->r_value = symnum;
/* FIXME: This breaks when a symbol in a reloc exactly follows the
end of the data for the section (e.g. in a calculation of section
data length). At present, the symbol will end up associated with
@@ -1368,81 +1438,33 @@ bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
}
/* Extract the info and address fields from r_address. */
- 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_address = BFD_MACH_O_GET_SR_TYPE (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_address = BFD_MACH_O_GET_SR_TYPE (addr);
res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
}
else
{
- unsigned int num;
-
/* Non-scattered relocation. */
- reloc.r_scattered = 0;
+ reloc->r_scattered = 0;
+ reloc->r_address = addr;
+ res->address = addr;
/* 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;
+ bfd_mach_o_swap_in_non_scattered_reloc (abfd, reloc, raw->r_symbolnum);
- if (reloc.r_extern)
- {
- /* PR 17512: file: 8396-1185-0.004. */
- if (num >= (unsigned) bfd_mach_o_count_symbols (abfd))
- sym = bfd_und_section_ptr->symbol_ptr_ptr;
- else if (syms == NULL)
- sym = bfd_und_section_ptr->symbol_ptr_ptr;
- else
- /* An external symbol number. */
- sym = syms + num;
- }
- else if (num == 0x00ffffff || num == 0)
- {
- /* 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
- {
- /* PR 17512: file: 006-2964-0.004. */
- if (num > mdata->nsects)
- return -1;
-
- /* A section number. */
- 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
- bfd convention, subtract the section address.
- Use the address from the header, so that the user can modify
- the vma of the section. */
- res->addend = -mdata->sections[num - 1]->addr;
- }
- /* 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;
+ if (!bfd_mach_o_canonicalize_non_scattered_reloc (abfd, reloc,
+ res, syms))
+ return FALSE;
}
/* 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 0;
+ return TRUE;
}
static int
@@ -1450,6 +1472,7 @@ bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
unsigned long count,
arelent *res, asymbol **syms)
{
+ bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
unsigned long i;
struct mach_o_reloc_info_external *native_relocs;
bfd_size_type native_size;
@@ -1472,8 +1495,8 @@ bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
for (i = 0; i < count; i++)
{
- if (bfd_mach_o_canonicalize_one_reloc (abfd, &native_relocs[i],
- &res[i], syms) < 0)
+ if (!(*bed->_bfd_mach_o_canonicalize_one_reloc)(abfd, &native_relocs[i],
+ &res[i], syms))
goto err;
}
free (native_relocs);
@@ -1495,7 +1518,7 @@ bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
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)
+ if (bed->_bfd_mach_o_canonicalize_one_reloc == NULL)
return 0;
if (asect->relocation == NULL)
@@ -1550,7 +1573,7 @@ bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
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)
+ if (bed->_bfd_mach_o_canonicalize_one_reloc == NULL)
return 0;
if (mdata->dyn_reloc_cache == NULL)
@@ -5807,7 +5830,7 @@ bfd_boolean bfd_mach_o_free_cached_info (bfd *abfd)
#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
+#define bfd_mach_o_canonicalize_one_reloc NULL
#define bfd_mach_o_swap_reloc_out NULL
#define bfd_mach_o_print_thread NULL
#define bfd_mach_o_tgt_seg_table NULL
diff --git a/bfd/mach-o.h b/bfd/mach-o.h
index 1b62c0f..5ea6d4a 100644
--- a/bfd/mach-o.h
+++ b/bfd/mach-o.h
@@ -704,6 +704,11 @@ bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd);
bfd_vma bfd_mach_o_get_base_address (bfd *);
+void bfd_mach_o_swap_in_non_scattered_reloc (bfd *, bfd_mach_o_reloc_info *,
+ unsigned char *);
+bfd_boolean bfd_mach_o_canonicalize_non_scattered_reloc (bfd *, bfd_mach_o_reloc_info *, arelent *, asymbol **);
+bfd_boolean bfd_mach_o_pre_canonicalize_one_reloc (bfd *, struct mach_o_reloc_info_external *, bfd_mach_o_reloc_info *, arelent *, asymbol **);
+
/* A placeholder in case we need to suppress emitting the dysymtab for some
reason (e.g. compatibility with older system versions). */
#define bfd_mach_o_should_emit_dysymtab(x) TRUE
@@ -740,7 +745,8 @@ typedef struct bfd_mach_o_backend_data
{
enum bfd_architecture arch;
bfd_vma page_size;
- bfd_boolean (*_bfd_mach_o_swap_reloc_in)(arelent *, bfd_mach_o_reloc_info *);
+ bfd_boolean (*_bfd_mach_o_canonicalize_one_reloc)
+ (bfd *, struct mach_o_reloc_info_external *, arelent *, asymbol **);
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 *);