* 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
6 changed files with 425 additions and 66 deletions
|
@ -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>
|
2005-05-11 Andreas Schwab <schwab@suse.de>
|
||||||
|
|
||||||
* elf32-i386.c (elf_i386_finish_dynamic_sections): Fix signedness
|
* elf32-i386.c (elf_i386_finish_dynamic_sections): Fix signedness
|
||||||
|
@ -145,7 +180,7 @@
|
||||||
(allocate_dynrelocs): Allocate space for static PLT relocations.
|
(allocate_dynrelocs): Allocate space for static PLT relocations.
|
||||||
(elf_i386_size_dynamic_sections): Save shortcuts to PLT and GOT
|
(elf_i386_size_dynamic_sections): Save shortcuts to PLT and GOT
|
||||||
symbols. Give PLT symbols function type. Don't strip PLT sections
|
symbols. Give PLT symbols function type. Don't strip PLT sections
|
||||||
if we have exported symbols from them.
|
if we have exported symbols from them.
|
||||||
(elf_i386_finish_dynamic_symbol): Fill in VxWorks PLT static
|
(elf_i386_finish_dynamic_symbol): Fill in VxWorks PLT static
|
||||||
relocation section. Don't mark _GLOBAL_OFFSET_TABLE_ as absolute on
|
relocation section. Don't mark _GLOBAL_OFFSET_TABLE_ as absolute on
|
||||||
VxWorks.
|
VxWorks.
|
||||||
|
@ -833,7 +868,7 @@
|
||||||
* coffcode.h (STRING_SIZE_SIZE): Updated to match libcoff-in.h.
|
* coffcode.h (STRING_SIZE_SIZE): Updated to match libcoff-in.h.
|
||||||
|
|
||||||
2005-04-11 Nick Clifton <nickc@redhat.com>
|
2005-04-11 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
* aout-target.h: Convert to ISO C.
|
* aout-target.h: Convert to ISO C.
|
||||||
* aoutf1.h: Convert to ISO C.
|
* aoutf1.h: Convert to ISO C.
|
||||||
* aoutx.h: Convert to ISO C.
|
* aoutx.h: Convert to ISO C.
|
||||||
|
@ -917,7 +952,7 @@
|
||||||
2005-04-04 H.J. Lu <hongjiu.lu@intel.com>
|
2005-04-04 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* elf.c (bfd_elf_set_group_contents): Ignore linker created
|
* elf.c (bfd_elf_set_group_contents): Ignore linker created
|
||||||
group section.
|
group section.
|
||||||
(assign_section_numbers): Accept link_info. Check SHT_GROUP
|
(assign_section_numbers): Accept link_info. Check SHT_GROUP
|
||||||
sections for relocatable files only. Remove the linker created
|
sections for relocatable files only. Remove the linker created
|
||||||
group sections.
|
group sections.
|
||||||
|
@ -1032,8 +1067,7 @@
|
||||||
* configure.in: Check for ffs decl and alphabetize.
|
* configure.in: Check for ffs decl and alphabetize.
|
||||||
* config.in: Regenerate.
|
* config.in: Regenerate.
|
||||||
* configure: Regenerate.
|
* configure: Regenerate.
|
||||||
* sysdep.h [NEED_DECLARATION_FFS] (ffs): Prototype and
|
* sysdep.h [NEED_DECLARATION_FFS] (ffs): Prototype and alphabetize.
|
||||||
alphabetize.
|
|
||||||
|
|
||||||
2005-03-29 Fred Fish <fnf@specifixinc.com>
|
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. */
|
/* Low 16 bits. */
|
||||||
BFD_RELOC_LO16,
|
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. */
|
/* MIPS16 high 16 bits of 32-bit value. */
|
||||||
BFD_RELOC_MIPS16_HI16,
|
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. */
|
section. */
|
||||||
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
#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. */
|
/* The size in bytes of an entry in the procedure linkage table. */
|
||||||
#define PLT_ENTRY_SIZE 12
|
#define PLT_ENTRY_SIZE 12
|
||||||
/* The initial size of the plt reserved for the dynamic linker. */
|
/* 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). */
|
/* The number of single-slot PLT entries (the rest use two slots). */
|
||||||
#define PLT_NUM_SINGLE_ENTRIES 8192
|
#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 NOP 0x60000000
|
||||||
#define CROR_151515 0x4def7b82
|
#define ADDIS_11_11 0x3d6b0000
|
||||||
#define CROR_313131 0x4ffffb82
|
#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. */
|
/* Offset of tp and dtp pointers from start of TLS block. */
|
||||||
#define TP_OFFSET 0x7000
|
#define TP_OFFSET 0x7000
|
||||||
|
@ -1259,6 +1273,67 @@ static reloc_howto_type ppc_elf_howto_raw[] = {
|
||||||
0xffff, /* dst_mask */
|
0xffff, /* dst_mask */
|
||||||
FALSE), /* pcrel_offset */
|
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. */
|
/* GNU extension to record C++ vtable hierarchy. */
|
||||||
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
|
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
|
||||||
0, /* rightshift */
|
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_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_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break;
|
||||||
case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; 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_INHERIT: r = R_PPC_GNU_VTINHERIT; break;
|
||||||
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; 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)];
|
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
|
static bfd_reloc_status_type
|
||||||
ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
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_section->vma;
|
||||||
relocation += symbol->section->output_offset;
|
relocation += symbol->section->output_offset;
|
||||||
relocation += reloc_entry->addend;
|
relocation += reloc_entry->addend;
|
||||||
|
if (reloc_entry->howto->pc_relative)
|
||||||
|
relocation -= reloc_entry->address;
|
||||||
|
|
||||||
reloc_entry->addend += (relocation & 0x8000) << 1;
|
reloc_entry->addend += (relocation & 0x8000) << 1;
|
||||||
|
|
||||||
|
@ -2164,6 +2245,7 @@ struct ppc_elf_link_hash_table
|
||||||
/* Short-cuts to get to dynamic linker sections. */
|
/* Short-cuts to get to dynamic linker sections. */
|
||||||
asection *got;
|
asection *got;
|
||||||
asection *relgot;
|
asection *relgot;
|
||||||
|
asection *glink;
|
||||||
asection *plt;
|
asection *plt;
|
||||||
asection *relplt;
|
asection *relplt;
|
||||||
asection *dynbss;
|
asection *dynbss;
|
||||||
|
@ -2182,11 +2264,18 @@ struct ppc_elf_link_hash_table
|
||||||
bfd_vma offset;
|
bfd_vma offset;
|
||||||
} tlsld_got;
|
} tlsld_got;
|
||||||
|
|
||||||
|
/* Offset of PltResolve function in glink. */
|
||||||
|
bfd_vma glink_pltresolve;
|
||||||
|
|
||||||
/* Size of reserved GOT entries. */
|
/* Size of reserved GOT entries. */
|
||||||
unsigned int got_header_size;
|
unsigned int got_header_size;
|
||||||
/* Non-zero if allocating the header left a gap. */
|
/* Non-zero if allocating the header left a gap. */
|
||||||
unsigned int got_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. */
|
/* Small local sym to section mapping cache. */
|
||||||
struct sym_sec_cache sym_sec;
|
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))
|
if (!_bfd_elf_create_dynamic_sections (abfd, info))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
|
||||||
| SEC_LINKER_CREATED);
|
| 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");
|
htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
|
||||||
s = bfd_make_section_with_flags (abfd, ".dynsbss",
|
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)
|
if (! info->shared)
|
||||||
{
|
{
|
||||||
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
|
htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
|
||||||
s = bfd_make_section_with_flags (abfd, ".rela.sbss",
|
s = bfd_make_section_with_flags (abfd, ".rela.sbss", flags);
|
||||||
flags | SEC_READONLY);
|
|
||||||
htab->relsbss = s;
|
htab->relsbss = s;
|
||||||
if (s == NULL
|
if (s == NULL
|
||||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||||
|
@ -2845,6 +2939,13 @@ ppc_elf_check_relocs (bfd *abfd,
|
||||||
case R_PPC_TOC16:
|
case R_PPC_TOC16:
|
||||||
break;
|
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. */
|
/* This are just markers. */
|
||||||
case R_PPC_TLS:
|
case R_PPC_TLS:
|
||||||
case R_PPC_EMB_MRKREF:
|
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. */
|
/* This refers only to functions defined in the shared library. */
|
||||||
case R_PPC_LOCAL24PC:
|
case R_PPC_LOCAL24PC:
|
||||||
|
if (h && h == htab->elf.hgot)
|
||||||
|
htab->old_plt = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* This relocation describes the C++ object vtable hierarchy.
|
/* 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_BRTAKEN:
|
||||||
case R_PPC_REL14_BRNTAKEN:
|
case R_PPC_REL14_BRNTAKEN:
|
||||||
case R_PPC_REL32:
|
case R_PPC_REL32:
|
||||||
if (h == NULL || h == htab->elf.hgot)
|
if (h == NULL)
|
||||||
break;
|
break;
|
||||||
|
if (h == htab->elf.hgot)
|
||||||
|
{
|
||||||
|
htab->old_plt = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case R_PPC_ADDR32:
|
case R_PPC_ADDR32:
|
||||||
|
@ -3157,6 +3265,43 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
|
||||||
return TRUE;
|
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
|
/* Return the section that should be marked against GC for a given
|
||||||
relocation. */
|
relocation. */
|
||||||
|
|
||||||
|
@ -3334,9 +3479,16 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
|
||||||
struct ppc_elf_link_hash_table *htab;
|
struct ppc_elf_link_hash_table *htab;
|
||||||
|
|
||||||
htab = ppc_elf_hash_table (info);
|
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",
|
htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
|
||||||
FALSE, FALSE, TRUE);
|
FALSE, FALSE, TRUE);
|
||||||
|
|
||||||
return _bfd_elf_tls_setup (obfd, info);
|
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)
|
allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
|
||||||
{
|
{
|
||||||
bfd_vma where;
|
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)
|
if (need <= htab->got_gap)
|
||||||
{
|
{
|
||||||
|
@ -3763,37 +3918,54 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
||||||
{
|
{
|
||||||
asection *s = htab->plt;
|
asection *s = htab->plt;
|
||||||
|
|
||||||
/* If this is the first .plt entry, make room for the special
|
if (!htab->old_plt)
|
||||||
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->plt.offset = s->size;
|
||||||
h->root.u.def.value = h->plt.offset;
|
s->size += 4;
|
||||||
}
|
|
||||||
|
|
||||||
/* Make room for this entry. After the 8192nd entry, room
|
s = htab->glink;
|
||||||
for two entries is allocated. */
|
if (!info->shared
|
||||||
s->size += PLT_ENTRY_SIZE;
|
&& !h->def_regular)
|
||||||
if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
|
{
|
||||||
> PLT_NUM_SINGLE_ENTRIES)
|
h->root.u.def.section = s;
|
||||||
s->size += PLT_ENTRY_SIZE;
|
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. */
|
/* We also need to make an entry in the .rela.plt section. */
|
||||||
htab->relplt->size += sizeof (Elf32_External_Rela);
|
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
|
/* Set up .got offsets for local syms, and space for local dynamic
|
||||||
relocs. */
|
relocs. */
|
||||||
|
@ -4118,11 +4293,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||||
g_o_t = htab->got->size;
|
g_o_t = htab->got->size;
|
||||||
htab->got->size += htab->got_header_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;
|
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.
|
/* We've now determined the sizes of the various dynamic sections.
|
||||||
Allocate memory for them. */
|
Allocate memory for them. */
|
||||||
relocs = FALSE;
|
relocs = FALSE;
|
||||||
|
@ -4132,6 +4314,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (s == htab->plt
|
if (s == htab->plt
|
||||||
|
|| s == htab->glink
|
||||||
|| s == htab->got
|
|| s == htab->got
|
||||||
|| s == htab->sbss)
|
|| s == htab->sbss)
|
||||||
{
|
{
|
||||||
|
@ -4179,7 +4362,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == htab->sbss)
|
if ((s->flags & SEC_HAS_CONTENTS) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Allocate memory for the section contents. */
|
/* Allocate memory for the section contents. */
|
||||||
|
@ -4213,6 +4396,12 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (htab->glink != NULL && htab->glink->size != 0)
|
||||||
|
{
|
||||||
|
if (!add_dynamic_entry (DT_PPC_GLINK, 0))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (relocs)
|
if (relocs)
|
||||||
{
|
{
|
||||||
if (!add_dynamic_entry (DT_RELA, 0)
|
if (!add_dynamic_entry (DT_RELA, 0)
|
||||||
|
@ -4281,7 +4470,7 @@ ppc_elf_relax_section (bfd *abfd,
|
||||||
Elf_Internal_Rela *irel, *irelend;
|
Elf_Internal_Rela *irel, *irelend;
|
||||||
struct one_fixup *fixups = NULL;
|
struct one_fixup *fixups = NULL;
|
||||||
bfd_boolean changed;
|
bfd_boolean changed;
|
||||||
struct ppc_elf_link_hash_table *ppc_info;
|
struct ppc_elf_link_hash_table *htab;
|
||||||
bfd_size_type trampoff;
|
bfd_size_type trampoff;
|
||||||
|
|
||||||
*again = FALSE;
|
*again = FALSE;
|
||||||
|
@ -4305,7 +4494,7 @@ ppc_elf_relax_section (bfd *abfd,
|
||||||
if (internal_relocs == NULL)
|
if (internal_relocs == NULL)
|
||||||
goto error_return;
|
goto error_return;
|
||||||
|
|
||||||
ppc_info = ppc_elf_hash_table (link_info);
|
htab = ppc_elf_hash_table (link_info);
|
||||||
irelend = internal_relocs + isec->reloc_count;
|
irelend = internal_relocs + isec->reloc_count;
|
||||||
|
|
||||||
for (irel = internal_relocs; irel < irelend; irel++)
|
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;
|
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||||
|
|
||||||
if (r_type == R_PPC_PLTREL24
|
if (r_type == R_PPC_PLTREL24
|
||||||
&& ppc_info->plt != NULL
|
&& htab->plt != NULL
|
||||||
&& h->plt.offset != (bfd_vma) -1)
|
&& h->plt.offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
tsec = ppc_info->plt;
|
if (!htab->old_plt)
|
||||||
toff = h->plt.offset;
|
{
|
||||||
|
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
|
else if (h->root.type == bfd_link_hash_defined
|
||||||
|| h->root.type == bfd_link_hash_defweak)
|
|| 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
|
if (R_PPC_RELAX32_PLT - R_PPC_RELAX32
|
||||||
!= R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC)
|
!= R_PPC_RELAX32PC_PLT - R_PPC_RELAX32PC)
|
||||||
abort ();
|
abort ();
|
||||||
if (tsec == ppc_info->plt)
|
if (tsec == htab->plt
|
||||||
|
|| tsec == htab->glink)
|
||||||
stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32;
|
stub_rtype += R_PPC_RELAX32_PLT - R_PPC_RELAX32;
|
||||||
|
|
||||||
/* Hijack the old relocation. Since we need two
|
/* Hijack the old relocation. Since we need two
|
||||||
|
@ -5426,6 +5624,12 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||||
addend = 0;
|
addend = 0;
|
||||||
goto dodyn;
|
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_REL24:
|
||||||
case R_PPC_REL32:
|
case R_PPC_REL32:
|
||||||
case R_PPC_REL14:
|
case R_PPC_REL14:
|
||||||
|
@ -5595,9 +5799,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||||
&& h->plt.offset != (bfd_vma) -1
|
&& h->plt.offset != (bfd_vma) -1
|
||||||
&& htab->plt != NULL);
|
&& htab->plt != NULL);
|
||||||
|
|
||||||
relocation = (htab->plt->output_section->vma
|
if (!htab->old_plt)
|
||||||
+ htab->plt->output_offset
|
relocation = (htab->glink->output_section->vma
|
||||||
+ h->plt.offset);
|
+ 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)
|
if (r_type == R_PPC_RELAX32_PLT)
|
||||||
goto relax32;
|
goto relax32;
|
||||||
/* Fall thru */
|
/* Fall thru */
|
||||||
|
@ -5676,9 +5885,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
relocation = (htab->plt->output_section->vma
|
if (!htab->old_plt)
|
||||||
+ htab->plt->output_offset
|
relocation = (htab->glink->output_section->vma
|
||||||
+ h->plt.offset);
|
+ 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;
|
break;
|
||||||
|
|
||||||
/* Relocate against _SDA_BASE_. */
|
/* Relocate against _SDA_BASE_. */
|
||||||
|
@ -5837,6 +6051,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC_ADDR16_HA:
|
case R_PPC_ADDR16_HA:
|
||||||
|
case R_PPC_REL16_HA:
|
||||||
case R_PPC_GOT16_HA:
|
case R_PPC_GOT16_HA:
|
||||||
case R_PPC_PLT16_HA:
|
case R_PPC_PLT16_HA:
|
||||||
case R_PPC_SECTOFF_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 (h->dynindx != -1);
|
||||||
BFD_ASSERT (htab->plt != NULL && htab->relplt != NULL);
|
BFD_ASSERT (htab->plt != NULL && htab->relplt != NULL);
|
||||||
|
|
||||||
/* We don't need to fill in the .plt. The ppc dynamic linker
|
if (htab->old_plt)
|
||||||
will fill it in. */
|
{
|
||||||
|
/* 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. */
|
/* Fill in the entry in the .rela.plt section. */
|
||||||
rela.r_offset = (htab->plt->output_section->vma
|
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_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
|
||||||
rela.r_addend = 0;
|
rela.r_addend = 0;
|
||||||
|
|
||||||
reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE;
|
if (!htab->old_plt)
|
||||||
if (reloc_index > PLT_NUM_SINGLE_ENTRIES)
|
reloc_index = h->plt.offset / 4;
|
||||||
reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
|
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
|
loc = (htab->relplt->contents
|
||||||
+ reloc_index * sizeof (Elf32_External_Rela));
|
+ reloc_index * sizeof (Elf32_External_Rela));
|
||||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
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;
|
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
|
||||||
break;
|
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:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -6128,7 +6365,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
|
||||||
bfd_vma val;
|
bfd_vma val;
|
||||||
|
|
||||||
p += elf_hash_table (info)->hgot->root.u.def.value;
|
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;
|
val = 0;
|
||||||
if (sdyn != NULL)
|
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;
|
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;
|
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
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
|
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 *);
|
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_tls_optimize (bfd *, struct bfd_link_info *);
|
||||||
bfd_boolean ppc_elf_set_sdata_syms (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",
|
||||||
"BFD_RELOC_HI16_S",
|
"BFD_RELOC_HI16_S",
|
||||||
"BFD_RELOC_LO16",
|
"BFD_RELOC_LO16",
|
||||||
|
"BFD_RELOC_HI16_PCREL",
|
||||||
|
"BFD_RELOC_HI16_S_PCREL",
|
||||||
|
"BFD_RELOC_LO16_PCREL",
|
||||||
"BFD_RELOC_MIPS16_HI16",
|
"BFD_RELOC_MIPS16_HI16",
|
||||||
"BFD_RELOC_MIPS16_HI16_S",
|
"BFD_RELOC_MIPS16_HI16_S",
|
||||||
"BFD_RELOC_MIPS16_LO16",
|
"BFD_RELOC_MIPS16_LO16",
|
||||||
|
|
13
bfd/reloc.c
13
bfd/reloc.c
|
@ -2062,6 +2062,19 @@ ENUM
|
||||||
ENUMDOC
|
ENUMDOC
|
||||||
Low 16 bits.
|
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
|
ENUM
|
||||||
BFD_RELOC_MIPS16_HI16
|
BFD_RELOC_MIPS16_HI16
|
||||||
ENUMDOC
|
ENUMDOC
|
||||||
|
|
Loading…
Reference in a new issue