mach-o: use a per-target reloc canonicalize function.
bfd/ * 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.
This commit is contained in:
parent
1798301e20
commit
bcb51645d3
|
@ -5,6 +5,32 @@
|
||||||
backward file movement via "negative" sizes.
|
backward file movement via "negative" sizes.
|
||||||
* coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise.
|
* coff-alpha.c (alpha_ecoff_openr_next_archived_file): Likewise.
|
||||||
|
|
||||||
|
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>
|
2015-11-18 Tristan Gingold <gingold@adacore.com>
|
||||||
|
|
||||||
* mach-o.h (struct mach_o_data_struct): Add hdr_offset field.
|
* mach-o.h (struct mach_o_data_struct): Add hdr_offset field.
|
||||||
|
|
|
@ -112,20 +112,27 @@ static reloc_howto_type i386_howto_table[]=
|
||||||
};
|
};
|
||||||
|
|
||||||
static bfd_boolean
|
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:
|
case BFD_MACH_O_GENERIC_RELOC_PAIR:
|
||||||
if (reloc->r_length == 2)
|
if (reloc.r_length == 2)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[7];
|
res->howto = &i386_howto_table[7];
|
||||||
res->address = res[-1].address;
|
res->address = res[-1].address;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (reloc->r_length == 1)
|
else if (reloc.r_length == 1)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[10];
|
res->howto = &i386_howto_table[10];
|
||||||
res->address = res[-1].address;
|
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;
|
return FALSE;
|
||||||
case BFD_MACH_O_GENERIC_RELOC_SECTDIFF:
|
case BFD_MACH_O_GENERIC_RELOC_SECTDIFF:
|
||||||
if (reloc->r_length == 2)
|
if (reloc.r_length == 2)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[5];
|
res->howto = &i386_howto_table[5];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (reloc->r_length == 1)
|
else if (reloc.r_length == 1)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[8];
|
res->howto = &i386_howto_table[8];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF:
|
case BFD_MACH_O_GENERIC_RELOC_LOCAL_SECTDIFF:
|
||||||
if (reloc->r_length == 2)
|
if (reloc.r_length == 2)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[6];
|
res->howto = &i386_howto_table[6];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (reloc->r_length == 1)
|
else if (reloc.r_length == 1)
|
||||||
{
|
{
|
||||||
res->howto = &i386_howto_table[9];
|
res->howto = &i386_howto_table[9];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -162,10 +169,10 @@ bfd_mach_o_i386_swap_reloc_in (arelent *res, bfd_mach_o_reloc_info *reloc)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (reloc->r_type)
|
switch (reloc.r_type)
|
||||||
{
|
{
|
||||||
case BFD_MACH_O_GENERIC_RELOC_VANILLA:
|
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 */
|
case 0: /* len = 0, pcrel = 0 */
|
||||||
res->howto = &i386_howto_table[2];
|
res->howto = &i386_howto_table[2];
|
||||||
|
@ -384,7 +391,7 @@ const mach_o_segment_name_xlat mach_o_i386_segsec_names_xlat[] =
|
||||||
{ NULL, NULL }
|
{ 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_swap_reloc_out bfd_mach_o_i386_swap_reloc_out
|
||||||
#define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread
|
#define bfd_mach_o_print_thread bfd_mach_o_i386_print_thread
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ static const bfd_mach_o_backend_data TARGET_NAME_BACKEND =
|
||||||
{
|
{
|
||||||
TARGET_ARCHITECTURE,
|
TARGET_ARCHITECTURE,
|
||||||
TARGET_PAGESIZE,
|
TARGET_PAGESIZE,
|
||||||
bfd_mach_o_swap_reloc_in,
|
bfd_mach_o_canonicalize_one_reloc,
|
||||||
bfd_mach_o_swap_reloc_out,
|
bfd_mach_o_swap_reloc_out,
|
||||||
bfd_mach_o_print_thread,
|
bfd_mach_o_print_thread,
|
||||||
bfd_mach_o_tgt_seg_table,
|
bfd_mach_o_tgt_seg_table,
|
||||||
|
|
|
@ -120,18 +120,25 @@ static reloc_howto_type x86_64_howto_table[]=
|
||||||
};
|
};
|
||||||
|
|
||||||
static bfd_boolean
|
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)
|
||||||
{
|
{
|
||||||
/* On x86-64, scattered relocs are not used. */
|
bfd_mach_o_reloc_info reloc;
|
||||||
if (reloc->r_scattered)
|
|
||||||
|
if (!bfd_mach_o_pre_canonicalize_one_reloc (abfd, raw, &reloc, res, syms))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
switch (reloc->r_type)
|
/* On x86-64, scattered relocs are not used. */
|
||||||
|
if (reloc.r_scattered)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (reloc.r_type)
|
||||||
{
|
{
|
||||||
case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
|
case BFD_MACH_O_X86_64_RELOC_UNSIGNED:
|
||||||
if (reloc->r_pcrel)
|
if (reloc.r_pcrel)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
switch (reloc->r_length)
|
switch (reloc.r_length)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
res->howto = &x86_64_howto_table[1];
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
case BFD_MACH_O_X86_64_RELOC_SIGNED:
|
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];
|
res->howto = &x86_64_howto_table[2];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_BRANCH:
|
case BFD_MACH_O_X86_64_RELOC_BRANCH:
|
||||||
if (!reloc->r_pcrel)
|
if (!reloc.r_pcrel)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
switch (reloc->r_length)
|
switch (reloc.r_length)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
res->howto = &x86_64_howto_table[6];
|
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;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_GOT_LOAD:
|
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];
|
res->howto = &x86_64_howto_table[7];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_GOT:
|
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];
|
res->howto = &x86_64_howto_table[10];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
|
case BFD_MACH_O_X86_64_RELOC_SUBTRACTOR:
|
||||||
if (reloc->r_pcrel)
|
if (reloc.r_pcrel)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
switch (reloc->r_length)
|
switch (reloc.r_length)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
res->howto = &x86_64_howto_table[8];
|
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;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_SIGNED_1:
|
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];
|
res->howto = &x86_64_howto_table[3];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_SIGNED_2:
|
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];
|
res->howto = &x86_64_howto_table[4];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BFD_MACH_O_X86_64_RELOC_SIGNED_4:
|
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];
|
res->howto = &x86_64_howto_table[5];
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -344,7 +351,7 @@ const mach_o_segment_name_xlat mach_o_x86_64_segsec_names_xlat[] =
|
||||||
{ NULL, NULL }
|
{ 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_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
|
#define bfd_mach_o_bfd_reloc_type_lookup bfd_mach_o_x86_64_bfd_reloc_type_lookup
|
||||||
|
|
175
bfd/mach-o.c
175
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
|
/* 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. */
|
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,
|
bfd_mach_o_swap_in_non_scattered_reloc (bfd *abfd, bfd_mach_o_reloc_info *rel,
|
||||||
unsigned char *fields)
|
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
|
/* Set syms_ptr_ptr and addend of RES. */
|
||||||
bfd_mach_o_canonicalize_one_reloc (bfd *abfd,
|
|
||||||
struct mach_o_reloc_info_external *raw,
|
bfd_boolean
|
||||||
arelent *res, asymbol **syms)
|
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_data_struct *mdata = bfd_mach_o_get_data (abfd);
|
||||||
bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
|
unsigned int num;
|
||||||
bfd_mach_o_reloc_info reloc;
|
|
||||||
bfd_vma addr;
|
|
||||||
asymbol **sym;
|
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);
|
addr = bfd_get_32 (abfd, raw->r_address);
|
||||||
res->sym_ptr_ptr = NULL;
|
res->sym_ptr_ptr = NULL;
|
||||||
res->addend = 0;
|
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);
|
bfd_vma symnum = bfd_get_32 (abfd, raw->r_symbolnum);
|
||||||
|
|
||||||
/* Scattered relocation, can't be extern. */
|
/* Scattered relocation, can't be extern. */
|
||||||
reloc.r_scattered = 1;
|
reloc->r_scattered = 1;
|
||||||
reloc.r_extern = 0;
|
reloc->r_extern = 0;
|
||||||
|
|
||||||
/* Extract section and offset from r_value (symnum). */
|
/* 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
|
/* 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
|
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
|
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. */
|
/* Extract the info and address fields from r_address. */
|
||||||
reloc.r_type = 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_length = BFD_MACH_O_GET_SR_LENGTH (addr);
|
||||||
reloc.r_pcrel = addr & BFD_MACH_O_SR_PCREL;
|
reloc->r_pcrel = addr & BFD_MACH_O_SR_PCREL;
|
||||||
reloc.r_address = BFD_MACH_O_GET_SR_TYPE (addr);
|
reloc->r_address = BFD_MACH_O_GET_SR_TYPE (addr);
|
||||||
res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
|
res->address = BFD_MACH_O_GET_SR_ADDRESS (addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned int num;
|
|
||||||
|
|
||||||
/* Non-scattered relocation. */
|
/* 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
|
/* The value and info fields have to be extracted dependent on target
|
||||||
endian-ness. */
|
endian-ness. */
|
||||||
bfd_mach_o_swap_in_non_scattered_reloc (abfd, &reloc, raw->r_symbolnum);
|
bfd_mach_o_swap_in_non_scattered_reloc (abfd, reloc, raw->r_symbolnum);
|
||||||
num = reloc.r_value;
|
|
||||||
|
|
||||||
if (reloc.r_extern)
|
if (!bfd_mach_o_canonicalize_non_scattered_reloc (abfd, reloc,
|
||||||
{
|
res, syms))
|
||||||
/* PR 17512: file: 8396-1185-0.004. */
|
return FALSE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have set up a reloc with all the information present, so the swapper
|
/* 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
|
can modify address, value and addend fields, if necessary, to convey
|
||||||
information in the generic BFD reloc that is mach-o specific. */
|
information in the generic BFD reloc that is mach-o specific. */
|
||||||
|
|
||||||
if (!(*bed->_bfd_mach_o_swap_reloc_in)(res, &reloc))
|
return TRUE;
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1450,6 +1472,7 @@ bfd_mach_o_canonicalize_relocs (bfd *abfd, unsigned long filepos,
|
||||||
unsigned long count,
|
unsigned long count,
|
||||||
arelent *res, asymbol **syms)
|
arelent *res, asymbol **syms)
|
||||||
{
|
{
|
||||||
|
bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
struct mach_o_reloc_info_external *native_relocs;
|
struct mach_o_reloc_info_external *native_relocs;
|
||||||
bfd_size_type native_size;
|
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++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (bfd_mach_o_canonicalize_one_reloc (abfd, &native_relocs[i],
|
if (!(*bed->_bfd_mach_o_canonicalize_one_reloc)(abfd, &native_relocs[i],
|
||||||
&res[i], syms) < 0)
|
&res[i], syms))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
free (native_relocs);
|
free (native_relocs);
|
||||||
|
@ -1495,7 +1518,7 @@ bfd_mach_o_canonicalize_reloc (bfd *abfd, asection *asect,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* No need to go further if we don't know how to read relocs. */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
if (asect->relocation == NULL)
|
if (asect->relocation == NULL)
|
||||||
|
@ -1550,7 +1573,7 @@ bfd_mach_o_canonicalize_dynamic_reloc (bfd *abfd, arelent **rels,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* No need to go further if we don't know how to read relocs. */
|
/* 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;
|
return 0;
|
||||||
|
|
||||||
if (mdata->dyn_reloc_cache == NULL)
|
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_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_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_swap_reloc_out NULL
|
||||||
#define bfd_mach_o_print_thread NULL
|
#define bfd_mach_o_print_thread NULL
|
||||||
#define bfd_mach_o_tgt_seg_table NULL
|
#define bfd_mach_o_tgt_seg_table NULL
|
||||||
|
|
|
@ -704,6 +704,11 @@ bfd_boolean bfd_mach_o_read_symtab_strtab (bfd *abfd);
|
||||||
|
|
||||||
bfd_vma bfd_mach_o_get_base_address (bfd *);
|
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
|
/* A placeholder in case we need to suppress emitting the dysymtab for some
|
||||||
reason (e.g. compatibility with older system versions). */
|
reason (e.g. compatibility with older system versions). */
|
||||||
#define bfd_mach_o_should_emit_dysymtab(x) TRUE
|
#define bfd_mach_o_should_emit_dysymtab(x) TRUE
|
||||||
|
@ -740,7 +745,8 @@ typedef struct bfd_mach_o_backend_data
|
||||||
{
|
{
|
||||||
enum bfd_architecture arch;
|
enum bfd_architecture arch;
|
||||||
bfd_vma page_size;
|
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_swap_reloc_out)(arelent *, bfd_mach_o_reloc_info *);
|
||||||
bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *,
|
bfd_boolean (*_bfd_mach_o_print_thread)(bfd *, bfd_mach_o_thread_flavour *,
|
||||||
void *, char *);
|
void *, char *);
|
||||||
|
|
Loading…
Reference in New Issue