mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-28 11:43:36 +08:00
Make @GOT relocations work
This commit is contained in:
parent
ef4d61874b
commit
07a159dbd4
@ -1,3 +1,15 @@
|
|||||||
|
Wed Jan 3 19:42:47 1996 Michael Meissner <meissner@wogglebug.tiac.net>
|
||||||
|
|
||||||
|
* elf32-ppc.c (ppc_elf_relocate_section): Make @GOT relocations
|
||||||
|
work.
|
||||||
|
(ppc_elf_howto_raw): Just use bfd_elf_generic_reloc for all howto
|
||||||
|
relocs, since ppc_elf_relocate_section handles the linker case.
|
||||||
|
(ppc_elf_{addr16_ha,got16,toc16,brtaken}_reloc): Delete, no longer
|
||||||
|
used.
|
||||||
|
(ppc_elf_{addr16_ha,got16,toc16,brtaken}_inner): Merge these into
|
||||||
|
ppc_elf_relocate_section since that is now the only caller.
|
||||||
|
(ppc_elf_relocate_section): Ditto.
|
||||||
|
|
||||||
Wed Jan 3 15:11:30 1996 Ian Lance Taylor <ian@cygnus.com>
|
Wed Jan 3 15:11:30 1996 Ian Lance Taylor <ian@cygnus.com>
|
||||||
|
|
||||||
* coffcode.h (coff_write_object_contents): If we don't know the
|
* coffcode.h (coff_write_object_contents): If we don't know the
|
||||||
|
385
bfd/elf32-ppc.c
385
bfd/elf32-ppc.c
@ -104,18 +104,6 @@ static bfd_reloc_status_type ppc_elf_unsupported_reloc
|
|||||||
static bfd_reloc_status_type ppc_elf_std_reloc
|
static bfd_reloc_status_type ppc_elf_std_reloc
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
||||||
|
|
||||||
static bfd_vma ppc_elf_addr16_ha_inner PARAMS ((bfd_vma));
|
|
||||||
static bfd_reloc_status_type ppc_elf_addr16_ha_reloc
|
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
|
||||||
static bfd_vma ppc_elf_got16_inner PARAMS ((asection *sec));
|
|
||||||
static bfd_reloc_status_type ppc_elf_got16_reloc
|
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
|
||||||
static bfd_vma ppc_elf_toc16_inner PARAMS ((asection *sec));
|
|
||||||
static bfd_reloc_status_type ppc_elf_toc16_reloc
|
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
|
||||||
static bfd_vma ppc_elf_brtaken_inner PARAMS ((bfd_vma, enum ppc_reloc_type));
|
|
||||||
static bfd_reloc_status_type ppc_elf_brtaken_reloc
|
|
||||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
|
||||||
static reloc_howto_type *ppc_elf_reloc_type_lookup
|
static reloc_howto_type *ppc_elf_reloc_type_lookup
|
||||||
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
|
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
|
||||||
static void ppc_elf_info_to_howto
|
static void ppc_elf_info_to_howto
|
||||||
@ -265,7 +253,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_dont, /* complain_on_overflow */
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
ppc_elf_addr16_ha_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_ADDR16_HA", /* name */
|
"R_PPC_ADDR16_HA", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -298,7 +286,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
||||||
ppc_elf_brtaken_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_ADDR14_BRTAKEN",/* name */
|
"R_PPC_ADDR14_BRTAKEN",/* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -315,7 +303,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
||||||
ppc_elf_brtaken_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_ADDR14_BRNTAKEN",/* name */
|
"R_PPC_ADDR14_BRNTAKEN",/* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -362,7 +350,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
true, /* pc_relative */
|
true, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_signed, /* complain_on_overflow */
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
ppc_elf_brtaken_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_REL14_BRTAKEN", /* name */
|
"R_PPC_REL14_BRTAKEN", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -379,7 +367,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
true, /* pc_relative */
|
true, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_signed, /* complain_on_overflow */
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
ppc_elf_brtaken_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_REL14_BRNTAKEN",/* name */
|
"R_PPC_REL14_BRNTAKEN",/* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -395,7 +383,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_signed, /* complain_on_overflow */
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
ppc_elf_got16_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_GOT16", /* name */
|
"R_PPC_GOT16", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -411,7 +399,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
||||||
ppc_elf_got16_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_GOT16_LO", /* name */
|
"R_PPC_GOT16_LO", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -427,7 +415,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_bitfield, /* complain_on_overflow */
|
complain_overflow_bitfield, /* complain_on_overflow */
|
||||||
ppc_elf_got16_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_GOT16_HI", /* name */
|
"R_PPC_GOT16_HI", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -684,7 +672,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_signed, /* complain_on_overflow */
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
ppc_elf_got16_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_SDAREL16", /* name */
|
"R_PPC_SDAREL16", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -840,7 +828,7 @@ static reloc_howto_type ppc_elf_howto_raw[] =
|
|||||||
false, /* pc_relative */
|
false, /* pc_relative */
|
||||||
0, /* bitpos */
|
0, /* bitpos */
|
||||||
complain_overflow_signed, /* complain_on_overflow */
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
ppc_elf_toc16_reloc, /* special_function */
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
"R_PPC_TOC16", /* name */
|
"R_PPC_TOC16", /* name */
|
||||||
false, /* partial_inplace */
|
false, /* partial_inplace */
|
||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
@ -982,10 +970,11 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
boolean error;
|
boolean error;
|
||||||
|
|
||||||
/* Check if we have the same endianess */
|
/* Check if we have the same endianess */
|
||||||
if (ibfd->xvec->byteorder != obfd->xvec->byteorder)
|
if (ibfd->xvec->byteorder != obfd->xvec->byteorder
|
||||||
|
&& obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: compiled for a %s endian system and target is %s endian.\n",
|
("%s: compiled for a %s endian system and target is %s endian",
|
||||||
bfd_get_filename (ibfd),
|
bfd_get_filename (ibfd),
|
||||||
bfd_big_endian (ibfd) ? "big" : "little",
|
bfd_big_endian (ibfd) ? "big" : "little",
|
||||||
bfd_big_endian (obfd) ? "big" : "little");
|
bfd_big_endian (obfd) ? "big" : "little");
|
||||||
@ -1021,7 +1010,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: compiled with -mrelocatable and linked with modules compiled normally\n",
|
("%s: compiled with -mrelocatable and linked with modules compiled normally",
|
||||||
bfd_get_filename (ibfd));
|
bfd_get_filename (ibfd));
|
||||||
}
|
}
|
||||||
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
|
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
|
||||||
@ -1029,7 +1018,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: compiled normally and linked with modules compiled with -mrelocatable\n",
|
("%s: compiled normally and linked with modules compiled with -mrelocatable",
|
||||||
bfd_get_filename (ibfd));
|
bfd_get_filename (ibfd));
|
||||||
}
|
}
|
||||||
else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0)
|
else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0)
|
||||||
@ -1044,7 +1033,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
new_flags &= ~EF_PPC_EMB;
|
new_flags &= ~EF_PPC_EMB;
|
||||||
error = true;
|
error = true;
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: compiled for the eabi and linked with modules compiled for System V\n",
|
("%s: compiled for the eabi and linked with modules compiled for System V",
|
||||||
bfd_get_filename (ibfd));
|
bfd_get_filename (ibfd));
|
||||||
}
|
}
|
||||||
else if ((new_flags & EF_PPC_EMB) == 0 && (old_flags & EF_PPC_EMB) != 0)
|
else if ((new_flags & EF_PPC_EMB) == 0 && (old_flags & EF_PPC_EMB) != 0)
|
||||||
@ -1052,7 +1041,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
old_flags &= ~EF_PPC_EMB;
|
old_flags &= ~EF_PPC_EMB;
|
||||||
error = true;
|
error = true;
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: compiled for System V and linked with modules compiled for eabi\n",
|
("%s: compiled for System V and linked with modules compiled for eabi",
|
||||||
bfd_get_filename (ibfd));
|
bfd_get_filename (ibfd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1061,7 +1050,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd)
|
|||||||
{
|
{
|
||||||
error = true;
|
error = true;
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)\n",
|
("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
|
||||||
bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
|
bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,7 +1119,7 @@ ppc_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|||||||
{
|
{
|
||||||
BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
|
BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: Relocation %s (%d) is not currently supported.\n",
|
("%s: relocation %s (%d) is not currently supported",
|
||||||
bfd_get_filename (abfd),
|
bfd_get_filename (abfd),
|
||||||
reloc_entry->howto->name,
|
reloc_entry->howto->name,
|
||||||
reloc_entry->howto->type);
|
reloc_entry->howto->type);
|
||||||
@ -1138,188 +1127,6 @@ ppc_elf_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|||||||
return bfd_reloc_notsupported;
|
return bfd_reloc_notsupported;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal function to return the adjustment to the addend for relocations
|
|
||||||
that return the upper 16 bits after sign extending the lower 16 bits, ie
|
|
||||||
for use with a ADDIS instruction followed by a memory reference using the
|
|
||||||
bottom 16 bits. */
|
|
||||||
|
|
||||||
INLINE
|
|
||||||
static bfd_vma
|
|
||||||
ppc_elf_addr16_ha_inner (relocation)
|
|
||||||
bfd_vma relocation;
|
|
||||||
{
|
|
||||||
return (relocation & 0x8000) << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the ADDR16_HA reloc by adjusting the reloc addend. */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static bfd_reloc_status_type
|
|
||||||
ppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|
||||||
output_bfd, error_message)
|
|
||||||
bfd *abfd;
|
|
||||||
arelent *reloc_entry;
|
|
||||||
asymbol *symbol;
|
|
||||||
PTR data;
|
|
||||||
asection *input_section;
|
|
||||||
bfd *output_bfd;
|
|
||||||
char **error_message;
|
|
||||||
{
|
|
||||||
bfd_vma relocation;
|
|
||||||
asection *sec;
|
|
||||||
|
|
||||||
if (output_bfd != (bfd *) NULL)
|
|
||||||
return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data,
|
|
||||||
input_section, output_bfd, error_message);
|
|
||||||
|
|
||||||
sec = symbol->section;
|
|
||||||
relocation = (((bfd_is_com_section (sec)) ? 0 : symbol->value)
|
|
||||||
+ sec->output_section->vma
|
|
||||||
+ sec->output_offset
|
|
||||||
+ reloc_entry->addend);
|
|
||||||
|
|
||||||
reloc_entry->addend += ppc_elf_addr16_ha_inner (relocation);
|
|
||||||
return bfd_reloc_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Internal function to return the addjustment to the addend for GOT16
|
|
||||||
entries */
|
|
||||||
|
|
||||||
INLINE
|
|
||||||
static bfd_vma
|
|
||||||
ppc_elf_got16_inner (sec)
|
|
||||||
asection *sec;
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "ppc_elf_got16_inner called for %s\n", sec->name);
|
|
||||||
#endif
|
|
||||||
return -(sec->output_section->vma + 0x8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the GOT16 reloc. We want to use the offset within the .got
|
|
||||||
section, not the actual VMA. */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static bfd_reloc_status_type
|
|
||||||
ppc_elf_got16_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|
||||||
output_bfd, error_message)
|
|
||||||
bfd *abfd;
|
|
||||||
arelent *reloc_entry;
|
|
||||||
asymbol *symbol;
|
|
||||||
PTR data;
|
|
||||||
asection *input_section;
|
|
||||||
bfd *output_bfd;
|
|
||||||
char **error_message;
|
|
||||||
{
|
|
||||||
if (output_bfd != (bfd *) NULL)
|
|
||||||
return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data,
|
|
||||||
input_section, output_bfd, error_message);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "ppc_elf_got16_reloc called for %s in %s\n", (*reloc_entry->sym_ptr_ptr)->name, input_section->name);
|
|
||||||
#endif
|
|
||||||
reloc_entry->addend += ppc_elf_got16_inner (bfd_get_section (*reloc_entry->sym_ptr_ptr));
|
|
||||||
return bfd_reloc_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Internal function to return the addjustment to the addend for TOC16
|
|
||||||
entries */
|
|
||||||
|
|
||||||
INLINE
|
|
||||||
static bfd_vma
|
|
||||||
ppc_elf_toc16_inner (sec)
|
|
||||||
asection *sec;
|
|
||||||
{
|
|
||||||
BFD_ASSERT (bfd_is_und_section (sec)
|
|
||||||
|| strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
|
|
||||||
|| strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0
|
|
||||||
|| strcmp (bfd_get_section_name (abfd, sec), ".sdata") == 0
|
|
||||||
|| strcmp (bfd_get_section_name (abfd, sec), ".sbss") == 0)
|
|
||||||
|
|
||||||
return -(sec->output_section->vma + 0x8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the TOC16 reloc. We want to use the offset within the .got
|
|
||||||
section, not the actual VMA. This is appropriate when generating
|
|
||||||
an embedded ELF object, for which the .got section acts like the
|
|
||||||
AIX .toc section. */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static bfd_reloc_status_type
|
|
||||||
ppc_elf_toc16_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|
||||||
output_bfd, error_message)
|
|
||||||
bfd *abfd;
|
|
||||||
arelent *reloc_entry;
|
|
||||||
asymbol *symbol;
|
|
||||||
PTR data;
|
|
||||||
asection *input_section;
|
|
||||||
bfd *output_bfd;
|
|
||||||
char **error_message;
|
|
||||||
{
|
|
||||||
if (output_bfd != (bfd *) NULL)
|
|
||||||
return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data,
|
|
||||||
input_section, output_bfd, error_message);
|
|
||||||
|
|
||||||
reloc_entry->addend += ppc_elf_toc16_inner (bfd_get_section (*reloc_entry->sym_ptr_ptr));
|
|
||||||
return bfd_reloc_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Internal function to return the adjustment for relocations that set the
|
|
||||||
branch taken bit or branch not taken in B0 for conditional branches.
|
|
||||||
The dst_mask for these relocations allows this bit to be set as part
|
|
||||||
of the addend. */
|
|
||||||
|
|
||||||
INLINE
|
|
||||||
static bfd_vma
|
|
||||||
ppc_elf_brtaken_inner (relocation, ppc_reloc)
|
|
||||||
bfd_vma relocation;
|
|
||||||
enum ppc_reloc_type ppc_reloc;
|
|
||||||
{
|
|
||||||
if (ppc_reloc == R_PPC_ADDR14_BRTAKEN || ppc_reloc == R_PPC_REL14_BRTAKEN)
|
|
||||||
return (relocation & 0x8000) ? 0 : BRANCH_PREDICT_BIT; /* branch taken */
|
|
||||||
else
|
|
||||||
return (relocation & 0x8000) ? BRANCH_PREDICT_BIT : 0; /* branch not taken */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle the R_PPC_{ADDR,REL}14_BR{,N}TAKEN relocs by setting bit 10 to indicate
|
|
||||||
whether the branch is taken or not. */
|
|
||||||
|
|
||||||
/*ARGSUSED*/
|
|
||||||
static bfd_reloc_status_type
|
|
||||||
ppc_elf_brtaken_reloc (abfd, reloc_entry, symbol, data, input_section,
|
|
||||||
output_bfd, error_message)
|
|
||||||
bfd *abfd;
|
|
||||||
arelent *reloc_entry;
|
|
||||||
asymbol *symbol;
|
|
||||||
PTR data;
|
|
||||||
asection *input_section;
|
|
||||||
bfd *output_bfd;
|
|
||||||
char **error_message;
|
|
||||||
{
|
|
||||||
bfd_vma relocation;
|
|
||||||
asection *sec;
|
|
||||||
long insn;
|
|
||||||
|
|
||||||
if (output_bfd != (bfd *) NULL)
|
|
||||||
return ppc_elf_std_reloc (abfd, reloc_entry, symbol, data,
|
|
||||||
input_section, output_bfd, error_message);
|
|
||||||
|
|
||||||
sec = symbol->section;
|
|
||||||
relocation = (((bfd_is_com_section (sec)) ? 0 : symbol->value)
|
|
||||||
+ sec->output_section->vma
|
|
||||||
+ sec->output_offset
|
|
||||||
+ reloc_entry->addend);
|
|
||||||
|
|
||||||
/* Set the branch prediction bit */
|
|
||||||
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
|
|
||||||
insn &= ~BRANCH_PREDICT_BIT;
|
|
||||||
insn |= ppc_elf_brtaken_inner (relocation - reloc_entry->address,
|
|
||||||
(enum ppc_reloc_type)reloc_entry->howto->type);
|
|
||||||
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
|
|
||||||
|
|
||||||
return bfd_reloc_continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Adjust a symbol defined by a dynamic object and referenced by a
|
/* Adjust a symbol defined by a dynamic object and referenced by a
|
||||||
regular object. The current definition is in some section of the
|
regular object. The current definition is in some section of the
|
||||||
@ -1690,7 +1497,7 @@ ppc_elf_check_relocs (abfd, info, sec, relocs)
|
|||||||
if (info->shared)
|
if (info->shared)
|
||||||
{
|
{
|
||||||
/* If we are generating a shared object, we need to
|
/* If we are generating a shared object, we need to
|
||||||
output a R_SPARC_RELATIVE reloc so that the
|
output a R_PPC_RELATIVE reloc so that the
|
||||||
dynamic linker can adjust this GOT entry. */
|
dynamic linker can adjust this GOT entry. */
|
||||||
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
srelgot->_raw_size += sizeof (Elf32_External_Rela);
|
||||||
}
|
}
|
||||||
@ -2131,12 +1938,10 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
|
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
bfd *dynobj = elf_hash_table (info)->dynobj;
|
bfd *dynobj = elf_hash_table (info)->dynobj;
|
||||||
bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
|
bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
|
||||||
asection *sgot;
|
asection *sgot = (asection *)0;
|
||||||
asection *splt;
|
Elf_Internal_Rela *rel = relocs;
|
||||||
asection *sreloc;
|
Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
|
||||||
Elf_Internal_Rela *rel = relocs;
|
boolean ret = true;
|
||||||
Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
|
|
||||||
boolean ret = true;
|
|
||||||
long insn;
|
long insn;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -2152,13 +1957,13 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
|
|
||||||
for (; rel < relend; rel++)
|
for (; rel < relend; rel++)
|
||||||
{
|
{
|
||||||
enum ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
|
enum ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
|
||||||
bfd_vma offset = rel->r_offset;
|
bfd_vma offset = rel->r_offset;
|
||||||
bfd_vma addend = rel->r_addend;
|
bfd_vma addend = rel->r_addend;
|
||||||
bfd_reloc_status_type r = bfd_reloc_other;
|
bfd_reloc_status_type r = bfd_reloc_other;
|
||||||
Elf_Internal_Sym *sym = (Elf_Internal_Sym *)0;
|
Elf_Internal_Sym *sym = (Elf_Internal_Sym *)0;
|
||||||
asection *sec = (asection *)0;
|
asection *sec = (asection *)0;
|
||||||
struct elf_link_hash_entry *h = (struct elf_link_hash_entry *)0;
|
struct elf_link_hash_entry *h = (struct elf_link_hash_entry *)0;
|
||||||
reloc_howto_type *howto;
|
reloc_howto_type *howto;
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
bfd_vma relocation;
|
bfd_vma relocation;
|
||||||
@ -2167,7 +1972,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
if ((unsigned)r_type >= (unsigned)R_PPC_max || !ppc_elf_howto_table[(int)r_type])
|
if ((unsigned)r_type >= (unsigned)R_PPC_max || !ppc_elf_howto_table[(int)r_type])
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: Unknown relocation type %d\n",
|
("%s: unknown relocation type %d",
|
||||||
bfd_get_filename (input_bfd),
|
bfd_get_filename (input_bfd),
|
||||||
(int)r_type);
|
(int)r_type);
|
||||||
|
|
||||||
@ -2212,7 +2017,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
if (howto->special_function == ppc_elf_unsupported_reloc)
|
if (howto->special_function == ppc_elf_unsupported_reloc)
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler)
|
(*_bfd_error_handler)
|
||||||
("%s: Relocation %s (%d) is not currently supported.\n",
|
("%s: relocation %s (%d) is not currently supported",
|
||||||
bfd_get_filename (input_bfd),
|
bfd_get_filename (input_bfd),
|
||||||
howto->name,
|
howto->name,
|
||||||
(int)r_type);
|
(int)r_type);
|
||||||
@ -2262,14 +2067,23 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (int)R_PPC_ADDR14_BRTAKEN: /* branch prediction relocations */
|
case (int)R_PPC_ADDR14_BRTAKEN: /* branch taken prediction relocations */
|
||||||
case (int)R_PPC_ADDR14_BRNTAKEN:
|
|
||||||
case (int)R_PPC_REL14_BRTAKEN:
|
case (int)R_PPC_REL14_BRTAKEN:
|
||||||
case (int)R_PPC_REL14_BRNTAKEN:
|
|
||||||
BFD_ASSERT (sec != (asection *)0);
|
|
||||||
insn = bfd_get_32 (output_bfd, contents + offset);
|
insn = bfd_get_32 (output_bfd, contents + offset);
|
||||||
insn &= ~BRANCH_PREDICT_BIT;
|
if ((relocation - offset) & 0x8000)
|
||||||
insn |= ppc_elf_brtaken_inner (relocation - offset, r_type);
|
insn &= ~BRANCH_PREDICT_BIT;
|
||||||
|
else
|
||||||
|
insn |= BRANCH_PREDICT_BIT;
|
||||||
|
bfd_put_32 (output_bfd, insn, contents + offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (int)R_PPC_ADDR14_BRNTAKEN: /* branch not taken predicition relocations */
|
||||||
|
case (int)R_PPC_REL14_BRNTAKEN:
|
||||||
|
insn = bfd_get_32 (output_bfd, contents + offset);
|
||||||
|
if ((relocation - offset) & 0x8000)
|
||||||
|
insn |= BRANCH_PREDICT_BIT;
|
||||||
|
else
|
||||||
|
insn &= ~BRANCH_PREDICT_BIT;
|
||||||
bfd_put_32 (output_bfd, insn, contents + offset);
|
bfd_put_32 (output_bfd, insn, contents + offset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2277,18 +2091,115 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
case (int)R_PPC_GOT16_LO:
|
case (int)R_PPC_GOT16_LO:
|
||||||
case (int)R_PPC_GOT16_HI:
|
case (int)R_PPC_GOT16_HI:
|
||||||
case (int)R_PPC_SDAREL16:
|
case (int)R_PPC_SDAREL16:
|
||||||
|
fprintf (stderr, "GOT relocations in section %s from section %s\n", input_section->name, sec->name);
|
||||||
BFD_ASSERT (sec != (asection *)0);
|
BFD_ASSERT (sec != (asection *)0);
|
||||||
addend += ppc_elf_got16_inner (sec);
|
if (!sgot)
|
||||||
|
{
|
||||||
|
sgot = bfd_get_section_by_name (dynobj, ".got");
|
||||||
|
BFD_ASSERT (sgot != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h != NULL)
|
||||||
|
{
|
||||||
|
bfd_vma off;
|
||||||
|
|
||||||
|
off = h->got_offset;
|
||||||
|
BFD_ASSERT (off != (bfd_vma) -1);
|
||||||
|
|
||||||
|
if (! elf_hash_table (info)->dynamic_sections_created
|
||||||
|
|| (info->shared
|
||||||
|
&& info->symbolic
|
||||||
|
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
|
||||||
|
{
|
||||||
|
/* This is actually a static link, or it is a
|
||||||
|
-Bsymbolic link and the symbol is defined
|
||||||
|
locally. We must initialize this entry in the
|
||||||
|
global offset table. Since the offset must
|
||||||
|
always be a multiple of 4, we use the least
|
||||||
|
significant bit to record whether we have
|
||||||
|
initialized it already.
|
||||||
|
|
||||||
|
When doing a dynamic link, we create a .rela.got
|
||||||
|
relocation entry to initialize the value. This
|
||||||
|
is done in the finish_dynamic_symbol routine. */
|
||||||
|
if ((off & 1) != 0)
|
||||||
|
off &= ~1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, relocation,
|
||||||
|
sgot->contents + off);
|
||||||
|
h->got_offset |= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relocation = sgot->output_offset + off;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_vma off;
|
||||||
|
|
||||||
|
BFD_ASSERT (local_got_offsets != NULL
|
||||||
|
&& local_got_offsets[r_symndx] != (bfd_vma) -1);
|
||||||
|
|
||||||
|
off = local_got_offsets[r_symndx];
|
||||||
|
|
||||||
|
/* The offset must always be a multiple of 4. We use
|
||||||
|
the least significant bit to record whether we have
|
||||||
|
already processed this entry. */
|
||||||
|
if ((off & 1) != 0)
|
||||||
|
off &= ~1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, relocation, sgot->contents + off);
|
||||||
|
|
||||||
|
if (info->shared)
|
||||||
|
{
|
||||||
|
asection *srelgot;
|
||||||
|
Elf_Internal_Rela outrel;
|
||||||
|
|
||||||
|
/* We need to generate a R_SPARC_RELATIVE reloc
|
||||||
|
for the dynamic linker. */
|
||||||
|
srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||||
|
BFD_ASSERT (srelgot != NULL);
|
||||||
|
|
||||||
|
outrel.r_offset = (sgot->output_section->vma
|
||||||
|
+ sgot->output_offset
|
||||||
|
+ off);
|
||||||
|
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||||
|
outrel.r_addend = 0;
|
||||||
|
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
|
||||||
|
(((Elf32_External_Rela *)
|
||||||
|
srelgot->contents)
|
||||||
|
+ srelgot->reloc_count));
|
||||||
|
++srelgot->reloc_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_got_offsets[r_symndx] |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
relocation = sgot->output_offset + off;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Handle the TOC16 reloc. We want to use the offset within the .got
|
||||||
|
section, not the actual VMA. This is appropriate when generating
|
||||||
|
an embedded ELF object, for which the .got section acts like the
|
||||||
|
AIX .toc section. */
|
||||||
case (int)R_PPC_TOC16: /* phony GOT16 relocations */
|
case (int)R_PPC_TOC16: /* phony GOT16 relocations */
|
||||||
BFD_ASSERT (sec != (asection *)0);
|
BFD_ASSERT (sec != (asection *)0);
|
||||||
addend += ppc_elf_toc16_inner (sec);
|
BFD_ASSERT (bfd_is_und_section (sec)
|
||||||
|
|| strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
|
||||||
|
|| strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0
|
||||||
|
|| strcmp (bfd_get_section_name (abfd, sec), ".sdata") == 0
|
||||||
|
|| strcmp (bfd_get_section_name (abfd, sec), ".sbss") == 0)
|
||||||
|
|
||||||
|
addend -= sec->output_section->vma + 0x8000;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (int)R_PPC_ADDR16_HA: /* arithmetic adjust relocations */
|
case (int)R_PPC_ADDR16_HA: /* arithmetic adjust relocations */
|
||||||
BFD_ASSERT (sec != (asection *)0);
|
BFD_ASSERT (sec != (asection *)0);
|
||||||
addend += ppc_elf_addr16_ha_inner (relocation + addend);
|
addend += ((relocation + addend) & 0x8000) << 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user