mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
* reloc.c (BFD_RELOC_HI16_PCREL): Define.
(BFD_RELOC_HI16_S_PCREL, BFD_RELOC_LO16_PCREL): Define. * elf32-ppc.c (GLINK_PLTRESOLVE, GLINK_ENTRY_SIZE): Define. (CROR_151515, CROR_313131): Delete. (ADDIS_11_11, ADDI_11_11, SUB_11_11_30, ADD_0_11_11, ADD_11_0_11, LWZ_0_4_30, MTCTR_0, LWZ_12_8_30, BCTR, ADDIS_11_30, LWZU_0_X_11): Define. (ppc_elf_howto_raw): Add R_PPC_REL16, R_PPC_REL16_LO, R_PPC_REL16_HI and R_PPC_REL16_HA entries. (ppc_elf_reloc_type_lookup): Convert new bfd reloc types. (ppc_elf_addr16_ha_reloc): Also handle R_PPC_REL16_HA. (struct ppc_elf_link_hash_table): Add glink, glink_pltresolve, new_plt, and old_plt. (ppc_elf_create_dynamic_sections): Create .glink section. (ppc_elf_check_relocs): Set new_plt and old_plt. (ppc_elf_select_plt_layout): New function. (ppc_elf_tls_setup): Set plt output section elf type and flags. (allocate_got): Handle differences between old and new got layout. (allocate_dynrelocs): Likewise for plt. (ppc_elf_size_dynamic_sections): Likewise. Allocate memory for .glink. Don't allocate memory for old bss .plt. Emit DT_PPC_GLINK. (ppc_elf_relax_section): Rename ppc_info to htab. Handle .glink destination of R_PPC_PLTREL24 relocs. (ppc_elf_relocate_section): Handle new relocs and changed destination of R_PPC_PLTREL24. (ppc_elf_finish_dynamic_symbol): Init new style plt and handle differences in layout. (ppc_elf_finish_dynamic_sections): Set DT_PPC_GLINK value. Don't put a blrl in new got. Write glink contents. * elf32-ppc.h (ppc_elf_select_plt_layout): Declare. * libbfd.h: Regenerate. * bfd-in2.h: Regenerate.
This commit is contained in:
parent
2df98d85f8
commit
d7128ce4b1
@ -1,3 +1,38 @@
|
||||
2005-05-11 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* reloc.c (BFD_RELOC_HI16_PCREL): Define.
|
||||
(BFD_RELOC_HI16_S_PCREL, BFD_RELOC_LO16_PCREL): Define.
|
||||
* elf32-ppc.c (GLINK_PLTRESOLVE, GLINK_ENTRY_SIZE): Define.
|
||||
(CROR_151515, CROR_313131): Delete.
|
||||
(ADDIS_11_11, ADDI_11_11, SUB_11_11_30, ADD_0_11_11, ADD_11_0_11,
|
||||
LWZ_0_4_30, MTCTR_0, LWZ_12_8_30, BCTR, ADDIS_11_30,
|
||||
LWZU_0_X_11): Define.
|
||||
(ppc_elf_howto_raw): Add R_PPC_REL16, R_PPC_REL16_LO, R_PPC_REL16_HI
|
||||
and R_PPC_REL16_HA entries.
|
||||
(ppc_elf_reloc_type_lookup): Convert new bfd reloc types.
|
||||
(ppc_elf_addr16_ha_reloc): Also handle R_PPC_REL16_HA.
|
||||
(struct ppc_elf_link_hash_table): Add glink, glink_pltresolve,
|
||||
new_plt, and old_plt.
|
||||
(ppc_elf_create_dynamic_sections): Create .glink section.
|
||||
(ppc_elf_check_relocs): Set new_plt and old_plt.
|
||||
(ppc_elf_select_plt_layout): New function.
|
||||
(ppc_elf_tls_setup): Set plt output section elf type and flags.
|
||||
(allocate_got): Handle differences between old and new got layout.
|
||||
(allocate_dynrelocs): Likewise for plt.
|
||||
(ppc_elf_size_dynamic_sections): Likewise. Allocate memory for
|
||||
.glink. Don't allocate memory for old bss .plt. Emit DT_PPC_GLINK.
|
||||
(ppc_elf_relax_section): Rename ppc_info to htab. Handle .glink
|
||||
destination of R_PPC_PLTREL24 relocs.
|
||||
(ppc_elf_relocate_section): Handle new relocs and changed destination
|
||||
of R_PPC_PLTREL24.
|
||||
(ppc_elf_finish_dynamic_symbol): Init new style plt and handle
|
||||
differences in layout.
|
||||
(ppc_elf_finish_dynamic_sections): Set DT_PPC_GLINK value. Don't
|
||||
put a blrl in new got. Write glink contents.
|
||||
* elf32-ppc.h (ppc_elf_select_plt_layout): Declare.
|
||||
* libbfd.h: Regenerate.
|
||||
* bfd-in2.h: Regenerate.
|
||||
|
||||
2005-05-11 Andreas Schwab <schwab@suse.de>
|
||||
|
||||
* elf32-i386.c (elf_i386_finish_dynamic_sections): Fix signedness
|
||||
@ -1032,8 +1067,7 @@
|
||||
* configure.in: Check for ffs decl and alphabetize.
|
||||
* config.in: Regenerate.
|
||||
* configure: Regenerate.
|
||||
* sysdep.h [NEED_DECLARATION_FFS] (ffs): Prototype and
|
||||
alphabetize.
|
||||
* sysdep.h [NEED_DECLARATION_FFS] (ffs): Prototype and alphabetize.
|
||||
|
||||
2005-03-29 Fred Fish <fnf@specifixinc.com>
|
||||
|
||||
|
@ -2441,6 +2441,15 @@ to compensate for the borrow when the low bits are added. */
|
||||
/* Low 16 bits. */
|
||||
BFD_RELOC_LO16,
|
||||
|
||||
/* High 16 bits of 32-bit pc-relative value */
|
||||
BFD_RELOC_HI16_PCREL,
|
||||
|
||||
/* High 16 bits of 32-bit pc-relative value, adjusted */
|
||||
BFD_RELOC_HI16_S_PCREL,
|
||||
|
||||
/* Low 16 bits of pc-relative value */
|
||||
BFD_RELOC_LO16_PCREL,
|
||||
|
||||
/* MIPS16 high 16 bits of 32-bit value. */
|
||||
BFD_RELOC_MIPS16_HI16,
|
||||
|
||||
|
421
bfd/elf32-ppc.c
421
bfd/elf32-ppc.c
@ -51,6 +51,7 @@ static bfd_reloc_status_type ppc_elf_unhandled_reloc
|
||||
section. */
|
||||
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
||||
|
||||
/* For old-style PLT. */
|
||||
/* The size in bytes of an entry in the procedure linkage table. */
|
||||
#define PLT_ENTRY_SIZE 12
|
||||
/* The initial size of the plt reserved for the dynamic linker. */
|
||||
@ -60,10 +61,23 @@ static bfd_reloc_status_type ppc_elf_unhandled_reloc
|
||||
/* The number of single-slot PLT entries (the rest use two slots). */
|
||||
#define PLT_NUM_SINGLE_ENTRIES 8192
|
||||
|
||||
/* Some nop instructions. */
|
||||
/* For new-style .glink and .plt. */
|
||||
#define GLINK_PLTRESOLVE 12*4
|
||||
#define GLINK_ENTRY_SIZE 4*4
|
||||
|
||||
/* Some instructions. */
|
||||
#define NOP 0x60000000
|
||||
#define CROR_151515 0x4def7b82
|
||||
#define CROR_313131 0x4ffffb82
|
||||
#define ADDIS_11_11 0x3d6b0000
|
||||
#define ADDI_11_11 0x396b0000
|
||||
#define SUB_11_11_30 0x7d7e5850
|
||||
#define ADD_0_11_11 0x7c0b5a14
|
||||
#define ADD_11_0_11 0x7d605a14
|
||||
#define LWZ_0_4_30 0x801e0004
|
||||
#define MTCTR_0 0x7c0903a6
|
||||
#define LWZ_12_8_30 0x819e0008
|
||||
#define BCTR 0x4e800420
|
||||
#define ADDIS_11_30 0x3d7e0000
|
||||
#define LWZU_0_X_11 0x840b0000
|
||||
|
||||
/* Offset of tp and dtp pointers from start of TLS block. */
|
||||
#define TP_OFFSET 0x7000
|
||||
@ -1259,6 +1273,67 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
||||
0xffff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit relative relocation. */
|
||||
HOWTO (R_PPC_REL16, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC_REL16", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit relative relocation without overflow. */
|
||||
HOWTO (R_PPC_REL16_LO, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC_REL16_LO", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* The high order 16 bits of a relative address. */
|
||||
HOWTO (R_PPC_REL16_HI, /* type */
|
||||
16, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC_REL16_HI", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* The high order 16 bits of a relative address, plus 1 if the contents of
|
||||
the low 16 bits, treated as a signed number, is negative. */
|
||||
HOWTO (R_PPC_REL16_HA, /* type */
|
||||
16, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
ppc_elf_addr16_ha_reloc, /* special_function */
|
||||
"R_PPC_REL16_HA", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy. */
|
||||
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
|
||||
0, /* rightshift */
|
||||
@ -1418,6 +1493,10 @@ ppc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break;
|
||||
case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break;
|
||||
case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break;
|
||||
case BFD_RELOC_16_PCREL: r = R_PPC_REL16; break;
|
||||
case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break;
|
||||
case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break;
|
||||
case BFD_RELOC_HI16_S_PCREL: r = R_PPC_REL16_HA; break;
|
||||
case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break;
|
||||
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break;
|
||||
}
|
||||
@ -1440,7 +1519,7 @@ ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
|
||||
}
|
||||
|
||||
/* Handle the R_PPC_ADDR16_HA reloc. */
|
||||
/* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
@ -1470,6 +1549,8 @@ ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
relocation += symbol->section->output_section->vma;
|
||||
relocation += symbol->section->output_offset;
|
||||
relocation += reloc_entry->addend;
|
||||
if (reloc_entry->howto->pc_relative)
|
||||
relocation -= reloc_entry->address;
|
||||
|
||||
reloc_entry->addend += (relocation & 0x8000) << 1;
|
||||
|
||||
@ -2164,6 +2245,7 @@ struct ppc_elf_link_hash_table
|
||||
/* Short-cuts to get to dynamic linker sections. */
|
||||
asection *got;
|
||||
asection *relgot;
|
||||
asection *glink;
|
||||
asection *plt;
|
||||
asection *relplt;
|
||||
asection *dynbss;
|
||||
@ -2182,11 +2264,18 @@ struct ppc_elf_link_hash_table
|
||||
bfd_vma offset;
|
||||
} tlsld_got;
|
||||
|
||||
/* Offset of PltResolve function in glink. */
|
||||
bfd_vma glink_pltresolve;
|
||||
|
||||
/* Size of reserved GOT entries. */
|
||||
unsigned int got_header_size;
|
||||
/* Non-zero if allocating the header left a gap. */
|
||||
unsigned int got_gap;
|
||||
|
||||
/* Whether to use new plt/got layout or not. */
|
||||
unsigned int new_plt:1;
|
||||
unsigned int old_plt:1;
|
||||
|
||||
/* Small local sym to section mapping cache. */
|
||||
struct sym_sec_cache sym_sec;
|
||||
};
|
||||
@ -2306,8 +2395,14 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
if (!_bfd_elf_create_dynamic_sections (abfd, info))
|
||||
return FALSE;
|
||||
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED);
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||
|
||||
s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags | SEC_CODE);
|
||||
htab->glink = s;
|
||||
if (s == NULL
|
||||
|| !bfd_set_section_alignment (abfd, s, 4))
|
||||
return FALSE;
|
||||
|
||||
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
|
||||
s = bfd_make_section_with_flags (abfd, ".dynsbss",
|
||||
@ -2319,8 +2414,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
if (! info->shared)
|
||||
{
|
||||
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
|
||||
s = bfd_make_section_with_flags (abfd, ".rela.sbss",
|
||||
flags | SEC_READONLY);
|
||||
s = bfd_make_section_with_flags (abfd, ".rela.sbss", flags);
|
||||
htab->relsbss = s;
|
||||
if (s == NULL
|
||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||
@ -2845,6 +2939,13 @@ ppc_elf_check_relocs (bfd *abfd,
|
||||
case R_PPC_TOC16:
|
||||
break;
|
||||
|
||||
case R_PPC_REL16:
|
||||
case R_PPC_REL16_LO:
|
||||
case R_PPC_REL16_HI:
|
||||
case R_PPC_REL16_HA:
|
||||
htab->new_plt = 1;
|
||||
break;
|
||||
|
||||
/* This are just markers. */
|
||||
case R_PPC_TLS:
|
||||
case R_PPC_EMB_MRKREF:
|
||||
@ -2870,6 +2971,8 @@ ppc_elf_check_relocs (bfd *abfd,
|
||||
|
||||
/* This refers only to functions defined in the shared library. */
|
||||
case R_PPC_LOCAL24PC:
|
||||
if (h && h == htab->elf.hgot)
|
||||
htab->old_plt = 1;
|
||||
break;
|
||||
|
||||
/* This relocation describes the C++ object vtable hierarchy.
|
||||
@ -2913,8 +3016,13 @@ ppc_elf_check_relocs (bfd *abfd,
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
case R_PPC_REL32:
|
||||
if (h == NULL || h == htab->elf.hgot)
|
||||
if (h == NULL)
|
||||
break;
|
||||
if (h == htab->elf.hgot)
|
||||
{
|
||||
htab->old_plt = 1;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case R_PPC_ADDR32:
|
||||
@ -3157,6 +3265,43 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Choose which PLT scheme to use, and set .plt flags appropriately.
|
||||
Returns -1 on error, 0 for old PLT, 1 for new PLT. */
|
||||
int
|
||||
ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info,
|
||||
int force_old_plt)
|
||||
{
|
||||
struct ppc_elf_link_hash_table *htab;
|
||||
|
||||
htab = ppc_elf_hash_table (info);
|
||||
if (force_old_plt || !htab->new_plt)
|
||||
htab->old_plt = 1;
|
||||
|
||||
if (!htab->old_plt)
|
||||
{
|
||||
/* The new PLT is a loaded section. Fix its flags. */
|
||||
if (htab->plt != NULL)
|
||||
{
|
||||
flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
|
||||
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||
|
||||
if (!bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Stop an unused .glink section from affecting .text alignment. */
|
||||
if (htab->glink != NULL)
|
||||
{
|
||||
if (!bfd_set_section_alignment (htab->elf.dynobj, htab->glink, 0))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return !htab->old_plt;
|
||||
}
|
||||
|
||||
/* Return the section that should be marked against GC for a given
|
||||
relocation. */
|
||||
|
||||
@ -3334,9 +3479,16 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
|
||||
struct ppc_elf_link_hash_table *htab;
|
||||
|
||||
htab = ppc_elf_hash_table (info);
|
||||
if (!htab->old_plt
|
||||
&& htab->plt != NULL
|
||||
&& htab->plt->output_section != NULL)
|
||||
{
|
||||
elf_section_type (htab->plt->output_section) = SHT_PROGBITS;
|
||||
elf_section_flags (htab->plt->output_section) = SHF_ALLOC + SHF_WRITE;
|
||||
}
|
||||
|
||||
htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
|
||||
FALSE, FALSE, TRUE);
|
||||
|
||||
return _bfd_elf_tls_setup (obfd, info);
|
||||
}
|
||||
|
||||
@ -3706,7 +3858,10 @@ static bfd_vma
|
||||
allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
|
||||
{
|
||||
bfd_vma where;
|
||||
unsigned int max_before_header = 32764;
|
||||
unsigned int max_before_header = 32768;
|
||||
|
||||
if (htab->old_plt)
|
||||
max_before_header = 32764;
|
||||
|
||||
if (need <= htab->got_gap)
|
||||
{
|
||||
@ -3763,37 +3918,54 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
||||
{
|
||||
asection *s = htab->plt;
|
||||
|
||||
/* If this is the first .plt entry, make room for the special
|
||||
first entry. */
|
||||
if (s->size == 0)
|
||||
s->size += PLT_INITIAL_ENTRY_SIZE;
|
||||
|
||||
/* The PowerPC PLT is actually composed of two parts, the
|
||||
first part is 2 words (for a load and a jump), and then
|
||||
there is a remaining word available at the end. */
|
||||
h->plt.offset = (PLT_INITIAL_ENTRY_SIZE
|
||||
+ (PLT_SLOT_SIZE
|
||||
* ((s->size - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ PLT_ENTRY_SIZE)));
|
||||
|
||||
/* If this symbol is not defined in a regular file, and we
|
||||
are not generating a shared library, then set the symbol
|
||||
to this location in the .plt. This is required to make
|
||||
function pointers compare as equal between the normal
|
||||
executable and the shared library. */
|
||||
if (! info->shared
|
||||
&& !h->def_regular)
|
||||
if (!htab->old_plt)
|
||||
{
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = h->plt.offset;
|
||||
}
|
||||
h->plt.offset = s->size;
|
||||
s->size += 4;
|
||||
|
||||
/* Make room for this entry. After the 8192nd entry, room
|
||||
for two entries is allocated. */
|
||||
s->size += PLT_ENTRY_SIZE;
|
||||
if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
|
||||
> PLT_NUM_SINGLE_ENTRIES)
|
||||
s->size += PLT_ENTRY_SIZE;
|
||||
s = htab->glink;
|
||||
if (!info->shared
|
||||
&& !h->def_regular)
|
||||
{
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = s->size;
|
||||
}
|
||||
s->size += GLINK_ENTRY_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If this is the first .plt entry, make room for the
|
||||
special first entry. */
|
||||
if (s->size == 0)
|
||||
s->size += PLT_INITIAL_ENTRY_SIZE;
|
||||
|
||||
/* The PowerPC PLT is actually composed of two parts, the
|
||||
first part is 2 words (for a load and a jump), and then
|
||||
there is a remaining word available at the end. */
|
||||
h->plt.offset = (PLT_INITIAL_ENTRY_SIZE
|
||||
+ (PLT_SLOT_SIZE
|
||||
* ((s->size - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ PLT_ENTRY_SIZE)));
|
||||
|
||||
/* If this symbol is not defined in a regular file, and we
|
||||
are not generating a shared library, then set the symbol
|
||||
to this location in the .plt. This is required to make
|
||||
function pointers compare as equal between the normal
|
||||
executable and the shared library. */
|
||||
if (! info->shared
|
||||
&& !h->def_regular)
|
||||
{
|
||||
h->root.u.def.section = s;
|
||||
h->root.u.def.value = h->plt.offset;
|
||||
}
|
||||
|
||||
/* Make room for this entry. After the 8192nd entry, room
|
||||
for two entries is allocated. */
|
||||
s->size += PLT_ENTRY_SIZE;
|
||||
if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
|
||||
> PLT_NUM_SINGLE_ENTRIES)
|
||||
s->size += PLT_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
/* We also need to make an entry in the .rela.plt section. */
|
||||
htab->relplt->size += sizeof (Elf32_External_Rela);
|
||||
@ -4010,7 +4182,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
}
|
||||
}
|
||||
|
||||
htab->got_header_size = 16;
|
||||
if (htab->old_plt)
|
||||
htab->got_header_size = 16;
|
||||
else
|
||||
htab->got_header_size = 12;
|
||||
|
||||
/* Set up .got offsets for local syms, and space for local dynamic
|
||||
relocs. */
|
||||
@ -4118,11 +4293,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
g_o_t = htab->got->size;
|
||||
htab->got->size += htab->got_header_size;
|
||||
}
|
||||
g_o_t += 4;
|
||||
if (htab->old_plt)
|
||||
g_o_t += 4;
|
||||
|
||||
htab->elf.hgot->root.u.def.value = g_o_t;
|
||||
}
|
||||
|
||||
if (htab->glink != NULL && htab->glink->size != 0)
|
||||
{
|
||||
htab->glink_pltresolve = htab->glink->size;
|
||||
htab->glink->size += GLINK_PLTRESOLVE;
|
||||
}
|
||||
|
||||
/* We've now determined the sizes of the various dynamic sections.
|
||||
Allocate memory for them. */
|
||||
relocs = FALSE;
|
||||
@ -4132,6 +4314,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
continue;
|
||||
|
||||
if (s == htab->plt
|
||||
|| s == htab->glink
|
||||
|| s == htab->got
|
||||
|| s == htab->sbss)
|
||||
{
|
||||
@ -4179,7 +4362,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s == htab->sbss)
|
||||
if ((s->flags & SEC_HAS_CONTENTS) == 0)
|
||||
continue;
|
||||
|
||||
/* Allocate memory for the section contents. */
|
||||
@ -4213,6 +4396,12 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (htab->glink != NULL && htab->glink->size != 0)
|
||||
{
|
||||
if (!add_dynamic_entry (DT_PPC_GLINK, 0))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (relocs)
|
||||
{
|
||||
if (!add_dynamic_entry (DT_RELA, 0)
|
||||
@ -4281,7 +4470,7 @@ ppc_elf_relax_section (bfd *abfd,
|
||||
Elf_Internal_Rela *irel, *irelend;
|
||||
struct one_fixup *fixups = NULL;
|
||||
bfd_boolean changed;
|
||||
struct ppc_elf_link_hash_table *ppc_info;
|
||||
struct ppc_elf_link_hash_table *htab;
|
||||
bfd_size_type trampoff;
|
||||
|
||||
*again = FALSE;
|
||||
@ -4305,7 +4494,7 @@ ppc_elf_relax_section (bfd *abfd,
|
||||
if (internal_relocs == NULL)
|
||||
goto error_return;
|
||||
|
||||
ppc_info = ppc_elf_hash_table (link_info);
|
||||
htab = ppc_elf_hash_table (link_info);
|
||||
irelend = internal_relocs + isec->reloc_count;
|
||||
|
||||
for (irel = internal_relocs; irel < irelend; irel++)
|
||||
@ -4382,11 +4571,19 @@ ppc_elf_relax_section (bfd *abfd,
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
if (r_type == R_PPC_PLTREL24
|
||||
&& ppc_info->plt != NULL
|
||||
&& htab->plt != NULL
|
||||
&& h->plt.offset != (bfd_vma) -1)
|
||||
{
|
||||
tsec = ppc_info->plt;
|
||||
toff = h->plt.offset;
|
||||
if (!htab->old_plt)
|
||||
{
|
||||
tsec = htab->glink;
|
||||
toff = h->plt.offset * (GLINK_ENTRY_SIZE / 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
tsec = htab->plt;
|
||||
toff = h->plt.offset;
|
||||
}
|
||||
}
|
||||
else if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
@ -4483,7 +4680,8 @@ ppc_elf_relax_section (bfd *abfd,
|
||||
if (R_PPC_RELAX32_PLT - R_PPC_RELAX32
|
||||
!= R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC)
|
||||
abort ();
|
||||
if (tsec == ppc_info->plt)
|
||||
if (tsec == htab->plt
|
||||
|| tsec == htab->glink)
|
||||
stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32;
|
||||
|
||||
/* Hijack the old relocation. Since we need two
|
||||
@ -5426,6 +5624,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
addend = 0;
|
||||
goto dodyn;
|
||||
|
||||
case R_PPC_REL16:
|
||||
case R_PPC_REL16_LO:
|
||||
case R_PPC_REL16_HI:
|
||||
case R_PPC_REL16_HA:
|
||||
break;
|
||||
|
||||
case R_PPC_REL24:
|
||||
case R_PPC_REL32:
|
||||
case R_PPC_REL14:
|
||||
@ -5595,9 +5799,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
&& h->plt.offset != (bfd_vma) -1
|
||||
&& htab->plt != NULL);
|
||||
|
||||
relocation = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
+ h->plt.offset);
|
||||
if (!htab->old_plt)
|
||||
relocation = (htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset
|
||||
+ h->plt.offset * (GLINK_ENTRY_SIZE / 4));
|
||||
else
|
||||
relocation = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
+ h->plt.offset);
|
||||
if (r_type == R_PPC_RELAX32_PLT)
|
||||
goto relax32;
|
||||
/* Fall thru */
|
||||
@ -5676,9 +5885,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
|
||||
unresolved_reloc = FALSE;
|
||||
relocation = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
+ h->plt.offset);
|
||||
if (!htab->old_plt)
|
||||
relocation = (htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset
|
||||
+ h->plt.offset * (GLINK_ENTRY_SIZE / 4));
|
||||
else
|
||||
relocation = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
+ h->plt.offset);
|
||||
break;
|
||||
|
||||
/* Relocate against _SDA_BASE_. */
|
||||
@ -5837,6 +6051,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16_HA:
|
||||
case R_PPC_REL16_HA:
|
||||
case R_PPC_GOT16_HA:
|
||||
case R_PPC_PLT16_HA:
|
||||
case R_PPC_SECTOFF_HA:
|
||||
@ -5974,8 +6189,18 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
BFD_ASSERT (h->dynindx != -1);
|
||||
BFD_ASSERT (htab->plt != NULL && htab->relplt != NULL);
|
||||
|
||||
/* We don't need to fill in the .plt. The ppc dynamic linker
|
||||
will fill it in. */
|
||||
if (htab->old_plt)
|
||||
{
|
||||
/* We don't need to fill in the .plt. The ppc dynamic linker
|
||||
will fill it in. */
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_vma val = (htab->glink_pltresolve
|
||||
+ htab->glink->output_section->vma
|
||||
+ htab->glink->output_offset);
|
||||
bfd_put_32 (output_bfd, val, htab->plt->contents + h->plt.offset);
|
||||
}
|
||||
|
||||
/* Fill in the entry in the .rela.plt section. */
|
||||
rela.r_offset = (htab->plt->output_section->vma
|
||||
@ -5984,9 +6209,15 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
|
||||
rela.r_addend = 0;
|
||||
|
||||
reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE;
|
||||
if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
|
||||
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
|
||||
if (!htab->old_plt)
|
||||
reloc_index = h->plt.offset / 4;
|
||||
else
|
||||
{
|
||||
reloc_index = ((h->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ PLT_SLOT_SIZE);
|
||||
if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
|
||||
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
|
||||
}
|
||||
loc = (htab->relplt->contents
|
||||
+ reloc_index * sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
@ -6112,6 +6343,12 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
||||
break;
|
||||
|
||||
case DT_PPC_GLINK:
|
||||
s = htab->glink;
|
||||
dyn.d_un.d_ptr = (htab->glink_pltresolve
|
||||
+ s->output_section->vma + s->output_offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -6128,7 +6365,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
bfd_vma val;
|
||||
|
||||
p += elf_hash_table (info)->hgot->root.u.def.value;
|
||||
bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
|
||||
if (htab->old_plt)
|
||||
bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
|
||||
|
||||
val = 0;
|
||||
if (sdyn != NULL)
|
||||
@ -6138,6 +6376,67 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||
elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
|
||||
}
|
||||
|
||||
if (htab->glink != NULL && htab->glink->contents != NULL)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned char *endp;
|
||||
bfd_vma pltgot;
|
||||
unsigned int i;
|
||||
static const unsigned int plt_resolve[] =
|
||||
{
|
||||
SUB_11_11_30,
|
||||
ADD_0_11_11,
|
||||
ADD_11_0_11,
|
||||
LWZ_0_4_30,
|
||||
MTCTR_0,
|
||||
LWZ_12_8_30,
|
||||
BCTR,
|
||||
NOP,
|
||||
NOP,
|
||||
NOP
|
||||
};
|
||||
|
||||
#define PPC_LO(v) ((v) & 0xffff)
|
||||
#define PPC_HI(v) (((v) >> 16) & 0xffff)
|
||||
#define PPC_HA(v) PPC_HI ((v) + 0x8000)
|
||||
|
||||
pltgot = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
- htab->elf.hgot->root.u.def.value
|
||||
- htab->elf.hgot->root.u.def.section->output_section->vma
|
||||
- htab->elf.hgot->root.u.def.section->output_offset);
|
||||
|
||||
p = htab->glink->contents;
|
||||
p += htab->glink_pltresolve;
|
||||
bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (-pltgot), p);
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (-pltgot), p);
|
||||
p += 4;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (plt_resolve); i++)
|
||||
{
|
||||
bfd_put_32 (output_bfd, plt_resolve[i], p);
|
||||
p += 4;
|
||||
}
|
||||
if (ARRAY_SIZE (plt_resolve) + 2 != GLINK_PLTRESOLVE / 4)
|
||||
abort ();
|
||||
|
||||
p = htab->glink->contents;
|
||||
endp = p + htab->glink_pltresolve;
|
||||
while (p < endp)
|
||||
{
|
||||
bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (pltgot), p);
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, LWZU_0_X_11 + PPC_LO (pltgot), p);
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, MTCTR_0, p);
|
||||
p += 4;
|
||||
bfd_put_32 (output_bfd, BCTR, p);
|
||||
p += 4;
|
||||
pltgot += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int);
|
||||
asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
|
||||
bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
|
||||
bfd_boolean ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);
|
||||
|
@ -907,6 +907,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_HI16",
|
||||
"BFD_RELOC_HI16_S",
|
||||
"BFD_RELOC_LO16",
|
||||
"BFD_RELOC_HI16_PCREL",
|
||||
"BFD_RELOC_HI16_S_PCREL",
|
||||
"BFD_RELOC_LO16_PCREL",
|
||||
"BFD_RELOC_MIPS16_HI16",
|
||||
"BFD_RELOC_MIPS16_HI16_S",
|
||||
"BFD_RELOC_MIPS16_LO16",
|
||||
|
13
bfd/reloc.c
13
bfd/reloc.c
@ -2062,6 +2062,19 @@ ENUM
|
||||
ENUMDOC
|
||||
Low 16 bits.
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_HI16_PCREL
|
||||
ENUMDOC
|
||||
High 16 bits of 32-bit pc-relative value
|
||||
ENUM
|
||||
BFD_RELOC_HI16_S_PCREL
|
||||
ENUMDOC
|
||||
High 16 bits of 32-bit pc-relative value, adjusted
|
||||
ENUM
|
||||
BFD_RELOC_LO16_PCREL
|
||||
ENUMDOC
|
||||
Low 16 bits of pc-relative value
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_MIPS16_HI16
|
||||
ENUMDOC
|
||||
|
Loading…
Reference in New Issue
Block a user