};
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;
}
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;
}
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];
{ 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
};
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];
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];
}
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];
}
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;
{ 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
/* 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)
{
}
}
-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;
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
}
/* 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
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;
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);
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)
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)
#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