This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
ppc64 tls support
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Date: Wed, 5 Feb 2003 01:17:22 +1030
- Subject: ppc64 tls support
Here's the ppc64 TLS support. As noted in a previous email, this patch
also changes got relocations to handle an addend a little more sensibly.
Oh yeah, I spent some effort to make --emit-relocs work when tls
optimization edits code and relocs, something I think other back-ends
don't bother to do..
include/elf/ChangeLog
* ppc.h: Add TLS relocs. Format.
* ppc64.h: Likewise.
bfd/ChangeLog
* reloc.c: Add PPC and PPC64 TLS relocs.
* libbfd.h: Regenerate.
* bfd-in2.h: Regenerate.
* elf64-ppc.c (TP_OFFSET, DTP_OFFSET): Declare.
(ppc64_elf_howto_raw): Add TLS howto's. Adjust R_PPC64_NONE to be
against a 32 bit field.
(ppc64_elf_reloc_type_lookup): Handle TLS relocs.
(_ppc64_elf_section_data): Add t_symndx and comments.
(ppc64_elf_section_data): Use elf_section_data macro.
(ppc64_elf_new_section_hook): American spelling.
(struct got_entry, struct plt_entry): New.
(MUST_BE_DYN_RELOC): Rename from IS_ABSOLUTE_RELOC.
(struct ppc_stub_hash_entry): Add "addend" field.
(struct ppc_link_hash_entry): Add "tls_type".
(TLS_TLS, TLS_GD_LD, TLS_LD, TLS_TPREL, TLS_DTPREL,
TLS_EXPLICIT): Define.
(struct ppc_link_hash_table): Add tls_sec, tls_get_addr, tlsld_got.
(link_hash_newfunc): Init new fields.
(ppc64_elf_link_hash_table_create): Likewise. Set init_relcount and
init_offset to NULL.
(ppc64_elf_copy_indirect_symbol): Copy got and plt info. Don't call
_bfd_elf_link_hash_copy_indirect, rather insert relevant code from
there.
(update_local_sym_info, update_plt_info): New functions.
(ppc64_elf_check_relocs): Use them. Handle TLS relocs. Adjust GOT
handling to use got.glist rather than got.refcount. Likewise for PLT.
(ppc64_elf_gc_sweep_hook): Handle TLS relocs, new GOT and PLT lists.
(func_desc_adjust): Adjust for new PLT list.
(ppc64_elf_adjust_dynamic_symbol): Likewise.
(get_sym_h, get_tls_type): New functions.
(ppc64_elf_edit_opd): Remove unused variable. Use get_sym_h.
(ppc64_elf_tls_optimize): New function.
(allocate_dynrelocs): Adjust for new PLT and GOT lists. Allocate
TLS relocs.
(ppc64_elf_size_dynamic_sections): Likewise.
(ppc_type_of_stub): Adjust for new PLT list.
(ppc_build_one_stub): Likewise.
(ppc64_elf_size_stubs): Likewise. Use get_sym_h. Treat __tls_get_addr
calls specially.
(ppc64_elf_relocate_section): Adjust for new GOT and PLT lists. Handle
TLS relocs. Report local syms using bfd_elf_local_sym_name. Don't
init GOT entries that have a reloc. Generate GOT relocs here..
(ppc64_elf_finish_dynamic_symbol): ..not here. Adjust for PLT list.
* elf64-ppc.h (ppc64_elf_tls_optimize): Declare.
gas/ChangeLog
* config/tc-ppc.c (mapping): Handle new TLS reloc specs.
(ppc_elf_suffix): Don't warn for x+off@got when ppc64 and don't
accept x@got+off etc.
(md_assemble): Handle TLS relocs.
(ppc_force_relocation): Force for all TLS relocs.
(ppc_fix_adjustable): Likewise.
(md_apply_fix3): Handle TLS relocs.
ld/ChangeLog
* emultempl/ppc64elf.em (ppc_before_allocation): Size sections then
call ppc64_elf_tls_optimize.
ld/testsuite/ChangeLog
* ld-powerpc/powerpc.exp (supports_ppc64): New.
(ppcelftests): Force 32 bit mode.
(ppc64elftests): New.
* ld-powerpc/tls.d: New.
* ld-powerpc/tls.g: New.
* ld-powerpc/tls.s: New.
* ld-powerpc/tls.t: New.
* ld-powerpc/tlsexe.d: New.
* ld-powerpc/tlsexe.g: New.
* ld-powerpc/tlsexe.r: New.
* ld-powerpc/tlsexe.t: New.
* ld-powerpc/tlsexetoc.d: New.
* ld-powerpc/tlsexetoc.g: New.
* ld-powerpc/tlsexetoc.r: New.
* ld-powerpc/tlsexetoc.t: New.
* ld-powerpc/tlslib.s: New.
* ld-powerpc/tlsso.d: New.
* ld-powerpc/tlsso.g: New.
* ld-powerpc/tlsso.r: New.
* ld-powerpc/tlsso.t: New.
* ld-powerpc/tlstoc.d: New.
* ld-powerpc/tlstoc.g: New.
* ld-powerpc/tlstoc.s: New.
* ld-powerpc/tlstoc.t: New.
* ld-powerpc/tlstocso.d: New.
* ld-powerpc/tlstocso.g: New.
* ld-powerpc/tlstocso.r: New.
* ld-powerpc/tlstocso.t: New.
--
Alan Modra
IBM OzLabs - Linux Technology Centre
Index: include/elf/ppc.h
===================================================================
RCS file: /cvs/src/src/include/elf/ppc.h,v
retrieving revision 1.9
diff -u -p -d -r1.9 ppc.h
--- include/elf/ppc.h 16 Jan 2003 04:08:47 -0000 1.9
+++ include/elf/ppc.h 4 Feb 2003 14:02:29 -0000
@@ -32,71 +32,101 @@ Foundation, Inc., 59 Temple Place - Suit
/* Relocations. */
START_RELOC_NUMBERS (elf_ppc_reloc_type)
- RELOC_NUMBER (R_PPC_NONE, 0)
- RELOC_NUMBER (R_PPC_ADDR32, 1)
- RELOC_NUMBER (R_PPC_ADDR24, 2)
- RELOC_NUMBER (R_PPC_ADDR16, 3)
- RELOC_NUMBER (R_PPC_ADDR16_LO, 4)
- RELOC_NUMBER (R_PPC_ADDR16_HI, 5)
- RELOC_NUMBER (R_PPC_ADDR16_HA, 6)
- RELOC_NUMBER (R_PPC_ADDR14, 7)
- RELOC_NUMBER (R_PPC_ADDR14_BRTAKEN, 8)
- RELOC_NUMBER (R_PPC_ADDR14_BRNTAKEN, 9)
- RELOC_NUMBER (R_PPC_REL24, 10)
- RELOC_NUMBER (R_PPC_REL14, 11)
- RELOC_NUMBER (R_PPC_REL14_BRTAKEN, 12)
- RELOC_NUMBER (R_PPC_REL14_BRNTAKEN, 13)
- RELOC_NUMBER (R_PPC_GOT16, 14)
- RELOC_NUMBER (R_PPC_GOT16_LO, 15)
- RELOC_NUMBER (R_PPC_GOT16_HI, 16)
- RELOC_NUMBER (R_PPC_GOT16_HA, 17)
- RELOC_NUMBER (R_PPC_PLTREL24, 18)
- RELOC_NUMBER (R_PPC_COPY, 19)
- RELOC_NUMBER (R_PPC_GLOB_DAT, 20)
- RELOC_NUMBER (R_PPC_JMP_SLOT, 21)
- RELOC_NUMBER (R_PPC_RELATIVE, 22)
- RELOC_NUMBER (R_PPC_LOCAL24PC, 23)
- RELOC_NUMBER (R_PPC_UADDR32, 24)
- RELOC_NUMBER (R_PPC_UADDR16, 25)
- RELOC_NUMBER (R_PPC_REL32, 26)
- RELOC_NUMBER (R_PPC_PLT32, 27)
- RELOC_NUMBER (R_PPC_PLTREL32, 28)
- RELOC_NUMBER (R_PPC_PLT16_LO, 29)
- RELOC_NUMBER (R_PPC_PLT16_HI, 30)
- RELOC_NUMBER (R_PPC_PLT16_HA, 31)
- RELOC_NUMBER (R_PPC_SDAREL16, 32)
- RELOC_NUMBER (R_PPC_SECTOFF, 33)
- RELOC_NUMBER (R_PPC_SECTOFF_LO, 34)
- RELOC_NUMBER (R_PPC_SECTOFF_HI, 35)
- RELOC_NUMBER (R_PPC_SECTOFF_HA, 36)
- RELOC_NUMBER (R_PPC_ADDR30, 37)
+ RELOC_NUMBER (R_PPC_NONE, 0)
+ RELOC_NUMBER (R_PPC_ADDR32, 1)
+ RELOC_NUMBER (R_PPC_ADDR24, 2)
+ RELOC_NUMBER (R_PPC_ADDR16, 3)
+ RELOC_NUMBER (R_PPC_ADDR16_LO, 4)
+ RELOC_NUMBER (R_PPC_ADDR16_HI, 5)
+ RELOC_NUMBER (R_PPC_ADDR16_HA, 6)
+ RELOC_NUMBER (R_PPC_ADDR14, 7)
+ RELOC_NUMBER (R_PPC_ADDR14_BRTAKEN, 8)
+ RELOC_NUMBER (R_PPC_ADDR14_BRNTAKEN, 9)
+ RELOC_NUMBER (R_PPC_REL24, 10)
+ RELOC_NUMBER (R_PPC_REL14, 11)
+ RELOC_NUMBER (R_PPC_REL14_BRTAKEN, 12)
+ RELOC_NUMBER (R_PPC_REL14_BRNTAKEN, 13)
+ RELOC_NUMBER (R_PPC_GOT16, 14)
+ RELOC_NUMBER (R_PPC_GOT16_LO, 15)
+ RELOC_NUMBER (R_PPC_GOT16_HI, 16)
+ RELOC_NUMBER (R_PPC_GOT16_HA, 17)
+ RELOC_NUMBER (R_PPC_PLTREL24, 18)
+ RELOC_NUMBER (R_PPC_COPY, 19)
+ RELOC_NUMBER (R_PPC_GLOB_DAT, 20)
+ RELOC_NUMBER (R_PPC_JMP_SLOT, 21)
+ RELOC_NUMBER (R_PPC_RELATIVE, 22)
+ RELOC_NUMBER (R_PPC_LOCAL24PC, 23)
+ RELOC_NUMBER (R_PPC_UADDR32, 24)
+ RELOC_NUMBER (R_PPC_UADDR16, 25)
+ RELOC_NUMBER (R_PPC_REL32, 26)
+ RELOC_NUMBER (R_PPC_PLT32, 27)
+ RELOC_NUMBER (R_PPC_PLTREL32, 28)
+ RELOC_NUMBER (R_PPC_PLT16_LO, 29)
+ RELOC_NUMBER (R_PPC_PLT16_HI, 30)
+ RELOC_NUMBER (R_PPC_PLT16_HA, 31)
+ RELOC_NUMBER (R_PPC_SDAREL16, 32)
+ RELOC_NUMBER (R_PPC_SECTOFF, 33)
+ RELOC_NUMBER (R_PPC_SECTOFF_LO, 34)
+ RELOC_NUMBER (R_PPC_SECTOFF_HI, 35)
+ RELOC_NUMBER (R_PPC_SECTOFF_HA, 36)
+ RELOC_NUMBER (R_PPC_ADDR30, 37)
+
+ /* Relocs added to support TLS. */
+ RELOC_NUMBER (R_PPC_TLS, 67)
+ RELOC_NUMBER (R_PPC_DTPMOD64, 68)
+ RELOC_NUMBER (R_PPC_TPREL16, 69)
+ RELOC_NUMBER (R_PPC_TPREL16_LO, 70)
+ RELOC_NUMBER (R_PPC_TPREL16_HI, 71)
+ RELOC_NUMBER (R_PPC_TPREL16_HA, 72)
+ RELOC_NUMBER (R_PPC_TPREL64, 73)
+ RELOC_NUMBER (R_PPC_DTPREL16, 74)
+ RELOC_NUMBER (R_PPC_DTPREL16_LO, 75)
+ RELOC_NUMBER (R_PPC_DTPREL16_HI, 76)
+ RELOC_NUMBER (R_PPC_DTPREL16_HA, 77)
+ RELOC_NUMBER (R_PPC_DTPREL64, 78)
+ RELOC_NUMBER (R_PPC_GOT_TLSGD16, 79)
+ RELOC_NUMBER (R_PPC_GOT_TLSGD16_LO, 80)
+ RELOC_NUMBER (R_PPC_GOT_TLSGD16_HI, 81)
+ RELOC_NUMBER (R_PPC_GOT_TLSGD16_HA, 82)
+ RELOC_NUMBER (R_PPC_GOT_TLSLD16, 83)
+ RELOC_NUMBER (R_PPC_GOT_TLSLD16_LO, 84)
+ RELOC_NUMBER (R_PPC_GOT_TLSLD16_HI, 85)
+ RELOC_NUMBER (R_PPC_GOT_TLSLD16_HA, 86)
+ RELOC_NUMBER (R_PPC_GOT_TPREL16, 87)
+ RELOC_NUMBER (R_PPC_GOT_TPREL16_LO, 88)
+ RELOC_NUMBER (R_PPC_GOT_TPREL16_HI, 89)
+ RELOC_NUMBER (R_PPC_GOT_TPREL16_HA, 90)
+ RELOC_NUMBER (R_PPC_GOT_DTPREL16, 91)
+ RELOC_NUMBER (R_PPC_GOT_DTPREL16_LO, 92)
+ RELOC_NUMBER (R_PPC_GOT_DTPREL16_HI, 93)
+ RELOC_NUMBER (R_PPC_GOT_DTPREL16_HA, 94)
/* The remaining relocs are from the Embedded ELF ABI, and are not
in the SVR4 ELF ABI. */
- RELOC_NUMBER (R_PPC_EMB_NADDR32, 101)
- RELOC_NUMBER (R_PPC_EMB_NADDR16, 102)
- RELOC_NUMBER (R_PPC_EMB_NADDR16_LO, 103)
- RELOC_NUMBER (R_PPC_EMB_NADDR16_HI, 104)
- RELOC_NUMBER (R_PPC_EMB_NADDR16_HA, 105)
- RELOC_NUMBER (R_PPC_EMB_SDAI16, 106)
- RELOC_NUMBER (R_PPC_EMB_SDA2I16, 107)
- RELOC_NUMBER (R_PPC_EMB_SDA2REL, 108)
- RELOC_NUMBER (R_PPC_EMB_SDA21, 109)
- RELOC_NUMBER (R_PPC_EMB_MRKREF, 110)
- RELOC_NUMBER (R_PPC_EMB_RELSEC16, 111)
- RELOC_NUMBER (R_PPC_EMB_RELST_LO, 112)
- RELOC_NUMBER (R_PPC_EMB_RELST_HI, 113)
- RELOC_NUMBER (R_PPC_EMB_RELST_HA, 114)
- RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115)
- RELOC_NUMBER (R_PPC_EMB_RELSDA, 116)
+ RELOC_NUMBER (R_PPC_EMB_NADDR32, 101)
+ RELOC_NUMBER (R_PPC_EMB_NADDR16, 102)
+ RELOC_NUMBER (R_PPC_EMB_NADDR16_LO, 103)
+ RELOC_NUMBER (R_PPC_EMB_NADDR16_HI, 104)
+ RELOC_NUMBER (R_PPC_EMB_NADDR16_HA, 105)
+ RELOC_NUMBER (R_PPC_EMB_SDAI16, 106)
+ RELOC_NUMBER (R_PPC_EMB_SDA2I16, 107)
+ RELOC_NUMBER (R_PPC_EMB_SDA2REL, 108)
+ RELOC_NUMBER (R_PPC_EMB_SDA21, 109)
+ RELOC_NUMBER (R_PPC_EMB_MRKREF, 110)
+ RELOC_NUMBER (R_PPC_EMB_RELSEC16, 111)
+ RELOC_NUMBER (R_PPC_EMB_RELST_LO, 112)
+ RELOC_NUMBER (R_PPC_EMB_RELST_HI, 113)
+ RELOC_NUMBER (R_PPC_EMB_RELST_HA, 114)
+ RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115)
+ RELOC_NUMBER (R_PPC_EMB_RELSDA, 116)
/* These are GNU extensions to enable C++ vtable garbage collection. */
- RELOC_NUMBER (R_PPC_GNU_VTINHERIT, 253)
- RELOC_NUMBER (R_PPC_GNU_VTENTRY, 254)
+ RELOC_NUMBER (R_PPC_GNU_VTINHERIT, 253)
+ RELOC_NUMBER (R_PPC_GNU_VTENTRY, 254)
/* This is a phony reloc to handle any old fashioned TOC16 references
that may still be in object files. */
- RELOC_NUMBER (R_PPC_TOC16, 255)
+ RELOC_NUMBER (R_PPC_TOC16, 255)
END_RELOC_NUMBERS (R_PPC_max)
Index: include/elf/ppc64.h
===================================================================
RCS file: /cvs/src/src/include/elf/ppc64.h,v
retrieving revision 1.1
diff -u -p -d -r1.1 ppc64.h
--- include/elf/ppc64.h 16 Jan 2003 04:08:47 -0000 1.1
+++ include/elf/ppc64.h 4 Feb 2003 14:02:29 -0000
@@ -24,82 +24,127 @@ Foundation, Inc., 59 Temple Place - Suit
/* Relocations. */
START_RELOC_NUMBERS (elf_ppc64_reloc_type)
- RELOC_NUMBER (R_PPC64_NONE, 0)
- RELOC_NUMBER (R_PPC64_ADDR32, 1)
- RELOC_NUMBER (R_PPC64_ADDR24, 2)
- RELOC_NUMBER (R_PPC64_ADDR16, 3)
- RELOC_NUMBER (R_PPC64_ADDR16_LO, 4)
- RELOC_NUMBER (R_PPC64_ADDR16_HI, 5)
- RELOC_NUMBER (R_PPC64_ADDR16_HA, 6)
- RELOC_NUMBER (R_PPC64_ADDR14, 7)
- RELOC_NUMBER (R_PPC64_ADDR14_BRTAKEN, 8)
- RELOC_NUMBER (R_PPC64_ADDR14_BRNTAKEN, 9)
- RELOC_NUMBER (R_PPC64_REL24, 10)
- RELOC_NUMBER (R_PPC64_REL14, 11)
- RELOC_NUMBER (R_PPC64_REL14_BRTAKEN, 12)
- RELOC_NUMBER (R_PPC64_REL14_BRNTAKEN, 13)
- RELOC_NUMBER (R_PPC64_GOT16, 14)
- RELOC_NUMBER (R_PPC64_GOT16_LO, 15)
- RELOC_NUMBER (R_PPC64_GOT16_HI, 16)
- RELOC_NUMBER (R_PPC64_GOT16_HA, 17)
+ RELOC_NUMBER (R_PPC64_NONE, 0)
+ RELOC_NUMBER (R_PPC64_ADDR32, 1)
+ RELOC_NUMBER (R_PPC64_ADDR24, 2)
+ RELOC_NUMBER (R_PPC64_ADDR16, 3)
+ RELOC_NUMBER (R_PPC64_ADDR16_LO, 4)
+ RELOC_NUMBER (R_PPC64_ADDR16_HI, 5)
+ RELOC_NUMBER (R_PPC64_ADDR16_HA, 6)
+ RELOC_NUMBER (R_PPC64_ADDR14, 7)
+ RELOC_NUMBER (R_PPC64_ADDR14_BRTAKEN, 8)
+ RELOC_NUMBER (R_PPC64_ADDR14_BRNTAKEN, 9)
+ RELOC_NUMBER (R_PPC64_REL24, 10)
+ RELOC_NUMBER (R_PPC64_REL14, 11)
+ RELOC_NUMBER (R_PPC64_REL14_BRTAKEN, 12)
+ RELOC_NUMBER (R_PPC64_REL14_BRNTAKEN, 13)
+ RELOC_NUMBER (R_PPC64_GOT16, 14)
+ RELOC_NUMBER (R_PPC64_GOT16_LO, 15)
+ RELOC_NUMBER (R_PPC64_GOT16_HI, 16)
+ RELOC_NUMBER (R_PPC64_GOT16_HA, 17)
/* 18 unused. 32-bit reloc is R_PPC_PLTREL24. */
- RELOC_NUMBER (R_PPC64_COPY, 19)
- RELOC_NUMBER (R_PPC64_GLOB_DAT, 20)
- RELOC_NUMBER (R_PPC64_JMP_SLOT, 21)
- RELOC_NUMBER (R_PPC64_RELATIVE, 22)
+ RELOC_NUMBER (R_PPC64_COPY, 19)
+ RELOC_NUMBER (R_PPC64_GLOB_DAT, 20)
+ RELOC_NUMBER (R_PPC64_JMP_SLOT, 21)
+ RELOC_NUMBER (R_PPC64_RELATIVE, 22)
/* 23 unused. 32-bit reloc is R_PPC_LOCAL24PC. */
- RELOC_NUMBER (R_PPC64_UADDR32, 24)
- RELOC_NUMBER (R_PPC64_UADDR16, 25)
- RELOC_NUMBER (R_PPC64_REL32, 26)
- RELOC_NUMBER (R_PPC64_PLT32, 27)
- RELOC_NUMBER (R_PPC64_PLTREL32, 28)
- RELOC_NUMBER (R_PPC64_PLT16_LO, 29)
- RELOC_NUMBER (R_PPC64_PLT16_HI, 30)
- RELOC_NUMBER (R_PPC64_PLT16_HA, 31)
+ RELOC_NUMBER (R_PPC64_UADDR32, 24)
+ RELOC_NUMBER (R_PPC64_UADDR16, 25)
+ RELOC_NUMBER (R_PPC64_REL32, 26)
+ RELOC_NUMBER (R_PPC64_PLT32, 27)
+ RELOC_NUMBER (R_PPC64_PLTREL32, 28)
+ RELOC_NUMBER (R_PPC64_PLT16_LO, 29)
+ RELOC_NUMBER (R_PPC64_PLT16_HI, 30)
+ RELOC_NUMBER (R_PPC64_PLT16_HA, 31)
/* 32 unused. 32-bit reloc is R_PPC_SDAREL16. */
- RELOC_NUMBER (R_PPC64_SECTOFF, 33)
- RELOC_NUMBER (R_PPC64_SECTOFF_LO, 34)
- RELOC_NUMBER (R_PPC64_SECTOFF_HI, 35)
- RELOC_NUMBER (R_PPC64_SECTOFF_HA, 36)
- RELOC_NUMBER (R_PPC64_REL30, 37)
- RELOC_NUMBER (R_PPC64_ADDR64, 38)
- RELOC_NUMBER (R_PPC64_ADDR16_HIGHER, 39)
- RELOC_NUMBER (R_PPC64_ADDR16_HIGHERA, 40)
- RELOC_NUMBER (R_PPC64_ADDR16_HIGHEST, 41)
- RELOC_NUMBER (R_PPC64_ADDR16_HIGHESTA, 42)
- RELOC_NUMBER (R_PPC64_UADDR64, 43)
- RELOC_NUMBER (R_PPC64_REL64, 44)
- RELOC_NUMBER (R_PPC64_PLT64, 45)
- RELOC_NUMBER (R_PPC64_PLTREL64, 46)
- RELOC_NUMBER (R_PPC64_TOC16, 47)
- RELOC_NUMBER (R_PPC64_TOC16_LO, 48)
- RELOC_NUMBER (R_PPC64_TOC16_HI, 49)
- RELOC_NUMBER (R_PPC64_TOC16_HA, 50)
- RELOC_NUMBER (R_PPC64_TOC, 51)
- RELOC_NUMBER (R_PPC64_PLTGOT16, 52)
- RELOC_NUMBER (R_PPC64_PLTGOT16_LO, 53)
- RELOC_NUMBER (R_PPC64_PLTGOT16_HI, 54)
- RELOC_NUMBER (R_PPC64_PLTGOT16_HA, 55)
+ RELOC_NUMBER (R_PPC64_SECTOFF, 33)
+ RELOC_NUMBER (R_PPC64_SECTOFF_LO, 34)
+ RELOC_NUMBER (R_PPC64_SECTOFF_HI, 35)
+ RELOC_NUMBER (R_PPC64_SECTOFF_HA, 36)
+ RELOC_NUMBER (R_PPC64_REL30, 37)
+ RELOC_NUMBER (R_PPC64_ADDR64, 38)
+ RELOC_NUMBER (R_PPC64_ADDR16_HIGHER, 39)
+ RELOC_NUMBER (R_PPC64_ADDR16_HIGHERA, 40)
+ RELOC_NUMBER (R_PPC64_ADDR16_HIGHEST, 41)
+ RELOC_NUMBER (R_PPC64_ADDR16_HIGHESTA, 42)
+ RELOC_NUMBER (R_PPC64_UADDR64, 43)
+ RELOC_NUMBER (R_PPC64_REL64, 44)
+ RELOC_NUMBER (R_PPC64_PLT64, 45)
+ RELOC_NUMBER (R_PPC64_PLTREL64, 46)
+ RELOC_NUMBER (R_PPC64_TOC16, 47)
+ RELOC_NUMBER (R_PPC64_TOC16_LO, 48)
+ RELOC_NUMBER (R_PPC64_TOC16_HI, 49)
+ RELOC_NUMBER (R_PPC64_TOC16_HA, 50)
+ RELOC_NUMBER (R_PPC64_TOC, 51)
+ RELOC_NUMBER (R_PPC64_PLTGOT16, 52)
+ RELOC_NUMBER (R_PPC64_PLTGOT16_LO, 53)
+ RELOC_NUMBER (R_PPC64_PLTGOT16_HI, 54)
+ RELOC_NUMBER (R_PPC64_PLTGOT16_HA, 55)
-/* The following relocs were added in the 64-bit PowerPC ELF ABI
- revision 1.2. */
- RELOC_NUMBER (R_PPC64_ADDR16_DS, 56)
- RELOC_NUMBER (R_PPC64_ADDR16_LO_DS, 57)
- RELOC_NUMBER (R_PPC64_GOT16_DS, 58)
- RELOC_NUMBER (R_PPC64_GOT16_LO_DS, 59)
- RELOC_NUMBER (R_PPC64_PLT16_LO_DS, 60)
- RELOC_NUMBER (R_PPC64_SECTOFF_DS, 61)
- RELOC_NUMBER (R_PPC64_SECTOFF_LO_DS, 62)
- RELOC_NUMBER (R_PPC64_TOC16_DS, 63)
- RELOC_NUMBER (R_PPC64_TOC16_LO_DS, 64)
- RELOC_NUMBER (R_PPC64_PLTGOT16_DS, 65)
- RELOC_NUMBER (R_PPC64_PLTGOT16_LO_DS, 66)
+ /* The following relocs were added in the 64-bit PowerPC ELF ABI
+ revision 1.2. */
+ RELOC_NUMBER (R_PPC64_ADDR16_DS, 56)
+ RELOC_NUMBER (R_PPC64_ADDR16_LO_DS, 57)
+ RELOC_NUMBER (R_PPC64_GOT16_DS, 58)
+ RELOC_NUMBER (R_PPC64_GOT16_LO_DS, 59)
+ RELOC_NUMBER (R_PPC64_PLT16_LO_DS, 60)
+ RELOC_NUMBER (R_PPC64_SECTOFF_DS, 61)
+ RELOC_NUMBER (R_PPC64_SECTOFF_LO_DS, 62)
+ RELOC_NUMBER (R_PPC64_TOC16_DS, 63)
+ RELOC_NUMBER (R_PPC64_TOC16_LO_DS, 64)
+ RELOC_NUMBER (R_PPC64_PLTGOT16_DS, 65)
+ RELOC_NUMBER (R_PPC64_PLTGOT16_LO_DS, 66)
+
+ /* Relocs added to support TLS. PowerPC64 ELF ABI revision 1.5. */
+ RELOC_NUMBER (R_PPC64_TLS, 67)
+ RELOC_NUMBER (R_PPC64_DTPMOD64, 68)
+ RELOC_NUMBER (R_PPC64_TPREL16, 69)
+ RELOC_NUMBER (R_PPC64_TPREL16_LO, 70)
+ RELOC_NUMBER (R_PPC64_TPREL16_HI, 71)
+ RELOC_NUMBER (R_PPC64_TPREL16_HA, 72)
+ RELOC_NUMBER (R_PPC64_TPREL64, 73)
+ RELOC_NUMBER (R_PPC64_DTPREL16, 74)
+ RELOC_NUMBER (R_PPC64_DTPREL16_LO, 75)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HI, 76)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HA, 77)
+ RELOC_NUMBER (R_PPC64_DTPREL64, 78)
+ RELOC_NUMBER (R_PPC64_GOT_TLSGD16, 79)
+ RELOC_NUMBER (R_PPC64_GOT_TLSGD16_LO, 80)
+ RELOC_NUMBER (R_PPC64_GOT_TLSGD16_HI, 81)
+ RELOC_NUMBER (R_PPC64_GOT_TLSGD16_HA, 82)
+ RELOC_NUMBER (R_PPC64_GOT_TLSLD16, 83)
+ RELOC_NUMBER (R_PPC64_GOT_TLSLD16_LO, 84)
+ RELOC_NUMBER (R_PPC64_GOT_TLSLD16_HI, 85)
+ RELOC_NUMBER (R_PPC64_GOT_TLSLD16_HA, 86)
+ RELOC_NUMBER (R_PPC64_GOT_TPREL16_DS, 87)
+ RELOC_NUMBER (R_PPC64_GOT_TPREL16_LO_DS, 88)
+ RELOC_NUMBER (R_PPC64_GOT_TPREL16_HI, 89)
+ RELOC_NUMBER (R_PPC64_GOT_TPREL16_HA, 90)
+ RELOC_NUMBER (R_PPC64_GOT_DTPREL16_DS, 91)
+ RELOC_NUMBER (R_PPC64_GOT_DTPREL16_LO_DS, 92)
+ RELOC_NUMBER (R_PPC64_GOT_DTPREL16_HI, 93)
+ RELOC_NUMBER (R_PPC64_GOT_DTPREL16_HA, 94)
+ RELOC_NUMBER (R_PPC64_TPREL16_DS, 95)
+ RELOC_NUMBER (R_PPC64_TPREL16_LO_DS, 96)
+ RELOC_NUMBER (R_PPC64_TPREL16_HIGHER, 97)
+ RELOC_NUMBER (R_PPC64_TPREL16_HIGHERA, 98)
+ RELOC_NUMBER (R_PPC64_TPREL16_HIGHEST, 99)
+ RELOC_NUMBER (R_PPC64_TPREL16_HIGHESTA, 100)
+ RELOC_NUMBER (R_PPC64_DTPREL16_DS, 101)
+ RELOC_NUMBER (R_PPC64_DTPREL16_LO_DS, 102)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HIGHER, 103)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HIGHERA, 104)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HIGHEST, 105)
+ RELOC_NUMBER (R_PPC64_DTPREL16_HIGHESTA, 106)
/* These are GNU extensions to enable C++ vtable garbage collection. */
- RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253)
- RELOC_NUMBER (R_PPC64_GNU_VTENTRY, 254)
+ RELOC_NUMBER (R_PPC64_GNU_VTINHERIT, 253)
+ RELOC_NUMBER (R_PPC64_GNU_VTENTRY, 254)
END_RELOC_NUMBERS (R_PPC64_max)
+
+#define IS_TLS_RELOC(R) \
+ ((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA)
/* Specify the start of the .glink section. */
#define DT_PPC64_GLINK DT_LOPROC
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.79
diff -u -p -d -r1.79 elf64-ppc.c
--- bfd/elf64-ppc.c 23 Jan 2003 11:51:32 -0000 1.79
+++ bfd/elf64-ppc.c 4 Feb 2003 14:02:14 -0000
@@ -71,7 +71,11 @@ static bfd_boolean ppc64_elf_new_section
#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE
/* TOC base pointers offset from start of TOC. */
-#define TOC_BASE_OFF (0x8000)
+#define TOC_BASE_OFF 0x8000
+
+/* Offset of tp and dtp pointers from start of TLS block. */
+#define TP_OFFSET 0x7000
+#define DTP_OFFSET 0x8000
/* .plt call stub instructions. */
#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */
@@ -134,8 +138,8 @@ static reloc_howto_type ppc64_elf_howto_
/* This reloc does nothing. */
HOWTO (R_PPC64_NONE, /* type */
0, /* rightshift */
- 0, /* size (0 = byte, 1 = short, 2 = long) */
- 8, /* bitsize */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
@@ -1152,6 +1156,616 @@ static reloc_howto_type ppc64_elf_howto_
0xfffc, /* dst_mask */
FALSE), /* pcrel_offset */
+ /* Marker reloc for TLS. */
+ HOWTO (R_PPC64_TLS,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC64_TLS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes the load module index of the load module that contains the
+ definition of its TLS sym. */
+ HOWTO (R_PPC64_DTPMOD64,
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPMOD64", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ONES (64), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a dtv-relative displacement, the difference between the value
+ of sym+add and the base address of the thread-local storage block that
+ contains the definition of sym, minus 0x8000. */
+ HOWTO (R_PPC64_DTPREL64,
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL64", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ONES (64), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 16 bit dtprel reloc. */
+ HOWTO (R_PPC64_DTPREL16,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16, but no overflow. */
+ HOWTO (R_PPC64_DTPREL16_LO,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_LO, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_HI, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HIGHER,
+ 32, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HIGHER", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_HIGHER, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HIGHERA,
+ 32, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HIGHERA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_HIGHER, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HIGHEST,
+ 48, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HIGHEST", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_DTPREL16_HIGHESTA,
+ 48, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_HIGHESTA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16, but for insns with a DS field. */
+ HOWTO (R_PPC64_DTPREL16_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like DTPREL16_DS, but no overflow. */
+ HOWTO (R_PPC64_DTPREL16_LO_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_DTPREL16_LO_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a tp-relative displacement, the difference between the value of
+ sym+add and the value of the thread pointer (r13). */
+ HOWTO (R_PPC64_TPREL64,
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL64", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ ONES (64), /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 16 bit tprel reloc. */
+ HOWTO (R_PPC64_TPREL16,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16, but no overflow. */
+ HOWTO (R_PPC64_TPREL16_LO,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_LO, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_HI, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HIGHER,
+ 32, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HIGHER", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_HIGHER, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HIGHERA,
+ 32, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HIGHERA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_HIGHER, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HIGHEST,
+ 48, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HIGHEST", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_HIGHEST, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_TPREL16_HIGHESTA,
+ 48, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_HIGHESTA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16, but for insns with a DS field. */
+ HOWTO (R_PPC64_TPREL16_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like TPREL16_DS, but no overflow. */
+ HOWTO (R_PPC64_TPREL16_LO_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_TPREL16_LO_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
+ with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset
+ to the first entry relative to the TOC base (r2). */
+ HOWTO (R_PPC64_GOT_TLSGD16,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSGD16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSGD16, but no overflow. */
+ HOWTO (R_PPC64_GOT_TLSGD16_LO,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSGD16_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_GOT_TLSGD16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSGD16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_GOT_TLSGD16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSGD16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Allocates two contiguous entries in the GOT to hold a tls_index structure,
+ with values (sym+add)@dtpmod and zero, and computes the offset to the
+ first entry relative to the TOC base (r2). */
+ HOWTO (R_PPC64_GOT_TLSLD16,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSLD16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSLD16, but no overflow. */
+ HOWTO (R_PPC64_GOT_TLSLD16_LO,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSLD16_LO", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_GOT_TLSLD16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSLD16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_GOT_TLSLD16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TLSLD16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes
+ the offset to the entry relative to the TOC base (r2). */
+ HOWTO (R_PPC64_GOT_DTPREL16_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_DTPREL16_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_DTPREL16_DS, but no overflow. */
+ HOWTO (R_PPC64_GOT_DTPREL16_LO_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_DTPREL16_LO_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_GOT_DTPREL16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_DTPREL16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_GOT_DTPREL16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_DTPREL16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the
+ offset to the entry relative to the TOC base (r2). */
+ HOWTO (R_PPC64_GOT_TPREL16_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TPREL16_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TPREL16_DS, but no overflow. */
+ HOWTO (R_PPC64_GOT_TPREL16_LO_DS,
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TPREL16_LO_DS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */
+ HOWTO (R_PPC64_GOT_TPREL16_HI,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TPREL16_HI", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */
+ HOWTO (R_PPC64_GOT_TPREL16_HA,
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc64_elf_unhandled_reloc, /* special_function */
+ "R_PPC64_GOT_TPREL16_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_PPC64_GNU_VTINHERIT, /* type */
0, /* rightshift */
@@ -1208,7 +1822,7 @@ ppc64_elf_reloc_type_lookup (abfd, code)
bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type code;
{
- enum elf_ppc64_reloc_type ppc_reloc = R_PPC64_NONE;
+ enum elf_ppc64_reloc_type r = R_PPC64_NONE;
if (!ppc64_elf_howto_table[R_PPC64_ADDR32])
/* Initialize howto table if needed. */
@@ -1219,131 +1833,211 @@ ppc64_elf_reloc_type_lookup (abfd, code)
default:
return (reloc_howto_type *) NULL;
- case BFD_RELOC_NONE: ppc_reloc = R_PPC64_NONE;
+ case BFD_RELOC_NONE: r = R_PPC64_NONE;
break;
- case BFD_RELOC_32: ppc_reloc = R_PPC64_ADDR32;
+ case BFD_RELOC_32: r = R_PPC64_ADDR32;
break;
- case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC64_ADDR24;
+ case BFD_RELOC_PPC_BA26: r = R_PPC64_ADDR24;
break;
- case BFD_RELOC_16: ppc_reloc = R_PPC64_ADDR16;
+ case BFD_RELOC_16: r = R_PPC64_ADDR16;
break;
- case BFD_RELOC_LO16: ppc_reloc = R_PPC64_ADDR16_LO;
+ case BFD_RELOC_LO16: r = R_PPC64_ADDR16_LO;
break;
- case BFD_RELOC_HI16: ppc_reloc = R_PPC64_ADDR16_HI;
+ case BFD_RELOC_HI16: r = R_PPC64_ADDR16_HI;
break;
- case BFD_RELOC_HI16_S: ppc_reloc = R_PPC64_ADDR16_HA;
+ case BFD_RELOC_HI16_S: r = R_PPC64_ADDR16_HA;
break;
- case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC64_ADDR14;
+ case BFD_RELOC_PPC_BA16: r = R_PPC64_ADDR14;
break;
- case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC64_ADDR14_BRTAKEN;
+ case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC64_ADDR14_BRTAKEN;
break;
- case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC64_ADDR14_BRNTAKEN;
+ case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC64_ADDR14_BRNTAKEN;
break;
- case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC64_REL24;
+ case BFD_RELOC_PPC_B26: r = R_PPC64_REL24;
break;
- case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC64_REL14;
+ case BFD_RELOC_PPC_B16: r = R_PPC64_REL14;
break;
- case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC64_REL14_BRTAKEN;
+ case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN;
break;
- case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC64_REL14_BRNTAKEN;
+ case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC64_REL14_BRNTAKEN;
break;
- case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC64_GOT16;
+ case BFD_RELOC_16_GOTOFF: r = R_PPC64_GOT16;
break;
- case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC64_GOT16_LO;
+ case BFD_RELOC_LO16_GOTOFF: r = R_PPC64_GOT16_LO;
break;
- case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC64_GOT16_HI;
+ case BFD_RELOC_HI16_GOTOFF: r = R_PPC64_GOT16_HI;
break;
- case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC64_GOT16_HA;
+ case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC64_GOT16_HA;
break;
- case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC64_COPY;
+ case BFD_RELOC_PPC_COPY: r = R_PPC64_COPY;
break;
- case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC64_GLOB_DAT;
+ case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC64_GLOB_DAT;
break;
- case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC64_REL32;
+ case BFD_RELOC_32_PCREL: r = R_PPC64_REL32;
break;
- case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC64_PLT32;
+ case BFD_RELOC_32_PLTOFF: r = R_PPC64_PLT32;
break;
- case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL32;
+ case BFD_RELOC_32_PLT_PCREL: r = R_PPC64_PLTREL32;
break;
- case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC64_PLT16_LO;
+ case BFD_RELOC_LO16_PLTOFF: r = R_PPC64_PLT16_LO;
break;
- case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC64_PLT16_HI;
+ case BFD_RELOC_HI16_PLTOFF: r = R_PPC64_PLT16_HI;
break;
- case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC64_PLT16_HA;
+ case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC64_PLT16_HA;
break;
- case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC64_SECTOFF;
+ case BFD_RELOC_16_BASEREL: r = R_PPC64_SECTOFF;
break;
- case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_LO;
+ case BFD_RELOC_LO16_BASEREL: r = R_PPC64_SECTOFF_LO;
break;
- case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HI;
+ case BFD_RELOC_HI16_BASEREL: r = R_PPC64_SECTOFF_HI;
break;
- case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HA;
+ case BFD_RELOC_HI16_S_BASEREL: r = R_PPC64_SECTOFF_HA;
break;
- case BFD_RELOC_CTOR: ppc_reloc = R_PPC64_ADDR64;
+ case BFD_RELOC_CTOR: r = R_PPC64_ADDR64;
break;
- case BFD_RELOC_64: ppc_reloc = R_PPC64_ADDR64;
+ case BFD_RELOC_64: r = R_PPC64_ADDR64;
break;
- case BFD_RELOC_PPC64_HIGHER: ppc_reloc = R_PPC64_ADDR16_HIGHER;
+ case BFD_RELOC_PPC64_HIGHER: r = R_PPC64_ADDR16_HIGHER;
break;
- case BFD_RELOC_PPC64_HIGHER_S: ppc_reloc = R_PPC64_ADDR16_HIGHERA;
+ case BFD_RELOC_PPC64_HIGHER_S: r = R_PPC64_ADDR16_HIGHERA;
break;
- case BFD_RELOC_PPC64_HIGHEST: ppc_reloc = R_PPC64_ADDR16_HIGHEST;
+ case BFD_RELOC_PPC64_HIGHEST: r = R_PPC64_ADDR16_HIGHEST;
break;
- case BFD_RELOC_PPC64_HIGHEST_S: ppc_reloc = R_PPC64_ADDR16_HIGHESTA;
+ case BFD_RELOC_PPC64_HIGHEST_S: r = R_PPC64_ADDR16_HIGHESTA;
break;
- case BFD_RELOC_64_PCREL: ppc_reloc = R_PPC64_REL64;
+ case BFD_RELOC_64_PCREL: r = R_PPC64_REL64;
break;
- case BFD_RELOC_64_PLTOFF: ppc_reloc = R_PPC64_PLT64;
+ case BFD_RELOC_64_PLTOFF: r = R_PPC64_PLT64;
break;
- case BFD_RELOC_64_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL64;
+ case BFD_RELOC_64_PLT_PCREL: r = R_PPC64_PLTREL64;
break;
- case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC64_TOC16;
+ case BFD_RELOC_PPC_TOC16: r = R_PPC64_TOC16;
break;
- case BFD_RELOC_PPC64_TOC16_LO: ppc_reloc = R_PPC64_TOC16_LO;
+ case BFD_RELOC_PPC64_TOC16_LO: r = R_PPC64_TOC16_LO;
break;
- case BFD_RELOC_PPC64_TOC16_HI: ppc_reloc = R_PPC64_TOC16_HI;
+ case BFD_RELOC_PPC64_TOC16_HI: r = R_PPC64_TOC16_HI;
break;
- case BFD_RELOC_PPC64_TOC16_HA: ppc_reloc = R_PPC64_TOC16_HA;
+ case BFD_RELOC_PPC64_TOC16_HA: r = R_PPC64_TOC16_HA;
break;
- case BFD_RELOC_PPC64_TOC: ppc_reloc = R_PPC64_TOC;
+ case BFD_RELOC_PPC64_TOC: r = R_PPC64_TOC;
break;
- case BFD_RELOC_PPC64_PLTGOT16: ppc_reloc = R_PPC64_PLTGOT16;
+ case BFD_RELOC_PPC64_PLTGOT16: r = R_PPC64_PLTGOT16;
break;
- case BFD_RELOC_PPC64_PLTGOT16_LO: ppc_reloc = R_PPC64_PLTGOT16_LO;
+ case BFD_RELOC_PPC64_PLTGOT16_LO: r = R_PPC64_PLTGOT16_LO;
break;
- case BFD_RELOC_PPC64_PLTGOT16_HI: ppc_reloc = R_PPC64_PLTGOT16_HI;
+ case BFD_RELOC_PPC64_PLTGOT16_HI: r = R_PPC64_PLTGOT16_HI;
break;
- case BFD_RELOC_PPC64_PLTGOT16_HA: ppc_reloc = R_PPC64_PLTGOT16_HA;
+ case BFD_RELOC_PPC64_PLTGOT16_HA: r = R_PPC64_PLTGOT16_HA;
break;
- case BFD_RELOC_PPC64_ADDR16_DS: ppc_reloc = R_PPC64_ADDR16_DS;
+ case BFD_RELOC_PPC64_ADDR16_DS: r = R_PPC64_ADDR16_DS;
break;
- case BFD_RELOC_PPC64_ADDR16_LO_DS: ppc_reloc = R_PPC64_ADDR16_LO_DS;
+ case BFD_RELOC_PPC64_ADDR16_LO_DS: r = R_PPC64_ADDR16_LO_DS;
break;
- case BFD_RELOC_PPC64_GOT16_DS: ppc_reloc = R_PPC64_GOT16_DS;
+ case BFD_RELOC_PPC64_GOT16_DS: r = R_PPC64_GOT16_DS;
break;
- case BFD_RELOC_PPC64_GOT16_LO_DS: ppc_reloc = R_PPC64_GOT16_LO_DS;
+ case BFD_RELOC_PPC64_GOT16_LO_DS: r = R_PPC64_GOT16_LO_DS;
break;
- case BFD_RELOC_PPC64_PLT16_LO_DS: ppc_reloc = R_PPC64_PLT16_LO_DS;
+ case BFD_RELOC_PPC64_PLT16_LO_DS: r = R_PPC64_PLT16_LO_DS;
break;
- case BFD_RELOC_PPC64_SECTOFF_DS: ppc_reloc = R_PPC64_SECTOFF_DS;
+ case BFD_RELOC_PPC64_SECTOFF_DS: r = R_PPC64_SECTOFF_DS;
break;
- case BFD_RELOC_PPC64_SECTOFF_LO_DS: ppc_reloc = R_PPC64_SECTOFF_LO_DS;
+ case BFD_RELOC_PPC64_SECTOFF_LO_DS: r = R_PPC64_SECTOFF_LO_DS;
break;
- case BFD_RELOC_PPC64_TOC16_DS: ppc_reloc = R_PPC64_TOC16_DS;
+ case BFD_RELOC_PPC64_TOC16_DS: r = R_PPC64_TOC16_DS;
break;
- case BFD_RELOC_PPC64_TOC16_LO_DS: ppc_reloc = R_PPC64_TOC16_LO_DS;
+ case BFD_RELOC_PPC64_TOC16_LO_DS: r = R_PPC64_TOC16_LO_DS;
break;
- case BFD_RELOC_PPC64_PLTGOT16_DS: ppc_reloc = R_PPC64_PLTGOT16_DS;
+ case BFD_RELOC_PPC64_PLTGOT16_DS: r = R_PPC64_PLTGOT16_DS;
break;
- case BFD_RELOC_PPC64_PLTGOT16_LO_DS: ppc_reloc = R_PPC64_PLTGOT16_LO_DS;
+ case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS;
break;
- case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC64_GNU_VTINHERIT;
+ case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS;
break;
- case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC64_GNU_VTENTRY;
+ case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64;
+ break;
+ case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16;
+ break;
+ case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC64_TPREL16_LO;
+ break;
+ case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC64_TPREL16_HI;
+ break;
+ case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA;
+ break;
+ case BFD_RELOC_PPC_TPREL: r = R_PPC64_TPREL64;
+ break;
+ case BFD_RELOC_PPC_DTPREL16: r = R_PPC64_DTPREL16;
+ break;
+ case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC64_DTPREL16_LO;
+ break;
+ case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC64_DTPREL16_HI;
+ break;
+ case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA;
+ break;
+ case BFD_RELOC_PPC_DTPREL: r = R_PPC64_DTPREL64;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC64_GOT_TLSGD16;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC64_GOT_TLSGD16_LO;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC64_GOT_TLSGD16_HI;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC64_GOT_TLSGD16_HA;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC64_GOT_TLSLD16;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC64_GOT_TLSLD16_LO;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC64_GOT_TLSLD16_HI;
+ break;
+ case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC64_GOT_TLSLD16_HA;
+ break;
+ case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC64_GOT_TPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC64_GOT_TPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC64_GOT_TPREL16_HI;
+ break;
+ case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC64_GOT_TPREL16_HA;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC64_GOT_DTPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC64_GOT_DTPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC64_GOT_DTPREL16_HI;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC64_GOT_DTPREL16_HA;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_DS: r = R_PPC64_TPREL16_DS;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_LO_DS: r = R_PPC64_TPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_HIGHER: r = R_PPC64_TPREL16_HIGHER;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_HIGHERA: r = R_PPC64_TPREL16_HIGHERA;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_HIGHEST: r = R_PPC64_TPREL16_HIGHEST;
+ break;
+ case BFD_RELOC_PPC64_TPREL16_HIGHESTA: r = R_PPC64_TPREL16_HIGHESTA;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_DS: r = R_PPC64_DTPREL16_DS;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_LO_DS: r = R_PPC64_DTPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_HIGHER: r = R_PPC64_DTPREL16_HIGHER;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_HIGHERA: r = R_PPC64_DTPREL16_HIGHERA;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_HIGHEST: r = R_PPC64_DTPREL16_HIGHEST;
+ break;
+ case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA;
+ break;
+ case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT;
+ break;
+ case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY;
break;
}
- return ppc64_elf_howto_table[(int) ppc_reloc];
+ return ppc64_elf_howto_table[(int) r];
};
/* Set the howto pointer for a PowerPC ELF reloc. */
@@ -1681,15 +2375,23 @@ ppc64_elf_merge_private_bfd_data (ibfd,
struct _ppc64_elf_section_data
{
struct bfd_elf_section_data elf;
+
+ /* An array with one entry for each opd function descriptor. */
union
{
+ /* Points to the function code section for local opd entries. */
asection **func_sec;
+ /* After editing .opd, adjust references to opd local syms. */
long *adjust;
} opd;
+
+ /* An array for toc sections, indexed by offset/8.
+ Specifies the relocation symbol index used at a given toc offset. */
+ unsigned *t_symndx;
};
#define ppc64_elf_section_data(sec) \
- ((struct _ppc64_elf_section_data *) (sec)->used_by_bfd)
+ ((struct _ppc64_elf_section_data *) elf_section_data (sec))
static bfd_boolean
ppc64_elf_new_section_hook (abfd, sec)
@@ -1747,7 +2449,7 @@ ppc64_elf_new_section_hook (abfd, sec)
.
. .foo_stub:
. addis 12,2,Lfoo@toc@ha # in practice, the call stub
- . addi 12,12,Lfoo@toc@l # is slightly optimised, but
+ . addi 12,12,Lfoo@toc@l # is slightly optimized, but
. std 2,40(1) # this is the general idea
. ld 11,0(12)
. ld 2,8(12)
@@ -1795,10 +2497,41 @@ struct ppc_dyn_relocs
bfd_size_type pc_count;
};
+/* Track GOT entries needed for a given symbol. We might need more
+ than one got entry per symbol. */
+struct got_entry
+{
+ struct got_entry *next;
+
+ bfd_vma addend;
+
+ union
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } got;
+
+ char tls_type;
+};
+
+/* The same for PLT. */
+struct plt_entry
+{
+ struct plt_entry *next;
+
+ bfd_vma addend;
+
+ union
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } plt;
+};
+
/* Of those relocs that might be copied as dynamic relocs, this macro
- selects between relative and absolute types. */
+ selects those that must be copied when linking a shared library. */
-#define IS_ABSOLUTE_RELOC(RTYPE) \
+#define MUST_BE_DYN_RELOC(RTYPE) \
((RTYPE) != R_PPC64_REL32 \
&& (RTYPE) != R_PPC64_REL64 \
&& (RTYPE) != R_PPC64_REL30)
@@ -1860,6 +2593,9 @@ struct ppc_stub_hash_entry {
/* The symbol table entry, if any, that this was derived from. */
struct ppc_link_hash_entry *h;
+ /* And the reloc addend that this was derived from. */
+ bfd_vma addend;
+
/* Where this stub is being called from, or, in the case of combined
stub sections, the first input section in the group. */
asection *id_sec;
@@ -1895,6 +2631,16 @@ struct ppc_link_hash_entry
unsigned int is_func:1;
unsigned int is_func_descriptor:1;
unsigned int is_entry:1;
+
+ /* Contexts in which symbol is used in the GOT (or TOC).
+ Linker optimization will result in various transformations. */
+#define TLS_TLS 1 /* Any TLS reloc. */
+#define TLS_GD_LD 2 /* GD or LD reloc requiring 2 got slots. */
+#define TLS_LD 4 /* LD reloc. */
+#define TLS_TPREL 8 /* TPREL reloc, => IE. */
+#define TLS_DTPREL 16 /* DTPREL reloc, => LD. */
+#define TLS_EXPLICIT 32 /* Marks TOC section relocs. */
+ char tls_type;
};
/* ppc64 ELF linker hash table. */
@@ -1941,6 +2687,18 @@ struct ppc_link_hash_table
asection *sbrlt;
asection *srelbrlt;
+ /* Short-cut to first output tls section. */
+ asection *tls_sec;
+
+ /* Shortcut to .__tls_get_addr. */
+ struct elf_link_hash_entry *tls_get_addr;
+
+ /* TLS local dynamic got entry handling. */
+ union {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } tlsld_got;
+
/* Set on error. */
unsigned int stub_error;
@@ -1985,6 +2743,10 @@ static bfd_boolean ppc64_elf_create_dyna
static void ppc64_elf_copy_indirect_symbol
PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *,
struct elf_link_hash_entry *));
+static bfd_boolean update_local_sym_info
+ PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned long, bfd_vma, int));
+static bfd_boolean update_plt_info
+ PARAMS ((bfd *, struct ppc_link_hash_entry *, bfd_vma));
static bfd_boolean ppc64_elf_check_relocs
PARAMS ((bfd *, struct bfd_link_info *, asection *,
const Elf_Internal_Rela *));
@@ -2002,6 +2764,11 @@ static bfd_boolean ppc64_elf_adjust_dyna
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
static void ppc64_elf_hide_symbol
PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
+static bfd_boolean get_sym_h
+ PARAMS ((struct elf_link_hash_entry **, Elf_Internal_Sym **, asection **,
+ char **, Elf_Internal_Sym **, unsigned long, bfd *));
+static bfd_boolean get_tls_type
+ PARAMS ((char **, Elf_Internal_Sym **, const Elf_Internal_Rela *, bfd *));
static bfd_boolean allocate_dynrelocs
PARAMS ((struct elf_link_hash_entry *, PTR));
static bfd_boolean readonly_dynrelocs
@@ -2010,7 +2777,7 @@ static enum elf_reloc_type_class ppc64_e
PARAMS ((const Elf_Internal_Rela *));
static bfd_boolean ppc64_elf_size_dynamic_sections
PARAMS ((bfd *, struct bfd_link_info *));
-static INLINE enum ppc_stub_type ppc_type_of_stub
+static enum ppc_stub_type ppc_type_of_stub
PARAMS ((asection *, const Elf_Internal_Rela *,
struct ppc_link_hash_entry **, bfd_vma));
static bfd_byte *build_plt_stub
@@ -2142,6 +2909,7 @@ link_hash_newfunc (entry, table, string)
eh->is_func = 0;
eh->is_func_descriptor = 0;
eh->is_entry = 0;
+ eh->tls_type = 0;
}
return entry;
@@ -2188,11 +2956,15 @@ ppc64_elf_link_hash_table_create (abfd)
htab->sfpr = NULL;
htab->sbrlt = NULL;
htab->srelbrlt = NULL;
+ htab->tls_sec = NULL;
+ htab->tlsld_got.refcount = 0;
htab->stub_error = 0;
htab->has_14bit_branch = 0;
htab->have_undefweak = 0;
htab->stub_iteration = 0;
htab->sym_sec.abfd = NULL;
+ htab->elf.init_refcount.glist = NULL;
+ htab->elf.init_offset.glist = NULL;
return &htab->elf.root;
}
@@ -2471,7 +3243,7 @@ ppc64_elf_create_dynamic_sections (dynob
static void
ppc64_elf_copy_indirect_symbol (bed, dir, ind)
- struct elf_backend_data *bed;
+ struct elf_backend_data *bed ATTRIBUTE_UNUSED;
struct elf_link_hash_entry *dir, *ind;
{
struct ppc_link_hash_entry *edir, *eind;
@@ -2479,6 +3251,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir
edir = (struct ppc_link_hash_entry *) dir;
eind = (struct ppc_link_hash_entry *) ind;
+ /* Copy over any dynamic relocs we may have on the indirect sym. */
if (eind->dyn_relocs != NULL)
{
if (edir->dyn_relocs != NULL)
@@ -2486,7 +3259,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir
struct ppc_dyn_relocs **pp;
struct ppc_dyn_relocs *p;
- if (ind->root.type == bfd_link_hash_indirect)
+ if (eind->elf.root.type == bfd_link_hash_indirect)
abort ();
/* Add reloc counts against the weak sym to the strong sym
@@ -2513,11 +3286,90 @@ ppc64_elf_copy_indirect_symbol (bed, dir
eind->dyn_relocs = NULL;
}
+ /* Do the same for got entries. */
+ if (eind->elf.got.glist != NULL)
+ {
+ if (edir->elf.got.glist != NULL)
+ {
+ struct got_entry **entp;
+ struct got_entry *ent;
+
+ for (entp = &eind->elf.got.glist; (ent = *entp) != NULL; )
+ {
+ struct got_entry *dent;
+
+ for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next)
+ if (dent->addend == ent->addend
+ && dent->tls_type == ent->tls_type)
+ {
+ dent->got.refcount += ent->got.refcount;
+ *entp = ent->next;
+ break;
+ }
+ if (dent == NULL)
+ entp = &ent->next;
+ }
+ *entp = edir->elf.got.glist;
+ }
+
+ edir->elf.got.glist = eind->elf.got.glist;
+ eind->elf.got.glist = NULL;
+ }
+
+ /* And plt entries. */
+ if (eind->elf.plt.plist != NULL)
+ {
+ if (edir->elf.plt.plist != NULL)
+ {
+ struct plt_entry **entp;
+ struct plt_entry *ent;
+
+ for (entp = &eind->elf.plt.plist; (ent = *entp) != NULL; )
+ {
+ struct plt_entry *dent;
+
+ for (dent = edir->elf.plt.plist; dent != NULL; dent = dent->next)
+ if (dent->addend == ent->addend)
+ {
+ dent->plt.refcount += ent->plt.refcount;
+ *entp = ent->next;
+ break;
+ }
+ if (dent == NULL)
+ entp = &ent->next;
+ }
+ *entp = edir->elf.plt.plist;
+ }
+
+ edir->elf.plt.plist = eind->elf.plt.plist;
+ eind->elf.plt.plist = NULL;
+ }
+
edir->is_func |= eind->is_func;
edir->is_func_descriptor |= eind->is_func_descriptor;
edir->is_entry |= eind->is_entry;
- _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+ /* Copy down any references that we may have already seen to the
+ symbol which just became indirect. */
+ edir->elf.elf_link_hash_flags |=
+ (eind->elf.elf_link_hash_flags
+ & (ELF_LINK_HASH_REF_DYNAMIC
+ | ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+ | ELF_LINK_NON_GOT_REF));
+
+ if (eind->elf.root.type != bfd_link_hash_indirect)
+ return;
+
+ if (edir->elf.dynindx == -1)
+ {
+ edir->elf.dynindx = eind->elf.dynindx;
+ edir->elf.dynstr_index = eind->elf.dynstr_index;
+ eind->elf.dynindx = -1;
+ eind->elf.dynstr_index = 0;
+ }
+ else
+ BFD_ASSERT (eind->elf.dynindx == -1);
}
/* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and
@@ -2542,6 +3394,83 @@ ppc64_elf_mark_entry_syms (info)
return TRUE;
}
+static bfd_boolean
+update_local_sym_info (abfd, symtab_hdr, r_symndx, r_addend, tls_type)
+ bfd *abfd;
+ Elf_Internal_Shdr *symtab_hdr;
+ unsigned long r_symndx;
+ bfd_vma r_addend;
+ int tls_type;
+{
+ struct got_entry **local_got_ents = elf_local_got_ents (abfd);
+ char *local_got_tls_types;
+
+ if (local_got_ents == NULL)
+ {
+ bfd_size_type size = symtab_hdr->sh_info;
+
+ size *= sizeof (*local_got_ents) + sizeof (char);
+ local_got_ents = (struct got_entry **) bfd_zalloc (abfd, size);
+ if (local_got_ents == NULL)
+ return FALSE;
+ elf_local_got_ents (abfd) = local_got_ents;
+ }
+
+ if ((tls_type & TLS_EXPLICIT) == 0)
+ {
+ struct got_entry *ent;
+
+ for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next)
+ if (ent->addend == r_addend && ent->tls_type == tls_type)
+ break;
+ if (ent == NULL)
+ {
+ bfd_size_type amt = sizeof (*ent);
+ ent = (struct got_entry *) bfd_alloc (abfd, amt);
+ if (ent == NULL)
+ return FALSE;
+ ent->next = local_got_ents[r_symndx];
+ ent->addend = r_addend;
+ ent->tls_type = tls_type;
+ ent->got.refcount = 0;
+ local_got_ents[r_symndx] = ent;
+ }
+ ent->got.refcount += 1;
+ }
+
+ local_got_tls_types = (char *) (local_got_ents + symtab_hdr->sh_info);
+ local_got_tls_types[r_symndx] |= tls_type;
+ return TRUE;
+}
+
+static bfd_boolean
+update_plt_info (abfd, eh, addend)
+ bfd *abfd;
+ struct ppc_link_hash_entry *eh;
+ bfd_vma addend;
+{
+ struct plt_entry *ent;
+
+ for (ent = eh->elf.plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == addend)
+ break;
+ if (ent == NULL)
+ {
+ bfd_size_type amt = sizeof (*ent);
+ ent = (struct plt_entry *) bfd_alloc (abfd, amt);
+ if (ent == NULL)
+ return FALSE;
+ ent->next = eh->elf.plt.plist;
+ ent->addend = addend;
+ ent->plt.refcount = 0;
+ eh->elf.plt.plist = ent;
+ }
+ ent->plt.refcount += 1;
+ eh->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ eh->is_func = 1;
+ return TRUE;
+}
+
/* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure
linkage table, and dynamic reloc sections. */
@@ -2610,6 +3539,7 @@ ppc64_elf_check_relocs (abfd, info, sec,
unsigned long r_symndx;
struct elf_link_hash_entry *h;
enum elf_ppc64_reloc_type r_type;
+ int tls_type = 0;
r_symndx = ELF64_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
@@ -2620,14 +3550,45 @@ ppc64_elf_check_relocs (abfd, info, sec,
r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info);
switch (r_type)
{
- /* GOT16 relocations */
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_HA:
+ htab->tlsld_got.refcount += 1;
+ tls_type = TLS_TLS | TLS_GD_LD | TLS_LD;
+ goto dogottls;
+
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_HA:
+ tls_type = TLS_TLS | TLS_GD_LD;
+ goto dogottls;
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_TPREL16_HA:
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ tls_type = TLS_TLS | TLS_TPREL;
+ goto dogottls;
+
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ case R_PPC64_GOT_DTPREL16_HA:
+ tls_type = TLS_TLS | TLS_DTPREL;
+ dogottls:
+ sec->has_tls_reloc = 1;
+ /* Fall thru */
+
case R_PPC64_GOT16:
case R_PPC64_GOT16_DS:
case R_PPC64_GOT16_HA:
case R_PPC64_GOT16_HI:
case R_PPC64_GOT16_LO:
case R_PPC64_GOT16_LO_DS:
-
/* This symbol requires a global offset table entry. */
if (htab->sgot == NULL
&& !create_got_section (htab->elf.dynobj, info))
@@ -2635,28 +3596,34 @@ ppc64_elf_check_relocs (abfd, info, sec,
if (h != NULL)
{
- h->got.refcount += 1;
- }
- else
- {
- bfd_signed_vma *local_got_refcounts;
+ struct ppc_link_hash_entry *eh;
+ struct got_entry *ent;
- /* This is a global offset table entry for a local symbol. */
- local_got_refcounts = elf_local_got_refcounts (abfd);
- if (local_got_refcounts == NULL)
+ eh = (struct ppc_link_hash_entry *) h;
+ for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->tls_type == tls_type)
+ break;
+ if (ent == NULL)
{
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= sizeof (bfd_signed_vma);
- local_got_refcounts = ((bfd_signed_vma *)
- bfd_zalloc (abfd, size));
- if (local_got_refcounts == NULL)
+ bfd_size_type amt = sizeof (*ent);
+ ent = (struct got_entry *) bfd_alloc (abfd, amt);
+ if (ent == NULL)
return FALSE;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
+ ent->next = eh->elf.got.glist;
+ ent->addend = rel->r_addend;
+ ent->tls_type = tls_type;
+ ent->got.refcount = 0;
+ eh->elf.got.glist = ent;
}
- local_got_refcounts[r_symndx] += 1;
+ ent->got.refcount += 1;
+ eh->tls_type |= tls_type;
}
+ else
+ /* This is a global offset table entry for a local symbol. */
+ if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
+ rel->r_addend, tls_type))
+ return FALSE;
break;
case R_PPC64_PLT16_HA:
@@ -2676,10 +3643,10 @@ ppc64_elf_check_relocs (abfd, info, sec,
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
-
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->plt.refcount += 1;
- ((struct ppc_link_hash_entry *) h)->is_func = 1;
+ else
+ if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h,
+ rel->r_addend))
+ return FALSE;
break;
/* The following relocations don't need to propagate the
@@ -2697,6 +3664,16 @@ ppc64_elf_check_relocs (abfd, info, sec,
case R_PPC64_TOC16_HA:
case R_PPC64_TOC16_DS:
case R_PPC64_TOC16_LO_DS:
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_DTPREL16_HIGHER:
+ case R_PPC64_DTPREL16_HIGHERA:
+ case R_PPC64_DTPREL16_HIGHEST:
+ case R_PPC64_DTPREL16_HIGHESTA:
break;
/* This relocation describes the C++ object vtable hierarchy.
@@ -2726,9 +3703,82 @@ ppc64_elf_check_relocs (abfd, info, sec,
{
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
- h->plt.refcount += 1;
- ((struct ppc_link_hash_entry *) h)->is_func = 1;
+ if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h,
+ rel->r_addend))
+ return FALSE;
+ if (h == htab->tls_get_addr)
+ sec->has_tls_reloc = 1;
+ else if (strcmp (h->root.root.string, ".__tls_get_addr") == 0)
+ {
+ htab->tls_get_addr = h;
+ sec->has_tls_reloc = 1;
+ }
+ }
+ break;
+
+ case R_PPC64_TPREL64:
+ tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ goto dotlstoc;
+
+ case R_PPC64_DTPMOD64:
+ if (rel + 1 < rel_end
+ && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)
+ && rel[1].r_offset == rel->r_offset + 8)
+ tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD_LD;
+ else
+ tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD_LD | TLS_LD;
+ goto dotlstoc;
+
+ case R_PPC64_DTPREL64:
+ tls_type = TLS_EXPLICIT | TLS_TLS | TLS_DTPREL;
+ if (rel != relocs
+ && rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64)
+ && rel[-1].r_offset == rel->r_offset - 8)
+ /* This is the second reloc of a dtpmod, dtprel pair.
+ Don't mark with TLS_DTPREL. */
+ goto dodyn;
+
+ dotlstoc:
+ sec->has_tls_reloc = 1;
+ if (h != NULL)
+ {
+ struct ppc_link_hash_entry *eh;
+ eh = (struct ppc_link_hash_entry *) h;
+ eh->tls_type |= tls_type;
+ }
+ else
+ if (!update_local_sym_info (abfd, symtab_hdr, r_symndx,
+ rel->r_addend, tls_type))
+ return FALSE;
+
+ if (ppc64_elf_section_data (sec)->t_symndx == NULL)
+ {
+ bfd_size_type amt = sec->_raw_size * sizeof (unsigned) / 8;
+ ppc64_elf_section_data (sec)->t_symndx
+ = (unsigned *) bfd_zalloc (abfd, amt);
+ if (ppc64_elf_section_data (sec)->t_symndx == NULL)
+ return FALSE;
+ }
+ BFD_ASSERT (rel->r_offset % 8 == 0);
+ ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8] = r_symndx;
+ goto dodyn;
+
+ case R_PPC64_TPREL16:
+ case R_PPC64_TPREL16_LO:
+ case R_PPC64_TPREL16_HI:
+ case R_PPC64_TPREL16_HA:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO_DS:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ if (info->shared)
+ {
+ info->flags |= DF_STATIC_TLS;
+ goto dodyn;
}
break;
@@ -2814,9 +3864,10 @@ ppc64_elf_check_relocs (abfd, info, sec,
may need to keep relocations for symbols satisfied by a
dynamic library if we manage to avoid copy relocs for the
symbol. */
+ dodyn:
if ((info->shared
&& (sec->flags & SEC_ALLOC) != 0
- && (IS_ABSOLUTE_RELOC (r_type)
+ && (MUST_BE_DYN_RELOC (r_type)
|| (h != NULL
&& (! info->symbolic
|| h->root.type == bfd_link_hash_defweak
@@ -2914,7 +3965,7 @@ ppc64_elf_check_relocs (abfd, info, sec,
}
p->count += 1;
- if (!IS_ABSOLUTE_RELOC (r_type))
+ if (!MUST_BE_DYN_RELOC (r_type))
p->pc_count += 1;
}
break;
@@ -3004,20 +4055,22 @@ ppc64_elf_gc_mark_hook (sec, info, rel,
static bfd_boolean
ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs)
bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
+ struct bfd_link_info *info;
asection *sec;
const Elf_Internal_Rela *relocs;
{
+ struct ppc_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
+ struct got_entry **local_got_ents;
const Elf_Internal_Rela *rel, *relend;
elf_section_data (sec)->local_dynrel = NULL;
+ htab = ppc_hash_table (info);
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
+ local_got_ents = elf_local_got_ents (abfd);
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++)
@@ -3025,28 +4078,68 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec
unsigned long r_symndx;
enum elf_ppc64_reloc_type r_type;
struct elf_link_hash_entry *h;
+ char tls_type = 0;
r_symndx = ELF64_R_SYM (rel->r_info);
r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info);
switch (r_type)
{
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_HA:
+ htab->tlsld_got.refcount -= 1;
+ tls_type = TLS_TLS | TLS_GD_LD | TLS_LD;
+ goto dogot;
+
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_HA:
+ tls_type = TLS_TLS | TLS_GD_LD;
+ goto dogot;
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_TPREL16_HA:
+ tls_type = TLS_TLS | TLS_TPREL;
+ goto dogot;
+
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ case R_PPC64_GOT_DTPREL16_HA:
+ tls_type = TLS_TLS | TLS_DTPREL;
+ goto dogot;
+
case R_PPC64_GOT16:
case R_PPC64_GOT16_DS:
case R_PPC64_GOT16_HA:
case R_PPC64_GOT16_HI:
case R_PPC64_GOT16_LO:
case R_PPC64_GOT16_LO_DS:
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->got.refcount > 0)
- h->got.refcount--;
- }
- else
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx]--;
- }
+ dogot:
+ {
+ struct got_entry *ent;
+
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ ent = h->got.glist;
+ }
+ else
+ ent = local_got_ents[r_symndx];
+
+ for (; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->tls_type == tls_type)
+ break;
+ if (ent == NULL)
+ abort ();
+ if (ent->got.refcount > 0)
+ ent->got.refcount -= 1;
+ }
break;
case R_PPC64_PLT16_HA:
@@ -3054,23 +4147,22 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec
case R_PPC64_PLT16_LO:
case R_PPC64_PLT32:
case R_PPC64_PLT64:
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->plt.refcount > 0)
- h->plt.refcount--;
- }
- break;
-
case R_PPC64_REL14:
case R_PPC64_REL14_BRNTAKEN:
case R_PPC64_REL14_BRTAKEN:
case R_PPC64_REL24:
if (r_symndx >= symtab_hdr->sh_info)
{
+ struct plt_entry *ent;
+
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- if (h->plt.refcount > 0)
- h->plt.refcount--;
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend)
+ break;
+ if (ent == NULL)
+ abort ();
+ if (ent->plt.refcount > 0)
+ ent->plt.refcount -= 1;
}
break;
@@ -3098,6 +4190,9 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec
}
break;
+ case R_PPC64_DTPMOD64:
+ case R_PPC64_DTPREL64:
+ case R_PPC64_TPREL64:
case R_PPC64_ADDR14:
case R_PPC64_ADDR14_BRNTAKEN:
case R_PPC64_ADDR14_BRTAKEN:
@@ -3155,6 +4250,7 @@ func_desc_adjust (h, inf)
{
struct bfd_link_info *info;
struct ppc_link_hash_table *htab;
+ struct plt_entry *ent;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
@@ -3174,7 +4270,10 @@ func_desc_adjust (h, inf)
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR))
htab->have_undefweak = TRUE;
- if (h->plt.refcount > 0
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->plt.refcount > 0)
+ break;
+ if (ent != NULL
&& h->root.root.string[0] == '.'
&& h->root.root.string[1] != '\0')
{
@@ -3233,7 +4332,7 @@ func_desc_adjust (h, inf)
| ELF_LINK_NON_GOT_REF));
if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
{
- fdh->plt.refcount = h->plt.refcount;
+ fdh->plt.plist = h->plt.plist;
fdh->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
}
((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1;
@@ -3405,20 +4504,24 @@ ppc64_elf_adjust_dynamic_symbol (info, h
{
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
+ struct plt_entry *ent;
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->plt.refcount > 0)
+ break;
if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor
- || h->plt.refcount <= 0
+ || ent == NULL
|| (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0
|| (! info->shared
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
&& (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0))
{
- h->plt.offset = (bfd_vma) -1;
+ h->plt.plist = NULL;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
return TRUE;
}
else
- h->plt.offset = (bfd_vma) -1;
+ h->plt.plist = NULL;
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
@@ -3567,17 +4670,147 @@ ppc64_elf_hide_symbol (info, h, force_lo
}
}
+static bfd_boolean
+get_sym_h (hp, symp, symsecp, tlstypep, locsymsp, r_symndx, ibfd)
+ struct elf_link_hash_entry **hp;
+ Elf_Internal_Sym **symp;
+ asection **symsecp;
+ char **tlstypep;
+ Elf_Internal_Sym **locsymsp;
+ unsigned long r_symndx;
+ bfd *ibfd;
+{
+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+
+ if (r_symndx >= symtab_hdr->sh_info)
+ {
+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd);
+ struct elf_link_hash_entry *h;
+
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ if (hp != NULL)
+ *hp = h;
+
+ if (symp != NULL)
+ *symp = NULL;
+
+ if (symsecp != NULL)
+ {
+ asection *symsec = NULL;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ symsec = h->root.u.def.section;
+ *symsecp = symsec;
+ }
+
+ if (tlstypep != NULL)
+ {
+ struct ppc_link_hash_entry *eh;
+
+ eh = (struct ppc_link_hash_entry *) h;
+ *tlstypep = &eh->tls_type;
+ }
+ }
+ else
+ {
+ Elf_Internal_Sym *sym;
+ Elf_Internal_Sym *locsyms = *locsymsp;
+
+ if (locsyms == NULL)
+ {
+ locsyms = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (locsyms == NULL)
+ locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
+ symtab_hdr->sh_info,
+ 0, NULL, NULL, NULL);
+ if (locsyms == NULL)
+ return FALSE;
+ *locsymsp = locsyms;
+ }
+ sym = locsyms + r_symndx;
+
+ if (hp != NULL)
+ *hp = NULL;
+
+ if (symp != NULL)
+ *symp = sym;
+
+ if (symsecp != NULL)
+ {
+ asection *symsec = NULL;
+ if ((sym->st_shndx != SHN_UNDEF
+ && sym->st_shndx < SHN_LORESERVE)
+ || sym->st_shndx > SHN_HIRESERVE)
+ symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
+ *symsecp = symsec;
+ }
+
+ if (tlstypep != NULL)
+ {
+ struct got_entry **lgot_ents;
+ char *tlstype;
+
+ tlstype = NULL;
+ lgot_ents = elf_local_got_ents (ibfd);
+ if (lgot_ents != NULL)
+ {
+ char *lgot_types = (char *) (lgot_ents + symtab_hdr->sh_info);
+ tlstype = &lgot_types[r_symndx];
+ }
+ *tlstypep = tlstype;
+ }
+ }
+ return TRUE;
+}
+
+static bfd_boolean
+get_tls_type (tls_type, locsymsp, rel, ibfd)
+ char **tls_type;
+ Elf_Internal_Sym **locsymsp;
+ const Elf_Internal_Rela *rel;
+ bfd *ibfd;
+{
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma off;
+
+ r_symndx = ELF64_R_SYM (rel->r_info);
+ if (!get_sym_h (&h, &sym, &sec, tls_type, locsymsp, r_symndx, ibfd))
+ return FALSE;
+
+ if ((*tls_type != NULL && **tls_type != 0)
+ || sec == NULL
+ || ppc64_elf_section_data (sec)->t_symndx == NULL)
+ return TRUE;
+
+ /* Look inside a TOC section too. */
+ if (h != NULL)
+ {
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+ off = h->root.u.def.value;
+ }
+ else
+ off = sym->st_value;
+ off += rel->r_addend;
+ BFD_ASSERT (off % 8 == 0);
+ r_symndx = ppc64_elf_section_data (sec)->t_symndx[off / 8];
+ return get_sym_h (&h, &sym, NULL, tls_type, locsymsp, r_symndx, ibfd);
+}
+
bfd_boolean
ppc64_elf_edit_opd (obfd, info)
bfd *obfd;
struct bfd_link_info *info;
{
bfd *ibfd;
- unsigned int bfd_indx;
- for (bfd_indx = 0, ibfd = info->input_bfds;
- ibfd != NULL;
- ibfd = ibfd->link_next, bfd_indx++)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
asection *sec;
Elf_Internal_Rela *relstart, *rel, *relend;
@@ -3672,44 +4905,22 @@ ppc64_elf_edit_opd (obfd, info)
}
r_symndx = ELF64_R_SYM (rel->r_info);
- sym_sec = NULL;
- h = NULL;
- sym = NULL;
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- sym_sec = h->root.u.def.section;
- }
- else
- {
- if (local_syms == NULL)
- {
- local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (local_syms == NULL)
- local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
- symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
- if (local_syms == NULL)
- goto error_free_rel;
- }
- sym = local_syms + r_symndx;
- if ((sym->st_shndx != SHN_UNDEF
- && sym->st_shndx < SHN_LORESERVE)
- || sym->st_shndx > SHN_HIRESERVE)
- sym_sec = bfd_section_from_elf_index (ibfd, sym->st_shndx);
- }
+ if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+ r_symndx, ibfd))
+ goto error_free_rel;
if (sym_sec == NULL || sym_sec->owner == NULL)
{
+ const char *sym_name;
+ if (h != NULL)
+ sym_name = h->root.root.string;
+ else
+ sym_name = bfd_elf_local_sym_name (ibfd, sym);
+
(*_bfd_error_handler)
(_("%s: undefined sym `%s' in .opd section"),
bfd_archive_filename (ibfd),
- h != NULL ? h->root.root.string : "<local symbol>");
+ sym_name);
need_edit = FALSE;
break;
}
@@ -3774,28 +4985,8 @@ ppc64_elf_edit_opd (obfd, info)
Elf_Internal_Sym *sym;
r_symndx = ELF64_R_SYM (rel->r_info);
- sym_sec = NULL;
- h = NULL;
- sym = NULL;
- if (r_symndx >= symtab_hdr->sh_info)
- {
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- sym_sec = h->root.u.def.section;
- }
- else
- {
- sym = local_syms + r_symndx;
- if ((sym->st_shndx != SHN_UNDEF
- && sym->st_shndx < SHN_LORESERVE)
- || sym->st_shndx > SHN_HIRESERVE)
- sym_sec = bfd_section_from_elf_index (ibfd,
- sym->st_shndx);
- }
+ get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+ r_symndx, ibfd);
skip = (sym_sec->owner != ibfd
|| sym_sec->output_section == bfd_abs_section_ptr);
@@ -3918,6 +5109,326 @@ ppc64_elf_edit_opd (obfd, info)
return TRUE;
}
+/* Run through all the TLS relocs looking for optimization
+ opportunities. The linker has been hacked (see ppc64elf.em) to do
+ a preliminary section layout so that we know the TLS segment
+ offsets. We can't optimize earlier because some optimizations need
+ to know the tp offset, and we need to optimize before allocating
+ dynamic relocations. */
+
+bfd_boolean
+ppc64_elf_tls_optimize (obfd, info)
+ bfd *obfd;
+ struct bfd_link_info *info;
+{
+ asection *tls;
+ bfd *ibfd;
+ asection *sec;
+ struct ppc_link_hash_table *htab;
+
+ if (info->relocateable)
+ return TRUE;
+
+ for (tls = obfd->sections; tls != NULL; tls = tls->next)
+ if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+ == (SEC_THREAD_LOCAL | SEC_LOAD))
+ break;
+ if (tls == NULL)
+ return TRUE;
+
+ htab = ppc_hash_table (info);
+ htab->tls_sec = tls;
+
+ if (info->shared)
+ return TRUE;
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ {
+ Elf_Internal_Sym *locsyms = NULL;
+
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section))
+ {
+ Elf_Internal_Rela *relstart, *rel, *relend;
+ int expecting_tls_get_addr;
+
+ /* Read the relocations. */
+ relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
+ if (relstart == NULL)
+ return FALSE;
+
+ expecting_tls_get_addr = 0;
+ relend = relstart + sec->reloc_count;
+ for (rel = relstart; rel < relend; rel++)
+ {
+ enum elf_ppc64_reloc_type r_type;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sym_sec;
+ char *tls_type;
+ char tls_set, tls_clear, got_tls_type = 0;
+ bfd_vma value;
+ bfd_boolean ok_tprel;
+
+ r_symndx = ELF64_R_SYM (rel->r_info);
+ if (!get_sym_h (&h, &sym, &sym_sec, &tls_type, &locsyms,
+ r_symndx, ibfd))
+ {
+ err_free_rel:
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ if (locsyms != NULL
+ && (elf_tdata (ibfd)->symtab_hdr.contents
+ != (unsigned char *) locsyms))
+ free (locsyms);
+ return FALSE;
+ }
+
+ if (h != NULL)
+ {
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ continue;
+ value = h->root.u.def.value;
+ }
+ else
+ value = sym->st_value;
+ ok_tprel = FALSE;
+ if (sym_sec != NULL && sym_sec->output_section != NULL)
+ {
+ value += sym_sec->output_offset;
+ value += sym_sec->output_section->vma;
+ value -= htab->tls_sec->vma;
+ ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
+ < (bfd_vma) 1 << 32);
+ }
+
+ r_type
+ = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info);
+ switch (r_type)
+ {
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_HA:
+ htab->tlsld_got.refcount -= 1;
+ if (ok_tprel)
+ /* LD -> LE */
+ tls_set = 0;
+ else
+ /* We still need a GOT entry as the offset is
+ too big. ie. LD -> IE. */
+ tls_set = TLS_TLS | TLS_TPREL;
+ tls_clear = TLS_GD_LD;
+ got_tls_type = TLS_TLS | TLS_GD_LD | TLS_LD;
+ expecting_tls_get_addr = 1;
+ break;
+
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_HA:
+ if (ok_tprel
+ && (h == NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->elf_link_hash_flags
+ & ELF_LINK_FORCED_LOCAL) != 0
+ || !info->shared
+ || info->symbolic))))
+ /* GD -> LE */
+ tls_set = 0;
+ else
+ /* GD -> IE */
+ tls_set = TLS_TLS | TLS_TPREL;
+ tls_clear = TLS_GD_LD;
+ got_tls_type = TLS_TLS | TLS_GD_LD;
+ expecting_tls_get_addr = 1;
+ break;
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_TPREL16_HA:
+ expecting_tls_get_addr = 0;
+ if (ok_tprel)
+ {
+ /* IE -> LE */
+ tls_set = 0;
+ tls_clear = TLS_TPREL;
+ got_tls_type = TLS_TLS | TLS_TPREL;
+ break;
+ }
+ else
+ continue;
+
+ case R_PPC64_REL14:
+ case R_PPC64_REL14_BRTAKEN:
+ case R_PPC64_REL14_BRNTAKEN:
+ case R_PPC64_REL24:
+ if (h != NULL
+ && h == htab->tls_get_addr)
+ {
+ if (!expecting_tls_get_addr
+ && rel != relstart
+ && ((ELF64_R_TYPE (rel[-1].r_info)
+ == R_PPC64_TOC16)
+ || (ELF64_R_TYPE (rel[-1].r_info)
+ == R_PPC64_TOC16_LO)))
+ {
+ /* Check for toc tls entries. */
+ char *toc_tls;
+
+ if (!get_tls_type (&toc_tls, &locsyms,
+ rel - 1, ibfd))
+ goto err_free_rel;
+ if (toc_tls != NULL)
+ expecting_tls_get_addr = *toc_tls != 0;
+ }
+
+ if (expecting_tls_get_addr)
+ {
+ struct plt_entry *ent;
+ for (ent = h->plt.plist; ent; ent = ent->next)
+ if (ent->addend == 0)
+ {
+ if (ent->plt.refcount > 0)
+ ent->plt.refcount -= 1;
+ break;
+ }
+ }
+ }
+ expecting_tls_get_addr = 0;
+ continue;
+
+ case R_PPC64_TPREL64:
+ expecting_tls_get_addr = 0;
+ if (ok_tprel)
+ {
+ /* IE -> LE */
+ tls_set = TLS_EXPLICIT;
+ tls_clear = TLS_TPREL;
+ break;
+ }
+ else
+ continue;
+
+ case R_PPC64_DTPMOD64:
+ expecting_tls_get_addr = 0;
+ if ((*tls_type & TLS_LD) == 0)
+ {
+ if ((h == NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) != 0
+ && ((h->elf_link_hash_flags
+ & ELF_LINK_FORCED_LOCAL) != 0
+ || !info->shared
+ || info->symbolic)))
+ && ok_tprel)
+ /* GD -> LE */
+ tls_set = TLS_EXPLICIT;
+ else
+ /* GD -> IE */
+ tls_set = TLS_EXPLICIT | TLS_TPREL;
+ tls_clear = TLS_GD_LD;
+ }
+ else
+ {
+ if (ok_tprel)
+ /* LD -> LE */
+ tls_set = TLS_EXPLICIT;
+ else
+ /* LD -> IE */
+ tls_set = TLS_EXPLICIT | TLS_TPREL;
+ tls_clear = TLS_GD_LD;
+ }
+ break;
+
+ default:
+ expecting_tls_get_addr = 0;
+ continue;
+ }
+
+ if ((tls_set & TLS_EXPLICIT) == 0)
+ {
+ struct got_entry *ent;
+
+ /* Adjust got entry for this reloc. */
+ if (h != NULL)
+ ent = h->got.glist;
+ else
+ ent = elf_local_got_ents (ibfd)[r_symndx];
+
+ for (; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->tls_type == got_tls_type)
+ break;
+ if (ent == NULL)
+ abort ();
+
+ if (tls_set == 0)
+ {
+ /* We managed to get rid of a got entry. */
+ if (ent->got.refcount > 0)
+ ent->got.refcount -= 1;
+ }
+ else
+ ent->tls_type = tls_set;
+ }
+ else if (h != NULL)
+ {
+ struct ppc_link_hash_entry * eh;
+ struct ppc_dyn_relocs **pp;
+ struct ppc_dyn_relocs *p;
+
+ /* Adjust dynamic relocs. */
+ eh = (struct ppc_link_hash_entry *) h;
+ for (pp = &eh->dyn_relocs;
+ (p = *pp) != NULL;
+ pp = &p->next)
+ if (p->sec == sec)
+ {
+ /* If we got rid of a DTPMOD/DTPREL reloc
+ pair then we'll lose one or two dyn
+ relocs. */
+ if (tls_clear == TLS_GD_LD
+ && rel + 1 < relend
+ && (rel[1].r_info
+ == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64))
+ && rel[1].r_offset == rel->r_offset + 8)
+ p->count -= 1;
+ if (tls_set == TLS_EXPLICIT)
+ p->count -= 1;
+ if (p->count == 0)
+ *pp = p->next;
+ break;
+ }
+ }
+
+ *tls_type |= tls_set;
+ *tls_type &= ~tls_clear;
+ }
+
+ if (elf_section_data (sec)->relocs != relstart)
+ free (relstart);
+ }
+
+ if (locsyms != NULL
+ && (elf_tdata (ibfd)->symtab_hdr.contents
+ != (unsigned char *) locsyms))
+ {
+ if (!info->keep_memory)
+ free (locsyms);
+ else
+ elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms;
+ }
+ }
+ return TRUE;
+}
+
/* This is the condition under which ppc64_elf_finish_dynamic_symbol
will be called from elflink.h. If elflink.h doesn't call our
finish_dynamic_symbol routine, we'll need to do something about
@@ -3942,6 +5453,7 @@ allocate_dynrelocs (h, inf)
asection *s;
struct ppc_link_hash_entry *eh;
struct ppc_dyn_relocs *p;
+ struct got_entry *gent;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
@@ -3953,71 +5465,86 @@ allocate_dynrelocs (h, inf)
htab = ppc_hash_table (info);
if (htab->elf.dynamic_sections_created
- && h->plt.refcount > 0
- && h->dynindx != -1)
+ && h->dynindx != -1
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
{
- BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
+ struct plt_entry *pent;
+ bfd_boolean doneone = FALSE;
+ for (pent = h->plt.plist; pent != NULL; pent = pent->next)
+ if (pent->plt.refcount > 0)
+ {
+ BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor);
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
- {
- /* If this is the first .plt entry, make room for the special
- first entry. */
- s = htab->splt;
- if (s->_raw_size == 0)
- s->_raw_size += PLT_INITIAL_ENTRY_SIZE;
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ s = htab->splt;
+ if (s->_raw_size == 0)
+ s->_raw_size += PLT_INITIAL_ENTRY_SIZE;
- h->plt.offset = s->_raw_size;
+ pent->plt.offset = s->_raw_size;
- /* Make room for this entry. */
- s->_raw_size += PLT_ENTRY_SIZE;
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
- /* Make room for the .glink code. */
- s = htab->sglink;
- if (s->_raw_size == 0)
- s->_raw_size += GLINK_CALL_STUB_SIZE;
- /* We need bigger stubs past index 32767. */
- if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
- s->_raw_size += 4;
- s->_raw_size += 2*4;
+ /* Make room for the .glink code. */
+ s = htab->sglink;
+ if (s->_raw_size == 0)
+ s->_raw_size += GLINK_CALL_STUB_SIZE;
+ /* We need bigger stubs past index 32767. */
+ if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
+ s->_raw_size += 4;
+ s->_raw_size += 2*4;
- /* We also need to make an entry in the .rela.plt section. */
- s = htab->srelplt;
- s->_raw_size += sizeof (Elf64_External_Rela);
- }
- else
+ /* We also need to make an entry in the .rela.plt section. */
+ s = htab->srelplt;
+ s->_raw_size += sizeof (Elf64_External_Rela);
+ doneone = TRUE;
+ }
+ else
+ pent->plt.offset = (bfd_vma) -1;
+ if (!doneone)
{
- h->plt.offset = (bfd_vma) -1;
+ h->plt.plist = NULL;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
}
else
{
- h->plt.offset = (bfd_vma) -1;
+ h->plt.plist = NULL;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
}
- if (h->got.refcount > 0)
- {
- bfd_boolean dyn;
+ for (gent = h->got.glist; gent != NULL; gent = gent->next)
+ if (gent->got.refcount > 0)
+ {
+ /* Make sure this symbol is output as a dynamic symbol.
+ Undefined weak syms won't yet be marked as dynamic. */
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ if (! bfd_elf64_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- if (! bfd_elf64_link_record_dynamic_symbol (info, h))
- return FALSE;
- }
+ if ((gent->tls_type & TLS_LD) != 0)
+ gent->got.offset = htab->tlsld_got.offset;
+ else
+ {
+ bfd_boolean dyn;
- s = htab->sgot;
- h->got.offset = s->_raw_size;
- s->_raw_size += 8;
- dyn = htab->elf.dynamic_sections_created;
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
- htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
- }
- else
- h->got.offset = (bfd_vma) -1;
+ s = htab->sgot;
+ gent->got.offset = s->_raw_size;
+ s->_raw_size += (gent->tls_type & TLS_GD_LD) != 0 ? 16 : 8;
+ dyn = htab->elf.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ htab->srelgot->_raw_size
+ += ((gent->tls_type & TLS_GD_LD) != 0
+ ? 2 * sizeof (Elf64_External_Rela)
+ : sizeof (Elf64_External_Rela));
+ }
+ }
+ else
+ gent->got.offset = (bfd_vma) -1;
eh = (struct ppc_link_hash_entry *) h;
if (eh->dyn_relocs == NULL)
@@ -4153,12 +5680,22 @@ ppc64_elf_size_dynamic_sections (output_
}
}
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = htab->sgot->_raw_size;
+ htab->sgot->_raw_size += 16;
+ if (info->shared)
+ htab->srelgot->_raw_size += sizeof (Elf64_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
{
- bfd_signed_vma *local_got;
- bfd_signed_vma *end_local_got;
+ struct got_entry **lgot_ents;
+ struct got_entry **end_lgot_ents;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
asection *srel;
@@ -4193,26 +5730,52 @@ ppc64_elf_size_dynamic_sections (output_
}
}
- local_got = elf_local_got_refcounts (ibfd);
- if (!local_got)
+ lgot_ents = elf_local_got_ents (ibfd);
+ if (!lgot_ents)
continue;
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
- end_local_got = local_got + locsymcount;
+ end_lgot_ents = lgot_ents + locsymcount;
s = htab->sgot;
srel = htab->srelgot;
- for (; local_got < end_local_got; ++local_got)
+ for (; lgot_ents < end_lgot_ents; ++lgot_ents)
{
- if (*local_got > 0)
- {
- *local_got = s->_raw_size;
- s->_raw_size += 8;
- if (info->shared)
- srel->_raw_size += sizeof (Elf64_External_Rela);
- }
- else
- *local_got = (bfd_vma) -1;
+ struct got_entry *ent;
+
+ for (ent = *lgot_ents; ent != NULL; ent = ent->next)
+ if (ent->got.refcount > 0)
+ {
+ if ((ent->tls_type & TLS_LD) != 0)
+ {
+ if (htab->tlsld_got.offset == (bfd_vma) -1)
+ {
+ htab->tlsld_got.offset = s->_raw_size;
+ s->_raw_size += 16;
+ if (info->shared)
+ srel->_raw_size += sizeof (Elf64_External_Rela);
+ }
+ ent->got.offset = htab->tlsld_got.offset;
+ }
+ else
+ {
+ ent->got.offset = s->_raw_size;
+ if ((ent->tls_type & TLS_GD_LD) != 0)
+ {
+ s->_raw_size += 16;
+ if (info->shared)
+ srel->_raw_size += 2 * sizeof (Elf64_External_Rela);
+ }
+ else
+ {
+ s->_raw_size += 8;
+ if (info->shared)
+ srel->_raw_size += sizeof (Elf64_External_Rela);
+ }
+ }
+ }
+ else
+ ent->got.offset = (bfd_vma) -1;
}
}
@@ -4228,6 +5791,10 @@ ppc64_elf_size_dynamic_sections (output_
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
+ /* Reset _cooked_size since prelim layout will set it wrongly,
+ and a non-zero _cooked_size sticks. */
+ s->_cooked_size = 0;
+
if (s == htab->sbrlt || s == htab->srelbrlt)
/* These haven't been allocated yet; don't strip. */
continue;
@@ -4281,8 +5848,10 @@ ppc64_elf_size_dynamic_sections (output_
/* Allocate memory for the section contents. We use bfd_zalloc
here in case unused entries are not reclaimed before the
section's contents are written out. This should not happen,
- but this way if it does, we get a R_PPC64_NONE reloc instead
- of garbage. */
+ but this way if it does we get a R_PPC64_NONE reloc in .rela
+ sections instead of garbage.
+ We also rely on the section contents being zero when writing
+ the GOT. */
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL)
return FALSE;
@@ -4364,11 +5933,16 @@ ppc_type_of_stub (input_sec, rel, hash,
if (h != NULL)
{
if (h->oh != NULL
- && h->oh->plt.offset != (bfd_vma) -1
&& h->oh->dynindx != -1)
{
- *hash = (struct ppc_link_hash_entry *) h->oh;
- return ppc_stub_plt_call;
+ struct plt_entry *ent;
+ for (ent = h->oh->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->plt.offset != (bfd_vma) -1)
+ {
+ *hash = (struct ppc_link_hash_entry *) h->oh;
+ return ppc_stub_plt_call;
+ }
}
if (h->elf.root.type == bfd_link_hash_undefweak
@@ -4443,6 +6017,7 @@ ppc_build_one_stub (gen_entry, in_arg)
bfd_byte *loc;
bfd_byte *p;
unsigned int indx;
+ struct plt_entry *ent;
bfd_vma off;
int size;
@@ -4554,7 +6129,13 @@ ppc_build_one_stub (gen_entry, in_arg)
}
/* Now build the stub. */
- off = stub_entry->h->elf.plt.offset;
+ off = (bfd_vma) -1;
+ for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == stub_entry->addend)
+ {
+ off = ent->plt.offset;
+ break;
+ }
if (off >= (bfd_vma) -2)
abort ();
@@ -4607,7 +6188,15 @@ ppc_size_one_stub (gen_entry, in_arg)
if (stub_entry->stub_type == ppc_stub_plt_call)
{
- off = stub_entry->h->elf.plt.offset & ~(bfd_vma) 1;
+ struct plt_entry *ent;
+ for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == stub_entry->addend)
+ {
+ off = ent->plt.offset & ~(bfd_vma) 1;
+ break;
+ }
+ if (ent == NULL)
+ abort ();
off += (htab->splt->output_offset
+ htab->splt->output_section->vma
- elf_gp (htab->splt->output_section->owner)
@@ -4938,6 +6527,8 @@ ppc64_elf_size_stubs (output_bfd, stub_b
bfd_vma sym_value;
bfd_vma destination;
struct ppc_link_hash_entry *hash;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
char *stub_name;
const asection *id_sec;
@@ -4959,33 +6550,16 @@ ppc64_elf_size_stubs (output_bfd, stub_b
/* Now determine the call target, its name, value,
section. */
- sym_sec = NULL;
- sym_value = 0;
destination = 0;
- hash = NULL;
- if (r_indx < symtab_hdr->sh_info)
+ if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms,
+ r_indx, input_bfd))
+ goto error_ret_free_internal;
+ hash = (struct ppc_link_hash_entry *) h;
+
+ if (hash == NULL)
{
/* It's a local symbol. */
- Elf_Internal_Sym *sym;
- Elf_Internal_Shdr *hdr;
-
- if (local_syms == NULL)
- {
- local_syms
- = (Elf_Internal_Sym *) symtab_hdr->contents;
- if (local_syms == NULL)
- local_syms
- = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
- symtab_hdr->sh_info, 0,
- NULL, NULL, NULL);
- if (local_syms == NULL)
- goto error_ret_free_internal;
- }
- sym = local_syms + r_indx;
- hdr = elf_elfsections (input_bfd)[sym->st_shndx];
- sym_sec = hdr->bfd_section;
- if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
- sym_value = sym->st_value;
+ sym_value = sym->st_value;
destination = (sym_value + irela->r_addend
+ sym_sec->output_offset
+ sym_sec->output_section->vma);
@@ -4993,21 +6567,10 @@ ppc64_elf_size_stubs (output_bfd, stub_b
else
{
/* It's an external symbol. */
- int e_indx;
-
- e_indx = r_indx - symtab_hdr->sh_info;
- hash = ((struct ppc_link_hash_entry *)
- elf_sym_hashes (input_bfd)[e_indx]);
-
- while (hash->elf.root.type == bfd_link_hash_indirect
- || hash->elf.root.type == bfd_link_hash_warning)
- hash = ((struct ppc_link_hash_entry *)
- hash->elf.root.u.i.link);
-
+ sym_value = 0;
if (hash->elf.root.type == bfd_link_hash_defined
|| hash->elf.root.type == bfd_link_hash_defweak)
{
- sym_sec = hash->elf.root.u.def.section;
sym_value = hash->elf.root.u.def.value;
if (sym_sec->output_section != NULL)
destination = (sym_value + irela->r_addend
@@ -5031,6 +6594,24 @@ ppc64_elf_size_stubs (output_bfd, stub_b
if (stub_type == ppc_stub_none)
continue;
+ /* __tls_get_addr calls might be eliminated. */
+ if (stub_type != ppc_stub_plt_call
+ && hash != NULL
+ && &hash->elf == htab->tls_get_addr
+ && section->has_tls_reloc
+ && irela != internal_relocs)
+ {
+ /* Get tls info. */
+ char *tls_type;
+
+ if (!get_tls_type (&tls_type, &local_syms,
+ irela - 1, input_bfd))
+ goto error_ret_free_internal;
+ if (tls_type != NULL
+ && (*tls_type & (TLS_TLS | TLS_GD_LD)) == TLS_TLS)
+ continue;
+ }
+
/* Support for grouping stub sections. */
id_sec = htab->stub_group[section->id].link_sec;
@@ -5067,6 +6648,7 @@ ppc64_elf_size_stubs (output_bfd, stub_b
stub_entry->target_section = sym_sec;
stub_entry->stub_type = stub_type;
stub_entry->h = hash;
+ stub_entry->addend = irela->r_addend;
stub_changed = TRUE;
}
@@ -5317,7 +6899,10 @@ ppc64_elf_relocate_section (output_bfd,
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- bfd_vma *local_got_offsets;
+ Elf_Internal_Rela outrel;
+ bfd_byte *loc;
+ unsigned int tls_get_addr_type;
+ struct got_entry **local_got_ents;
bfd_vma TOCstart;
bfd_boolean ret = TRUE;
bfd_boolean is_opd;
@@ -5332,18 +6917,32 @@ ppc64_elf_relocate_section (output_bfd,
ppc_howto_init ();
htab = ppc_hash_table (info);
- local_got_offsets = elf_local_got_offsets (input_bfd);
+ if (info->shared && (htab->tlsld_got.offset & 1) == 0)
+ {
+ outrel.r_offset = (htab->sgot->output_section->vma
+ + htab->sgot->output_offset
+ + htab->tlsld_got.offset);
+ outrel.r_info = ELF64_R_INFO (0, R_PPC64_DTPMOD64);
+ outrel.r_addend = 0;
+
+ loc = htab->srelgot->contents;
+ loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+ bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+ htab->tlsld_got.offset |= 1;
+ }
+
+ local_got_ents = elf_local_got_ents (input_bfd);
TOCstart = elf_gp (output_bfd);
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
is_opd = ppc64_elf_section_data (input_section)->opd.adjust != NULL;
+ tls_get_addr_type = 0;
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
enum elf_ppc64_reloc_type r_type;
- bfd_vma offset;
bfd_vma addend;
bfd_reloc_status_type r;
Elf_Internal_Sym *sym;
@@ -5352,6 +6951,7 @@ ppc64_elf_relocate_section (output_bfd,
struct elf_link_hash_entry *fdh;
const char *sym_name;
unsigned long r_symndx;
+ char tls_type;
bfd_vma relocation;
bfd_boolean unresolved_reloc;
bfd_boolean warned;
@@ -5362,8 +6962,6 @@ ppc64_elf_relocate_section (output_bfd,
r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info);
r_symndx = ELF64_R_SYM (rel->r_info);
- offset = rel->r_offset;
- addend = rel->r_addend;
r = bfd_reloc_other;
sym = (Elf_Internal_Sym *) 0;
sec = (asection *) 0;
@@ -5382,12 +6980,8 @@ ppc64_elf_relocate_section (output_bfd,
/* It's a local symbol. */
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- sym_name = "<local symbol>";
-
+ sym_name = bfd_elf_local_sym_name (input_bfd, sym);
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
- /* rel may have changed, update our copy of addend. */
- addend = rel->r_addend;
-
if (elf_section_data (sec) != NULL)
{
long *opd_sym_adjust;
@@ -5432,15 +7026,275 @@ ppc64_elf_relocate_section (output_bfd,
{
if (! ((*info->callbacks->undefined_symbol)
(info, h->root.root.string, input_bfd, input_section,
- offset, (!info->shared
- || info->no_undefined
- || ELF_ST_VISIBILITY (h->other)))))
+ rel->r_offset, (!info->shared
+ || info->no_undefined
+ || ELF_ST_VISIBILITY (h->other)))))
return FALSE;
warned = TRUE;
}
}
- /* First handle relocations that tweak non-addend part of insn. */
+ /* TLS optimizations. */
+ tls_type = 0;
+ if (IS_TLS_RELOC (r_type))
+ {
+ if (h != NULL)
+ tls_type = ((struct ppc_link_hash_entry *) h)->tls_type;
+ else if (local_got_ents != NULL)
+ {
+ char *lgot_types;
+ lgot_types = (char *) (local_got_ents + symtab_hdr->sh_info);
+ tls_type = lgot_types[r_symndx];
+ }
+ }
+
+ /* Ensure reloc mapping code below stays sane. */
+ if (R_PPC64_TOC16_LO_DS != R_PPC64_TOC16_DS + 1
+ || R_PPC64_TOC16_LO != R_PPC64_TOC16 + 1
+ || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TLSGD16 & 3)
+ || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TLSGD16_LO & 3)
+ || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TLSGD16_HI & 3)
+ || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TLSGD16_HA & 3)
+ || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TPREL16_DS & 3)
+ || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TPREL16_LO_DS & 3)
+ || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3)
+ || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3))
+ abort ();
+ switch (r_type)
+ {
+ default:
+ tls_get_addr_type = 0;
+ break;
+
+ case R_PPC64_TOC16:
+ case R_PPC64_TOC16_LO:
+ case R_PPC64_TOC16_DS:
+ case R_PPC64_TOC16_LO_DS:
+ tls_get_addr_type = 0;
+ {
+ /* Check for toc tls entries. */
+ char *toc_tls;
+
+ if (!get_tls_type (&toc_tls, &local_syms, rel, input_bfd))
+ return FALSE;
+
+ if (toc_tls)
+ {
+ tls_type = *toc_tls;
+ if (r_type == R_PPC64_TOC16_DS
+ || r_type == R_PPC64_TOC16_LO_DS)
+ goto toctprel;
+ else
+ tls_get_addr_type = tls_type;
+ }
+ }
+ break;
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ tls_get_addr_type = 0;
+ toctprel:
+ if (tls_type != 0
+ && (tls_type & TLS_TPREL) == 0)
+ {
+ bfd_vma insn;
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2);
+ insn &= 31 << 21;
+ insn |= 0x3c0d0000; /* addis 0,13,0 */
+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2);
+ r_type = R_PPC64_TPREL16_HA;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ }
+ break;
+
+ case R_PPC64_TLS:
+ tls_get_addr_type = 0;
+ if (tls_type == 0)
+ {
+ /* Check for toc tls entries. */
+ char *toc_tls;
+
+ if (!get_tls_type (&toc_tls, &local_syms, rel, input_bfd))
+ return FALSE;
+
+ if (toc_tls)
+ tls_type = *toc_tls;
+ }
+ if (tls_type != 0
+ && (tls_type & TLS_TPREL) == 0)
+ {
+ bfd_vma insn, rtra;
+ insn = bfd_get_32 (output_bfd, contents + rel->r_offset);
+ if ((insn & ((31 << 26) | (31 << 11)))
+ == ((31 << 26) | (13 << 11)))
+ rtra = insn & ((1 << 26) - (1 << 16));
+ else if ((insn & ((31 << 26) | (31 << 16)))
+ == ((31 << 26) | (13 << 16)))
+ rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5);
+ else
+ abort ();
+ if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1)
+ /* add -> addi. */
+ insn = 14 << 26;
+ else if ((insn & (31 << 1)) == 23 << 1
+ && ((insn & (31 << 6)) < 14 << 6
+ || ((insn & (31 << 6)) >= 16 << 6
+ && (insn & (31 << 6)) < 24 << 6)))
+ /* load and store indexed -> dform. */
+ insn = (32 | ((insn >> 6) & 31)) << 26;
+ else if ((insn & (31 << 1)) == 21 << 1
+ && (insn & (0x1a << 6)) == 0)
+ /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */
+ insn = (((58 | ((insn >> 6) & 4)) << 26)
+ | ((insn >> 6) & 1));
+ else if ((insn & (31 << 1)) == 21 << 1
+ && (insn & ((1 << 11) - (1 << 1))) == 341 << 1)
+ /* lwax -> lwa. */
+ insn = (58 << 26) | 2;
+ else
+ abort ();
+ insn |= rtra;
+ bfd_put_32 (output_bfd, insn, contents + rel->r_offset);
+ r_type = R_PPC64_TPREL16_LO;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ /* Was PPC64_TLS which sits on insn boundary, now
+ PPC64_TPREL16_LO which is at insn+2. */
+ rel->r_offset += 2;
+ }
+ break;
+
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_HA:
+ tls_get_addr_type = 0;
+ if (tls_type != 0 && (tls_type & TLS_GD_LD) == 0)
+ {
+ if (r_type == R_PPC64_GOT_TLSGD16_HI
+ || r_type == R_PPC64_GOT_TLSGD16_HA
+ || r_type == R_PPC64_GOT_TLSLD16_HI
+ || r_type == R_PPC64_GOT_TLSLD16_HA)
+ {
+ if ((tls_type & TLS_LD) != 0)
+ {
+ bfd_put_32 (output_bfd, NOP, contents + rel->r_offset);
+ r_type = R_PPC64_NONE;
+ rel->r_offset -= 2;
+ }
+ else
+ r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
+ + R_PPC64_GOT_TPREL16_DS);
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ break;
+ }
+
+ /* This reloc and its instruction will be replaced so there's
+ not much point in doing anything more here. We know the
+ next reloc will be a REL24 to __tls_get_addr, and will
+ be handled below. */
+ tls_get_addr_type = tls_type;
+ continue;
+ }
+ break;
+
+ case R_PPC64_REL14:
+ case R_PPC64_REL14_BRTAKEN:
+ case R_PPC64_REL14_BRNTAKEN:
+ case R_PPC64_REL24:
+ if (h != NULL
+ && h == htab->tls_get_addr
+ && tls_get_addr_type != 0
+ && (tls_get_addr_type & TLS_GD_LD) == 0)
+ {
+ /* Replace the call. */
+ bfd_vma insn1, insn2, insn3;
+ bfd_vma offset = rel->r_offset;
+
+ insn1 = bfd_get_32 (output_bfd, contents + rel[-1].r_offset - 2);
+ insn3 = bfd_get_32 (output_bfd, contents + offset + 4);
+ if (tls_get_addr_type & TLS_TPREL)
+ {
+ /* IE */
+ insn1 &= (1 << 26) - (1 << 2);
+ insn1 |= 58 << 26; /* ld */
+ insn2 = 0x7c636a14; /* add 3,3,13 */
+ /* Fix the relocs for --emit-relocs. */
+ r_type = ELF64_R_TYPE (rel[-1].r_info);
+ if (tls_get_addr_type & TLS_EXPLICIT)
+ r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16;
+ else
+ r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3)
+ + R_PPC64_GOT_TPREL16_DS);
+ rel[-1].r_info
+ = ELF64_R_INFO (ELF64_R_SYM (rel[-1].r_info), r_type);
+ rel->r_info = 0;
+ }
+ else
+ {
+ /* LE */
+ insn1 = 0x3c6d0000; /* addis 3,13,0 */
+ insn2 = 0x38630000; /* addi 3,3,0 */
+ if (tls_get_addr_type & TLS_LD)
+ {
+ r_symndx = 0;
+ rel[-1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
+ rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
+ }
+ else
+ r_symndx = ELF64_R_SYM (rel[-1].r_info);
+ rel[-1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_TPREL16_HA);
+ rel->r_info = ELF64_R_INFO (r_symndx, R_PPC64_TPREL16_LO);
+ rel->r_offset += 2;
+ }
+ if (insn3 == NOP
+ || insn3 == CROR_151515 || insn3 == CROR_313131)
+ {
+ insn3 = insn2;
+ insn2 = NOP;
+ rel->r_offset += 4;
+ }
+ bfd_put_32 (output_bfd, insn1, contents + rel[-1].r_offset - 2);
+ bfd_put_32 (output_bfd, insn2, contents + offset);
+ bfd_put_32 (output_bfd, insn3, contents + offset + 4);
+ /* Do the relocs again. */
+ rel -= 2;
+ tls_get_addr_type = 0;
+ continue;
+ }
+ tls_get_addr_type = 0;
+ break;
+
+ case R_PPC64_DTPMOD64:
+ if ((tls_type & TLS_GD_LD) == 0)
+ {
+ if ((tls_type & TLS_TPREL) != 0)
+ r_type = R_PPC64_TPREL64;
+ else
+ {
+ bfd_put_64 (output_bfd, (bfd_vma) 1,
+ contents + rel->r_offset);
+ r_type = R_PPC64_NONE;
+ }
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ if ((tls_type & TLS_LD) == 0)
+ rel[1].r_info = 0;
+ }
+ break;
+
+ case R_PPC64_TPREL64:
+ if ((tls_type & TLS_TPREL) == 0)
+ {
+ r_type = R_PPC64_NONE;
+ rel->r_info = ELF64_R_INFO (r_symndx, r_type);
+ }
+ break;
+ }
+
+ /* Handle other relocations that tweak non-addend part of insn. */
insn = 0;
switch (r_type)
{
@@ -5456,7 +7310,8 @@ ppc64_elf_relocate_section (output_bfd,
/* Branch not taken prediction relocations. */
case R_PPC64_ADDR14_BRNTAKEN:
case R_PPC64_REL14_BRNTAKEN:
- insn |= bfd_get_32 (output_bfd, contents + offset) & ~(0x01 << 21);
+ insn |= bfd_get_32 (output_bfd,
+ contents + rel->r_offset) & ~(0x01 << 21);
if (is_power4)
{
/* Set 'a' bit. This is 0b00010 in BO field for branch
@@ -5471,16 +7326,16 @@ ppc64_elf_relocate_section (output_bfd,
}
else
{
- from = (offset
+ from = (rel->r_offset
+ input_section->output_offset
+ input_section->output_section->vma);
/* Invert 'y' bit if not the default. */
- if ((bfd_signed_vma) (relocation + addend - from) < 0)
+ if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0)
insn ^= 0x01 << 21;
}
- bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset);
+ bfd_put_32 (output_bfd, (bfd_vma) insn, contents + rel->r_offset);
break;
case R_PPC64_REL24:
@@ -5491,20 +7346,20 @@ ppc64_elf_relocate_section (output_bfd,
need for a PLT entry. */
if (h != NULL
&& (fdh = ((struct ppc_link_hash_entry *) h)->oh) != NULL
- && fdh->plt.offset != (bfd_vma) -1
+ && fdh->plt.plist != NULL
&& (stub_entry = ppc_get_stub_entry (input_section, sec, fdh,
rel, htab)) != NULL)
{
bfd_boolean can_plt_call = 0;
- if (offset + 8 <= input_section->_cooked_size)
+ if (rel->r_offset + 8 <= input_section->_cooked_size)
{
- insn = bfd_get_32 (input_bfd, contents + offset + 4);
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
if (insn == NOP
|| insn == CROR_151515 || insn == CROR_313131)
{
bfd_put_32 (input_bfd, (bfd_vma) LD_R2_40R1,
- contents + offset + 4);
+ contents + rel->r_offset + 4);
can_plt_call = 1;
}
}
@@ -5513,7 +7368,7 @@ ppc64_elf_relocate_section (output_bfd,
{
/* If this is a plain branch rather than a branch
and link, don't require a nop. */
- insn = bfd_get_32 (input_bfd, contents + offset);
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
if ((insn & 1) == 0)
can_plt_call = 1;
}
@@ -5523,7 +7378,6 @@ ppc64_elf_relocate_section (output_bfd,
relocation = (stub_entry->stub_offset
+ stub_entry->stub_sec->output_offset
+ stub_entry->stub_sec->output_section->vma);
- addend = 0;
unresolved_reloc = FALSE;
}
}
@@ -5531,7 +7385,7 @@ ppc64_elf_relocate_section (output_bfd,
if (h != NULL
&& h->root.type == bfd_link_hash_undefweak
&& relocation == 0
- && addend == 0)
+ && rel->r_addend == 0)
{
/* Tweak calls to undefined weak functions to point at a
blr. We can thus call a weak function without first
@@ -5541,7 +7395,7 @@ ppc64_elf_relocate_section (output_bfd,
relocation = (htab->sfpr->_raw_size - 4
+ htab->sfpr->output_offset
+ htab->sfpr->output_section->vma);
- from = (offset
+ from = (rel->r_offset
+ input_section->output_offset
+ input_section->output_section->vma);
@@ -5555,6 +7409,8 @@ ppc64_elf_relocate_section (output_bfd,
}
/* Set `addend'. */
+ tls_type = 0;
+ addend = rel->r_addend;
switch (r_type)
{
default:
@@ -5567,34 +7423,81 @@ ppc64_elf_relocate_section (output_bfd,
continue;
case R_PPC64_NONE:
+ case R_PPC64_TLS:
case R_PPC64_GNU_VTINHERIT:
case R_PPC64_GNU_VTENTRY:
continue;
/* GOT16 relocations. Like an ADDR16 using the symbol's
address in the GOT as relocation value instead of the
- symbols value itself. Also, create a GOT entry for the
+ symbol's value itself. Also, create a GOT entry for the
symbol and put the symbol value there. */
+ case R_PPC64_GOT_TLSGD16:
+ case R_PPC64_GOT_TLSGD16_LO:
+ case R_PPC64_GOT_TLSGD16_HI:
+ case R_PPC64_GOT_TLSGD16_HA:
+ tls_type = TLS_TLS | TLS_GD_LD;
+ goto dogot;
+
+ case R_PPC64_GOT_TLSLD16:
+ case R_PPC64_GOT_TLSLD16_LO:
+ case R_PPC64_GOT_TLSLD16_HI:
+ case R_PPC64_GOT_TLSLD16_HA:
+ tls_type = TLS_TLS | TLS_GD_LD | TLS_LD;
+ goto dogot;
+
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_TPREL16_HI:
+ case R_PPC64_GOT_TPREL16_HA:
+ tls_type = TLS_TLS | TLS_TPREL;
+ goto dogot;
+
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_HI:
+ case R_PPC64_GOT_DTPREL16_HA:
+ tls_type = TLS_TLS | TLS_DTPREL;
+ goto dogot;
+
case R_PPC64_GOT16:
case R_PPC64_GOT16_LO:
case R_PPC64_GOT16_HI:
case R_PPC64_GOT16_HA:
case R_PPC64_GOT16_DS:
case R_PPC64_GOT16_LO_DS:
+ dogot:
{
/* Relocation is to the entry for this symbol in the global
offset table. */
+ struct got_entry *ent;
bfd_vma off;
+ unsigned long indx;
if (htab->sgot == NULL)
abort ();
if (h != NULL)
+ ent = h->got.glist;
+ else
{
- bfd_boolean dyn;
+ if (local_got_ents == NULL)
+ abort ();
+ ent = local_got_ents[r_symndx];
+ }
- off = h->got.offset;
- dyn = htab->elf.dynamic_sections_created;
+ for (; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->tls_type == tls_type)
+ break;
+ if (ent == NULL)
+ abort ();
+
+ off = ent->got.offset;
+ indx = 0;
+ if (h != NULL)
+ {
+ bfd_boolean dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)
|| (info->shared
&& (info->symbolic
@@ -5603,68 +7506,87 @@ ppc64_elf_relocate_section (output_bfd,
& ELF_LINK_FORCED_LOCAL))
&& (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, or the symbol was forced to be local
+ because of a version file. */
+ ;
+ else
{
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally, or the symbol was forced to be local
- because of a version file. We must initialize
- this entry in the global offset table. Since the
- offset must always be a multiple of 8, we use the
- least significant bit to record whether we have
- initialized it already.
-
- When doing a dynamic link, we create a .rel.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_64 (output_bfd, relocation,
- htab->sgot->contents + off);
- h->got.offset |= 1;
- }
+ indx = h->dynindx;
+ unresolved_reloc = FALSE;
}
- else
- unresolved_reloc = FALSE;
}
+
+ /* The offset must always be a multiple of 8. We use the
+ least significant bit to record whether we have already
+ processed this entry. */
+ if ((off & 1) != 0)
+ off &= ~1;
else
{
- if (local_got_offsets == NULL)
- abort ();
-
- off = local_got_offsets[r_symndx];
-
- /* The offset must always be a multiple of 8. We use
- the least significant bit to record whether we have
- already processed this entry. */
- if ((off & 1) != 0)
- off &= ~1;
- else
+ /* Generate relocs for the dynamic linker, except in
+ the case of TLSLD where we'll use one entry per
+ module. */
+ if ((info->shared || indx != 0)
+ && ent->tls_type != (TLS_TLS | TLS_GD_LD | TLS_LD))
{
- bfd_put_64 (output_bfd, relocation,
- htab->sgot->contents + off);
-
- if (info->shared)
+ outrel.r_offset = (htab->sgot->output_section->vma
+ + htab->sgot->output_offset
+ + off);
+ if (ent->tls_type == (TLS_TLS | TLS_GD_LD))
{
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
-
- /* We need to generate a R_PPC64_RELATIVE reloc
- for the dynamic linker. */
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + off);
- outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
- outrel.r_addend = relocation;
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
+ outrel.r_addend = 0;
loc = htab->srelgot->contents;
loc += (htab->srelgot->reloc_count++
* sizeof (Elf64_External_Rela));
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
+ outrel.r_offset += 8;
}
+ else if (ent->tls_type == (TLS_TLS | TLS_DTPREL))
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
+ else if (ent->tls_type == (TLS_TLS | TLS_TPREL))
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64);
+ else if (indx == 0)
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
+ else
+ outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
+ outrel.r_addend = ent->addend;
+ if (indx == 0)
+ outrel.r_addend += relocation;
+ loc = htab->srelgot->contents;
+ loc += (htab->srelgot->reloc_count++
+ * sizeof (Elf64_External_Rela));
+ bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+ }
- local_got_offsets[r_symndx] |= 1;
+ /* Init the .got section contents if we're not
+ emitting a reloc. */
+ if (!(info->shared || indx != 0))
+ {
+
+ relocation += ent->addend;
+ if ((tls_type & TLS_TLS) != 0)
+ {
+ relocation -= htab->tls_sec->vma + DTP_OFFSET;
+ if ((tls_type & TLS_TPREL) != 0)
+ relocation += DTP_OFFSET - TP_OFFSET;
+ }
+
+ if ((tls_type & TLS_GD_LD) != 0)
+ {
+ if ((tls_type & TLS_LD) != 0)
+ relocation = - DTP_OFFSET;
+ bfd_put_64 (output_bfd, relocation,
+ htab->sgot->contents + off + 8);
+ relocation = 1;
+ }
+ bfd_put_64 (output_bfd, relocation,
+ htab->sgot->contents + off);
}
+ ent->got.offset |= 1;
}
if (off >= (bfd_vma) -2)
@@ -5673,7 +7595,7 @@ ppc64_elf_relocate_section (output_bfd,
relocation = htab->sgot->output_offset + off;
/* TOC base (r2) is TOC start plus 0x8000. */
- addend -= TOC_BASE_OFF;
+ addend = - TOC_BASE_OFF;
}
break;
@@ -5690,19 +7612,23 @@ ppc64_elf_relocate_section (output_bfd,
if (h == NULL)
break;
- if (h->plt.offset == (bfd_vma) -1
- || htab->splt == NULL)
+ /* It's possible that we didn't make a PLT entry for this
+ symbol. This happens when statically linking PIC code,
+ or when using -Bsymbolic. Go find a match if there is a
+ PLT entry. */
+ if (htab->splt != NULL)
{
- /* We didn't make a PLT entry for this symbol. This
- happens when statically linking PIC code, or when
- using -Bsymbolic. */
- break;
+ struct plt_entry *ent;
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->addend == rel->r_addend
+ && ent->plt.offset != (bfd_vma) -1)
+ {
+ relocation = (htab->splt->output_section->vma
+ + htab->splt->output_offset
+ + ent->plt.offset);
+ unresolved_reloc = FALSE;
+ }
}
-
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
- + h->plt.offset);
- unresolved_reloc = FALSE;
break;
/* TOC16 relocs. We want the offset relative to the TOC base,
@@ -5735,8 +7661,48 @@ ppc64_elf_relocate_section (output_bfd,
case R_PPC64_REL24:
break;
+ case R_PPC64_TPREL16:
+ case R_PPC64_TPREL16_LO:
+ case R_PPC64_TPREL16_HI:
+ case R_PPC64_TPREL16_HA:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO_DS:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ addend -= htab->tls_sec->vma + TP_OFFSET;
+ if (info->shared)
+ /* The TPREL16 relocs shouldn't really be used in shared
+ libs as they will result in DT_TEXTREL being set, but
+ support them anyway. */
+ goto dodyn;
+ break;
+
+ case R_PPC64_DTPREL16:
+ case R_PPC64_DTPREL16_LO:
+ case R_PPC64_DTPREL16_HI:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_LO_DS:
+ case R_PPC64_DTPREL16_HIGHER:
+ case R_PPC64_DTPREL16_HIGHERA:
+ case R_PPC64_DTPREL16_HIGHEST:
+ case R_PPC64_DTPREL16_HIGHESTA:
+ addend -= htab->tls_sec->vma + DTP_OFFSET;
+ break;
+
+ case R_PPC64_TPREL64:
+ addend -= htab->tls_sec->vma + TP_OFFSET;
+ goto dodyn;
+
+ case R_PPC64_DTPREL64:
+ addend -= htab->tls_sec->vma + DTP_OFFSET;
+ /* Fall thru */
+
/* Relocations that may need to be propagated if this is a
dynamic object. */
+ case R_PPC64_DTPMOD64:
case R_PPC64_REL30:
case R_PPC64_REL32:
case R_PPC64_REL64:
@@ -5762,6 +7728,7 @@ ppc64_elf_relocate_section (output_bfd,
/* r_symndx will be zero only for relocs against symbols
from removed linkonce sections, or sections discarded by
a linker script. */
+ dodyn:
if (r_symndx == 0)
break;
/* Fall thru. */
@@ -5774,7 +7741,7 @@ ppc64_elf_relocate_section (output_bfd,
break;
if ((info->shared
- && (IS_ABSOLUTE_RELOC (r_type)
+ && (MUST_BE_DYN_RELOC (r_type)
|| (h != NULL
&& h->dynindx != -1
&& (! info->symbolic
@@ -5812,14 +7779,14 @@ ppc64_elf_relocate_section (output_bfd,
skip = TRUE, relocate = TRUE;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
- outrel.r_addend = addend;
+ outrel.r_addend = rel->r_addend;
if (skip)
memset (&outrel, 0, sizeof outrel);
else if (h != NULL
&& h->dynindx != -1
&& !is_opd
- && (!IS_ABSOLUTE_RELOC (r_type)
+ && (!MUST_BE_DYN_RELOC (r_type)
|| !info->shared
|| !info->symbolic
|| (h->elf_link_hash_flags
@@ -5831,6 +7798,7 @@ ppc64_elf_relocate_section (output_bfd,
or this is an opd section reloc which must point
at a local function. */
outrel.r_addend += relocation;
+ /* ??? why? */
relocate = TRUE;
if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
{
@@ -5938,6 +7906,20 @@ ppc64_elf_relocate_section (output_bfd,
case R_PPC64_PLT16_HA:
case R_PPC64_TOC16_HA:
case R_PPC64_SECTOFF_HA:
+ case R_PPC64_TPREL16_HA:
+ case R_PPC64_DTPREL16_HA:
+ case R_PPC64_GOT_TLSGD16_HA:
+ case R_PPC64_GOT_TLSLD16_HA:
+ case R_PPC64_GOT_TPREL16_HA:
+ case R_PPC64_GOT_DTPREL16_HA:
+ case R_PPC64_TPREL16_HIGHER:
+ case R_PPC64_TPREL16_HIGHERA:
+ case R_PPC64_TPREL16_HIGHEST:
+ case R_PPC64_TPREL16_HIGHESTA:
+ case R_PPC64_DTPREL16_HIGHER:
+ case R_PPC64_DTPREL16_HIGHERA:
+ case R_PPC64_DTPREL16_HIGHEST:
+ case R_PPC64_DTPREL16_HIGHESTA:
/* It's just possible that this symbol is a weak symbol
that's not actually defined anywhere. In that case,
'sec' would be NULL, and we should leave the symbol
@@ -5958,6 +7940,14 @@ ppc64_elf_relocate_section (output_bfd,
case R_PPC64_TOC16_LO_DS:
case R_PPC64_PLTGOT16_DS:
case R_PPC64_PLTGOT16_LO_DS:
+ case R_PPC64_GOT_TPREL16_DS:
+ case R_PPC64_GOT_TPREL16_LO_DS:
+ case R_PPC64_GOT_DTPREL16_DS:
+ case R_PPC64_GOT_DTPREL16_LO_DS:
+ case R_PPC64_TPREL16_DS:
+ case R_PPC64_TPREL16_LO_DS:
+ case R_PPC64_DTPREL16_DS:
+ case R_PPC64_DTPREL16_LO_DS:
if (((relocation + addend) & 3) != 0)
{
(*_bfd_error_handler)
@@ -5982,7 +7972,7 @@ ppc64_elf_relocate_section (output_bfd,
branch_check:
/* If the branch is out of reach, then redirect the
call to the local stub for this function. */
- from = (offset
+ from = (rel->r_offset
+ input_section->output_offset
+ input_section->output_section->vma);
if (relocation + addend - from + max_br_offset >= 2 * max_br_offset
@@ -6019,7 +8009,7 @@ ppc64_elf_relocate_section (output_bfd,
input_bfd,
input_section,
contents,
- offset,
+ rel->r_offset,
relocation,
addend);
@@ -6045,13 +8035,9 @@ ppc64_elf_relocate_section (output_bfd,
}
else
{
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
+ name = bfd_elf_local_sym_name (input_bfd, sym);
if (name == NULL)
continue;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, sec);
}
if (r == bfd_reloc_overflow)
@@ -6060,7 +8046,7 @@ ppc64_elf_relocate_section (output_bfd,
continue;
if (!((*info->callbacks->reloc_overflow)
(info, name, ppc64_elf_howto_table[(int) r_type]->name,
- rel->r_addend, input_bfd, input_section, offset)))
+ rel->r_addend, input_bfd, input_section, rel->r_offset)))
return FALSE;
}
else
@@ -6094,79 +8080,37 @@ ppc64_elf_finish_dynamic_symbol (output_
htab = ppc_hash_table (info);
dynobj = htab->elf.dynobj;
- if (h->plt.offset != (bfd_vma) -1
- && ((struct ppc_link_hash_entry *) h)->is_func_descriptor)
- {
- Elf_Internal_Rela rela;
- bfd_byte *loc;
-
- /* This symbol has an entry in the procedure linkage table. Set
- it up. */
-
- if (htab->splt == NULL
- || htab->srelplt == NULL
- || htab->sglink == NULL)
- abort ();
-
- /* Create a JMP_SLOT reloc to inform the dynamic linker to
- fill in the PLT entry. */
-
- rela.r_offset = (htab->splt->output_section->vma
- + htab->splt->output_offset
- + h->plt.offset);
- rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
- rela.r_addend = 0;
-
- loc = htab->srelplt->contents;
- loc += ((h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
- * sizeof (Elf64_External_Rela));
- bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
- }
-
- if (h->got.offset != (bfd_vma) -1)
+ if (((struct ppc_link_hash_entry *) h)->is_func_descriptor)
{
+ struct plt_entry *ent;
Elf_Internal_Rela rela;
bfd_byte *loc;
- /* This symbol has an entry in the global offset table. Set it
- up. */
+ for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+ if (ent->plt.offset != (bfd_vma) -1)
+ {
+ /* This symbol has an entry in the procedure linkage
+ table. Set it up. */
- if (htab->sgot == NULL || htab->srelgot == NULL)
- abort ();
+ if (htab->splt == NULL
+ || htab->srelplt == NULL
+ || htab->sglink == NULL)
+ abort ();
- rela.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + (h->got.offset &~ (bfd_vma) 1));
+ /* Create a JMP_SLOT reloc to inform the dynamic linker to
+ fill in the PLT entry. */
- /* If this is a static link, or it is a -Bsymbolic link and the
- symbol is defined locally or was forced to be local because
- of a version file, we just want to emit a RELATIVE reloc.
- The entry in the global offset table will already have been
- initialized in the relocate_section function. */
- if (info->shared
- && (info->symbolic
- || h->dynindx == -1
- || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
- {
- BFD_ASSERT((h->got.offset & 1) != 0);
- rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
- rela.r_addend = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else
- {
- BFD_ASSERT ((h->got.offset & 1) == 0);
- bfd_put_64 (output_bfd, (bfd_vma) 0,
- htab->sgot->contents + h->got.offset);
- rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_GLOB_DAT);
- rela.r_addend = 0;
- }
+ rela.r_offset = (htab->splt->output_section->vma
+ + htab->splt->output_offset
+ + ent->plt.offset);
+ rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
+ rela.r_addend = ent->addend;
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
- bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+ loc = htab->srelplt->contents;
+ loc += ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
+ * sizeof (Elf64_External_Rela));
+ bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
+ }
}
if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
Index: bfd/elf64-ppc.h
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.h,v
retrieving revision 1.6
diff -u -p -d -r1.6 elf64-ppc.h
--- bfd/elf64-ppc.h 30 Nov 2002 08:39:39 -0000 1.6
+++ bfd/elf64-ppc.h 4 Feb 2003 14:02:14 -0000
@@ -1,5 +1,5 @@
/* PowerPC64-specific support for 64-bit ELF.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002, 2003 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place - Suit
bfd_boolean ppc64_elf_mark_entry_syms
PARAMS ((struct bfd_link_info *));
bfd_boolean ppc64_elf_edit_opd
+ PARAMS ((bfd *, struct bfd_link_info *));
+bfd_boolean ppc64_elf_tls_optimize
PARAMS ((bfd *, struct bfd_link_info *));
bfd_vma ppc64_elf_toc
PARAMS ((bfd *));
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.78
diff -u -p -d -r1.78 reloc.c
--- bfd/reloc.c 24 Jan 2003 23:44:44 -0000 1.78
+++ bfd/reloc.c 4 Feb 2003 14:02:17 -0000
@@ -2393,6 +2393,89 @@ ENUMDOC
Power(rs6000) and PowerPC relocations.
ENUM
+ BFD_RELOC_PPC_TLS
+ENUMX
+ BFD_RELOC_PPC_DTPMOD
+ENUMX
+ BFD_RELOC_PPC_TPREL16
+ENUMX
+ BFD_RELOC_PPC_TPREL16_LO
+ENUMX
+ BFD_RELOC_PPC_TPREL16_HI
+ENUMX
+ BFD_RELOC_PPC_TPREL16_HA
+ENUMX
+ BFD_RELOC_PPC_TPREL
+ENUMX
+ BFD_RELOC_PPC_DTPREL16
+ENUMX
+ BFD_RELOC_PPC_DTPREL16_LO
+ENUMX
+ BFD_RELOC_PPC_DTPREL16_HI
+ENUMX
+ BFD_RELOC_PPC_DTPREL16_HA
+ENUMX
+ BFD_RELOC_PPC_DTPREL
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSGD16
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSGD16_LO
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSGD16_HI
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSGD16_HA
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSLD16
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSLD16_LO
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSLD16_HI
+ENUMX
+ BFD_RELOC_PPC_GOT_TLSLD16_HA
+ENUMX
+ BFD_RELOC_PPC_GOT_TPREL16
+ENUMX
+ BFD_RELOC_PPC_GOT_TPREL16_LO
+ENUMX
+ BFD_RELOC_PPC_GOT_TPREL16_HI
+ENUMX
+ BFD_RELOC_PPC_GOT_TPREL16_HA
+ENUMX
+ BFD_RELOC_PPC_GOT_DTPREL16
+ENUMX
+ BFD_RELOC_PPC_GOT_DTPREL16_LO
+ENUMX
+ BFD_RELOC_PPC_GOT_DTPREL16_HI
+ENUMX
+ BFD_RELOC_PPC_GOT_DTPREL16_HA
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_DS
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_LO_DS
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_HIGHER
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_HIGHERA
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_HIGHEST
+ENUMX
+ BFD_RELOC_PPC64_TPREL16_HIGHESTA
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_DS
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_LO_DS
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_HIGHER
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_HIGHERA
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_HIGHEST
+ENUMX
+ BFD_RELOC_PPC64_DTPREL16_HIGHESTA
+ENUMDOC
+ PowerPC and PowerPC64 thread-local storage relocations.
+
+ENUM
BFD_RELOC_I370_D12
ENUMDOC
IBM 370/390 relocations
Index: gas/config/tc-ppc.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-ppc.c,v
retrieving revision 1.64
diff -u -p -d -r1.64 tc-ppc.c
--- gas/config/tc-ppc.c 23 Jan 2003 12:51:05 -0000 1.64
+++ gas/config/tc-ppc.c 4 Feb 2003 14:02:25 -0000
@@ -1460,60 +1460,94 @@ ppc_elf_suffix (str_p, exp_p)
#define MAP(str,reloc) { str, sizeof (str)-1, reloc }
static const struct map_bfd mapping[] = {
- MAP ("l", (int) BFD_RELOC_LO16),
- MAP ("h", (int) BFD_RELOC_HI16),
- MAP ("ha", (int) BFD_RELOC_HI16_S),
- MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
- MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
- MAP ("got", (int) BFD_RELOC_16_GOTOFF),
- MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
- MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
- MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
- MAP ("fixup", (int) BFD_RELOC_CTOR), /* warning with -mrelocatable */
- MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL),
- MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL),
- MAP ("copy", (int) BFD_RELOC_PPC_COPY),
- MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT),
- MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC),
- MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC),
- MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL),
- MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF),
- MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
- MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
- MAP ("sdarel", (int) BFD_RELOC_GPREL16),
- MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
- MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
- MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
- MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
- MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32),
- MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16),
- MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
- MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
- MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
- MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16),
- MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL),
- MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16),
- MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21),
- MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF),
- MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16),
- MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO),
- MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI),
- MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
- MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD),
- MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA),
- MAP ("xgot", (int) BFD_RELOC_PPC_TOC16),
+ MAP ("l", (int) BFD_RELOC_LO16),
+ MAP ("h", (int) BFD_RELOC_HI16),
+ MAP ("ha", (int) BFD_RELOC_HI16_S),
+ MAP ("brtaken", (int) BFD_RELOC_PPC_B16_BRTAKEN),
+ MAP ("brntaken", (int) BFD_RELOC_PPC_B16_BRNTAKEN),
+ MAP ("got", (int) BFD_RELOC_16_GOTOFF),
+ MAP ("got@l", (int) BFD_RELOC_LO16_GOTOFF),
+ MAP ("got@h", (int) BFD_RELOC_HI16_GOTOFF),
+ MAP ("got@ha", (int) BFD_RELOC_HI16_S_GOTOFF),
+ MAP ("fixup", (int) BFD_RELOC_CTOR),
+ MAP ("plt", (int) BFD_RELOC_24_PLT_PCREL),
+ MAP ("pltrel24", (int) BFD_RELOC_24_PLT_PCREL),
+ MAP ("copy", (int) BFD_RELOC_PPC_COPY),
+ MAP ("globdat", (int) BFD_RELOC_PPC_GLOB_DAT),
+ MAP ("local24pc", (int) BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("local", (int) BFD_RELOC_PPC_LOCAL24PC),
+ MAP ("pltrel", (int) BFD_RELOC_32_PLT_PCREL),
+ MAP ("plt@l", (int) BFD_RELOC_LO16_PLTOFF),
+ MAP ("plt@h", (int) BFD_RELOC_HI16_PLTOFF),
+ MAP ("plt@ha", (int) BFD_RELOC_HI16_S_PLTOFF),
+ MAP ("sdarel", (int) BFD_RELOC_GPREL16),
+ MAP ("sectoff", (int) BFD_RELOC_16_BASEREL),
+ MAP ("sectoff@l", (int) BFD_RELOC_LO16_BASEREL),
+ MAP ("sectoff@h", (int) BFD_RELOC_HI16_BASEREL),
+ MAP ("sectoff@ha", (int) BFD_RELOC_HI16_S_BASEREL),
+ MAP ("naddr", (int) BFD_RELOC_PPC_EMB_NADDR32),
+ MAP ("naddr16", (int) BFD_RELOC_PPC_EMB_NADDR16),
+ MAP ("naddr@l", (int) BFD_RELOC_PPC_EMB_NADDR16_LO),
+ MAP ("naddr@h", (int) BFD_RELOC_PPC_EMB_NADDR16_HI),
+ MAP ("naddr@ha", (int) BFD_RELOC_PPC_EMB_NADDR16_HA),
+ MAP ("sdai16", (int) BFD_RELOC_PPC_EMB_SDAI16),
+ MAP ("sda2rel", (int) BFD_RELOC_PPC_EMB_SDA2REL),
+ MAP ("sda2i16", (int) BFD_RELOC_PPC_EMB_SDA2I16),
+ MAP ("sda21", (int) BFD_RELOC_PPC_EMB_SDA21),
+ MAP ("mrkref", (int) BFD_RELOC_PPC_EMB_MRKREF),
+ MAP ("relsect", (int) BFD_RELOC_PPC_EMB_RELSEC16),
+ MAP ("relsect@l", (int) BFD_RELOC_PPC_EMB_RELST_LO),
+ MAP ("relsect@h", (int) BFD_RELOC_PPC_EMB_RELST_HI),
+ MAP ("relsect@ha", (int) BFD_RELOC_PPC_EMB_RELST_HA),
+ MAP ("bitfld", (int) BFD_RELOC_PPC_EMB_BIT_FLD),
+ MAP ("relsda", (int) BFD_RELOC_PPC_EMB_RELSDA),
+ MAP ("xgot", (int) BFD_RELOC_PPC_TOC16),
+ MAP ("tls", (int) BFD_RELOC_PPC_TLS),
+ MAP ("dtpmod", (int) BFD_RELOC_PPC_DTPMOD),
+ MAP ("dtprel", (int) BFD_RELOC_PPC_DTPREL),
+ MAP ("dtprel@l", (int) BFD_RELOC_PPC_DTPREL16_LO),
+ MAP ("dtprel@h", (int) BFD_RELOC_PPC_DTPREL16_HI),
+ MAP ("dtprel@ha", (int) BFD_RELOC_PPC_DTPREL16_HA),
+ MAP ("tprel", (int) BFD_RELOC_PPC_TPREL),
+ MAP ("tprel@l", (int) BFD_RELOC_PPC_TPREL16_LO),
+ MAP ("tprel@h", (int) BFD_RELOC_PPC_TPREL16_HI),
+ MAP ("tprel@ha", (int) BFD_RELOC_PPC_TPREL16_HA),
+ MAP ("got@tlsgd", (int) BFD_RELOC_PPC_GOT_TLSGD16),
+ MAP ("got@tlsgd@l", (int) BFD_RELOC_PPC_GOT_TLSGD16_LO),
+ MAP ("got@tlsgd@h", (int) BFD_RELOC_PPC_GOT_TLSGD16_HI),
+ MAP ("got@tlsgd@ha", (int) BFD_RELOC_PPC_GOT_TLSGD16_HA),
+ MAP ("got@tlsld", (int) BFD_RELOC_PPC_GOT_TLSLD16),
+ MAP ("got@tlsld@l", (int) BFD_RELOC_PPC_GOT_TLSLD16_LO),
+ MAP ("got@tlsld@h", (int) BFD_RELOC_PPC_GOT_TLSLD16_HI),
+ MAP ("got@tlsld@ha", (int) BFD_RELOC_PPC_GOT_TLSLD16_HA),
+ MAP ("got@dtprel", (int) BFD_RELOC_PPC_GOT_DTPREL16),
+ MAP ("got@dtprel@l", (int) BFD_RELOC_PPC_GOT_DTPREL16_LO),
+ MAP ("got@dtprel@h", (int) BFD_RELOC_PPC_GOT_DTPREL16_HI),
+ MAP ("got@dtprel@ha", (int) BFD_RELOC_PPC_GOT_DTPREL16_HA),
+ MAP ("got@tprel", (int) BFD_RELOC_PPC_GOT_TPREL16),
+ MAP ("got@tprel@l", (int) BFD_RELOC_PPC_GOT_TPREL16_LO),
+ MAP ("got@tprel@h", (int) BFD_RELOC_PPC_GOT_TPREL16_HI),
+ MAP ("got@tprel@ha", (int) BFD_RELOC_PPC_GOT_TPREL16_HA),
/* The following are only valid for ppc64. Negative values are
used instead of a flag. */
- MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
- MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
- MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
- MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
- MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
- MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
- MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
- MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
- MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
- { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
+ MAP ("higher", - (int) BFD_RELOC_PPC64_HIGHER),
+ MAP ("highera", - (int) BFD_RELOC_PPC64_HIGHER_S),
+ MAP ("highest", - (int) BFD_RELOC_PPC64_HIGHEST),
+ MAP ("highesta", - (int) BFD_RELOC_PPC64_HIGHEST_S),
+ MAP ("tocbase", - (int) BFD_RELOC_PPC64_TOC),
+ MAP ("toc", - (int) BFD_RELOC_PPC_TOC16),
+ MAP ("toc@l", - (int) BFD_RELOC_PPC64_TOC16_LO),
+ MAP ("toc@h", - (int) BFD_RELOC_PPC64_TOC16_HI),
+ MAP ("toc@ha", - (int) BFD_RELOC_PPC64_TOC16_HA),
+ MAP ("dtprel@higher", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHER),
+ MAP ("dtprel@highera", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHERA),
+ MAP ("dtprel@highest", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHEST),
+ MAP ("dtprel@highesta", - (int) BFD_RELOC_PPC64_DTPREL16_HIGHESTA),
+ MAP ("tprel@higher", - (int) BFD_RELOC_PPC64_TPREL16_HIGHER),
+ MAP ("tprel@highera", - (int) BFD_RELOC_PPC64_TPREL16_HIGHERA),
+ MAP ("tprel@highest", - (int) BFD_RELOC_PPC64_TPREL16_HIGHEST),
+ MAP ("tprel@highesta", - (int) BFD_RELOC_PPC64_TPREL16_HIGHESTA),
+ { (char *) 0, 0, (int) BFD_RELOC_UNUSED }
};
if (*str++ != '@')
@@ -1545,29 +1579,32 @@ ppc_elf_suffix (str_p, exp_p)
reloc = -reloc;
}
- if (exp_p->X_add_number != 0
- && (reloc == (int) BFD_RELOC_16_GOTOFF
- || reloc == (int) BFD_RELOC_LO16_GOTOFF
- || reloc == (int) BFD_RELOC_HI16_GOTOFF
- || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
- as_warn (_("identifier+constant@got means identifier@got+constant"));
-
- /* Now check for identifier@suffix+constant. */
- if (*str == '-' || *str == '+')
+ if (!ppc_obj64)
{
- char *orig_line = input_line_pointer;
- expressionS new_exp;
+ if (exp_p->X_add_number != 0
+ && (reloc == (int) BFD_RELOC_16_GOTOFF
+ || reloc == (int) BFD_RELOC_LO16_GOTOFF
+ || reloc == (int) BFD_RELOC_HI16_GOTOFF
+ || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
+ as_warn (_("identifier+constant@got means identifier@got+constant"));
- input_line_pointer = str;
- expression (&new_exp);
- if (new_exp.X_op == O_constant)
+ /* Now check for identifier@suffix+constant. */
+ if (*str == '-' || *str == '+')
{
- exp_p->X_add_number += new_exp.X_add_number;
- str = input_line_pointer;
- }
+ char *orig_line = input_line_pointer;
+ expressionS new_exp;
- if (&input_line_pointer != str_p)
- input_line_pointer = orig_line;
+ input_line_pointer = str;
+ expression (&new_exp);
+ if (new_exp.X_op == O_constant)
+ {
+ exp_p->X_add_number += new_exp.X_add_number;
+ str = input_line_pointer;
+ }
+
+ if (&input_line_pointer != str_p)
+ input_line_pointer = orig_line;
+ }
}
*str_p = str;
@@ -2363,6 +2400,25 @@ md_assemble (str)
#ifdef OBJ_ELF
else if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_UNUSED)
{
+ /* Some TLS tweaks. */
+ switch (reloc)
+ {
+ default:
+ break;
+ case BFD_RELOC_PPC_TLS:
+ insn = ppc_insert_operand (insn, operand, ppc_obj64 ? 13 : 2,
+ (char *) NULL, 0);
+ break;
+ /* We'll only use the 32 (or 64) bit form of these relocations
+ in constants. Instructions get the 16 bit form. */
+ case BFD_RELOC_PPC_DTPREL:
+ reloc = BFD_RELOC_PPC_DTPREL16;
+ break;
+ case BFD_RELOC_PPC_TPREL:
+ reloc = BFD_RELOC_PPC_TPREL16;
+ break;
+ }
+
/* For the absolute forms of branches, convert the PC
relative form back into the absolute. */
if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
@@ -2424,6 +2480,23 @@ md_assemble (str)
case BFD_RELOC_PPC64_PLTGOT16_LO:
reloc = BFD_RELOC_PPC64_PLTGOT16_LO_DS;
break;
+ case BFD_RELOC_PPC_DTPREL16:
+ reloc = BFD_RELOC_PPC64_DTPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_DTPREL16_LO:
+ reloc = BFD_RELOC_PPC64_DTPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_TPREL16:
+ reloc = BFD_RELOC_PPC64_TPREL16_DS;
+ break;
+ case BFD_RELOC_PPC_TPREL16_LO:
+ reloc = BFD_RELOC_PPC64_TPREL16_LO_DS;
+ break;
+ case BFD_RELOC_PPC_GOT_DTPREL16:
+ case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+ case BFD_RELOC_PPC_GOT_TPREL16:
+ case BFD_RELOC_PPC_GOT_TPREL16_LO:
+ break;
default:
as_bad (_("unsupported relocation for DS offset field"));
break;
@@ -5283,6 +5356,10 @@ ppc_force_relocation (fix)
break;
}
+ if (fix->fx_r_type >= BFD_RELOC_PPC_TLS
+ && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
+ return 1;
+
return generic_force_reloc (fix);
}
@@ -5297,6 +5374,8 @@ ppc_fix_adjustable (fix)
&& fix->fx_r_type != BFD_RELOC_GPREL16
&& fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
&& fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
+ && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
+ && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA)
&& (fix->fx_pcrel
|| (fix->fx_subsy != NULL
&& (S_GET_SEGMENT (fix->fx_subsy)
@@ -5632,6 +5711,48 @@ md_apply_fix3 (fixP, valP, seg)
else
bfd_putl16 ((bfd_vma) val, where);
}
+ break;
+
+ case BFD_RELOC_PPC_TLS:
+ case BFD_RELOC_PPC_DTPMOD:
+ case BFD_RELOC_PPC_TPREL16:
+ case BFD_RELOC_PPC_TPREL16_LO:
+ case BFD_RELOC_PPC_TPREL16_HI:
+ case BFD_RELOC_PPC_TPREL16_HA:
+ case BFD_RELOC_PPC_TPREL:
+ case BFD_RELOC_PPC_DTPREL16:
+ case BFD_RELOC_PPC_DTPREL16_LO:
+ case BFD_RELOC_PPC_DTPREL16_HI:
+ case BFD_RELOC_PPC_DTPREL16_HA:
+ case BFD_RELOC_PPC_DTPREL:
+ case BFD_RELOC_PPC_GOT_TLSGD16:
+ case BFD_RELOC_PPC_GOT_TLSGD16_LO:
+ case BFD_RELOC_PPC_GOT_TLSGD16_HI:
+ case BFD_RELOC_PPC_GOT_TLSGD16_HA:
+ case BFD_RELOC_PPC_GOT_TLSLD16:
+ case BFD_RELOC_PPC_GOT_TLSLD16_LO:
+ case BFD_RELOC_PPC_GOT_TLSLD16_HI:
+ case BFD_RELOC_PPC_GOT_TLSLD16_HA:
+ case BFD_RELOC_PPC_GOT_TPREL16:
+ case BFD_RELOC_PPC_GOT_TPREL16_LO:
+ case BFD_RELOC_PPC_GOT_TPREL16_HI:
+ case BFD_RELOC_PPC_GOT_TPREL16_HA:
+ case BFD_RELOC_PPC_GOT_DTPREL16:
+ case BFD_RELOC_PPC_GOT_DTPREL16_LO:
+ case BFD_RELOC_PPC_GOT_DTPREL16_HI:
+ case BFD_RELOC_PPC_GOT_DTPREL16_HA:
+ case BFD_RELOC_PPC64_TPREL16_DS:
+ case BFD_RELOC_PPC64_TPREL16_LO_DS:
+ case BFD_RELOC_PPC64_TPREL16_HIGHER:
+ case BFD_RELOC_PPC64_TPREL16_HIGHERA:
+ case BFD_RELOC_PPC64_TPREL16_HIGHEST:
+ case BFD_RELOC_PPC64_TPREL16_HIGHESTA:
+ case BFD_RELOC_PPC64_DTPREL16_DS:
+ case BFD_RELOC_PPC64_DTPREL16_LO_DS:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHER:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHERA:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHEST:
+ case BFD_RELOC_PPC64_DTPREL16_HIGHESTA:
break;
#endif
/* Because SDA21 modifies the register field, the size is set to 4
Index: ld/emultempl/ppc64elf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/ppc64elf.em,v
retrieving revision 1.11
diff -u -p -d -r1.11 ppc64elf.em
--- ld/emultempl/ppc64elf.em 30 Nov 2002 08:39:46 -0000 1.11
+++ ld/emultempl/ppc64elf.em 4 Feb 2003 14:02:37 -0000
@@ -1,5 +1,5 @@
# This shell script emits a C file. -*- C -*-
-# Copyright 2002 Free Software Foundation, Inc.
+# Copyright 2002, 2003 Free Software Foundation, Inc.
#
# This file is part of GLD, the Gnu Linker.
#
@@ -101,7 +101,20 @@ ppc_before_allocation ()
return;
}
+ /* Size the sections. This is premature, but we want to know the
+ TLS segment layout so that certain optimizations can be done. */
+ lang_size_sections (stat_ptr->head, abs_output_section,
+ &stat_ptr->head, 0, (bfd_vma) 0, NULL);
+
+ if (!ppc64_elf_tls_optimize (output_bfd, &link_info))
+ {
+ einfo ("%X%P: TLS problem %E\n");
+ return;
+ }
+
gld${EMULATION_NAME}_before_allocation ();
+
+ lang_reset_memory_regions ();
}
struct hook_stub_info
Index: ld/testsuite/ld-powerpc/powerpc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-powerpc/powerpc.exp,v
retrieving revision 1.4
diff -u -p -d -r1.4 powerpc.exp
--- ld/testsuite/ld-powerpc/powerpc.exp 3 Dec 2002 18:24:33 -0000 1.4
+++ ld/testsuite/ld-powerpc/powerpc.exp 4 Feb 2003 14:02:37 -0000
@@ -1,5 +1,5 @@
# Expect script for ld-powerpc tests
-# Copyright (C) 2002 Free Software Foundation
+# Copyright 2002, 2003 Free Software Foundation
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,15 +20,26 @@ if { ![istarget "powerpc*-*-*"] } {
return
}
-# powerpc 32 bit ELF only at the moment.
+# powerpc ELF only at the moment.
if { [istarget "*-*-macos*"] || [istarget "*-*-netware*"]
|| [istarget "*-*-pe"] || [istarget "*-*-winnt*"]
|| [istarget "*-*-cygwin*"] || [istarget "*-*-aix*"]
- || [istarget "*-*-beos*"] || [istarget "powerpc64*-*-*"] } {
+ || [istarget "*-*-beos*"] } {
return
}
+proc supports_ppc64 { } {
+ global ld
+
+ catch "exec $ld --help | grep emulations" tmp
+ if [ string match "*elf64ppc*" $tmp ] then {
+ return 1
+ } else {
+ return 0
+ }
+}
+
# List contains test-items with 3 items followed by 2 lists:
# 0:name 1:ld options 2:assembler options
# 3:filenames of assembler files 4: action and options. 5: name of output file
@@ -39,10 +50,45 @@ if { [istarget "*-*-macos*"] || [istarge
# readelf: Apply readelf options on result. Compare with regex (last arg).
set ppcelftests {
- {"Reloc section order" "-shared -z nocombreloc" "" {reloc.s}
+ {"Reloc section order" "-melf32ppc -shared -z nocombreloc" "-a32" {reloc.s}
{{objdump -hw reloc.d}} "reloc.so"}
- {"APUinfo section processing" "" "-me500" {apuinfo1.s apuinfo2.s}
+ {"APUinfo section processing" "-melf32ppc"
+ "-a32 -me500" {apuinfo1.s apuinfo2.s}
{{readelf -x5 apuinfo.rd}} "apuinfo"}
}
+set ppc64elftests {
+ {"TLS static exec" "-melf64ppc" "-a64" {tls.s tlslib.s}
+ {{objdump -dr tls.d} {objdump -sj.got tls.g} {objdump -sj.tdata tls.t}}
+ "tls"}
+ {"TLS helper shared library" "-shared -melf64ppc tmpdir/tlslib.o" "" {}
+ {} "libtlslib.so"}
+ {"TLS dynamic exec" "-melf64ppc tmpdir/tls.o tmpdir/libtlslib.so" "" {}
+ {{readelf -WSsrl tlsexe.r} {objdump -dr tlsexe.d}
+ {objdump -sj.got tlsexe.g} {objdump -sj.tdata tlsexe.t}}
+ "tlsexe"}
+ {"TLS shared" "-shared -melf64ppc tmpdir/tls.o" "" {}
+ {{readelf -WSsrl tlsso.r} {objdump -dr tlsso.d}
+ {objdump -sj.got tlsso.g} {objdump -sj.tdata tlsso.t}}
+ "tls.so"}
+ {"TLSTOC static exec" "-melf64ppc tmpdir/tlslib.o " "-a64" {tlstoc.s}
+ {{objdump -dr tlstoc.d} {objdump -sj.toc tlstoc.g}
+ {objdump -sj.tdata tlstoc.t}}
+ "tlstoc"}
+ {"TLSTOC dynamic exec" "-melf64ppc tmpdir/tlstoc.o tmpdir/libtlslib.so"
+ "" {}
+ {{readelf -WSsrl tlsexetoc.r} {objdump -dr tlsexetoc.d}
+ {objdump -sj.toc tlsexetoc.g} {objdump -sj.tdata tlsexetoc.t}}
+ "tlsexetoc"}
+ {"TLSTOC shared" "-shared -melf64ppc tmpdir/tlstoc.o" "" {}
+ {{readelf -WSsrl tlstocso.r} {objdump -dr tlstocso.d}
+ {objdump -sj.toc tlstocso.g} {objdump -sj.tdata tlstocso.t}}
+ "tlstoc.so"}
+}
+
+
run_ld_link_tests $ppcelftests
+
+if [ supports_ppc64 ] then {
+ run_ld_link_tests $ppc64elftests
+}
Index: ld/testsuite/ld-powerpc/tls.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tls.d
diff -N ld/testsuite/ld-powerpc/tls.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tls.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,53 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+0+100000e8 <_start>:
+ 100000e8: 3c 6d 00 00 addis r3,r13,0
+ 100000ec: 60 00 00 00 nop
+ 100000f0: 38 63 90 78 addi r3,r3,-28552
+ 100000f4: 3c 6d 00 00 addis r3,r13,0
+ 100000f8: 60 00 00 00 nop
+ 100000fc: 38 63 10 00 addi r3,r3,4096
+ 10000100: 3c 6d 00 00 addis r3,r13,0
+ 10000104: 60 00 00 00 nop
+ 10000108: 38 63 90 40 addi r3,r3,-28608
+ 1000010c: 3c 6d 00 00 addis r3,r13,0
+ 10000110: 60 00 00 00 nop
+ 10000114: 38 63 10 00 addi r3,r3,4096
+ 10000118: 39 23 80 48 addi r9,r3,-32696
+ 1000011c: 3d 23 00 00 addis r9,r3,0
+ 10000120: 81 49 80 50 lwz r10,-32688\(r9\)
+ 10000124: e9 22 80 10 ld r9,-32752\(r2\)
+ 10000128: 7d 49 18 2a ldx r10,r9,r3
+ 1000012c: 3d 2d 00 00 addis r9,r13,0
+ 10000130: a1 49 90 60 lhz r10,-28576\(r9\)
+ 10000134: 89 4d 90 68 lbz r10,-28568\(r13\)
+ 10000138: 3d 2d 00 00 addis r9,r13,0
+ 1000013c: 99 49 90 70 stb r10,-28560\(r9\)
+ 10000140: 3c 6d 00 00 addis r3,r13,0
+ 10000144: 60 00 00 00 nop
+ 10000148: 38 63 90 00 addi r3,r3,-28672
+ 1000014c: 3c 6d 00 00 addis r3,r13,0
+ 10000150: 60 00 00 00 nop
+ 10000154: 38 63 10 00 addi r3,r3,4096
+ 10000158: f9 43 80 08 std r10,-32760\(r3\)
+ 1000015c: 3d 23 00 00 addis r9,r3,0
+ 10000160: 91 49 80 10 stw r10,-32752\(r9\)
+ 10000164: e9 22 80 08 ld r9,-32760\(r2\)
+ 10000168: 7d 49 19 2a stdx r10,r9,r3
+ 1000016c: 3d 2d 00 00 addis r9,r13,0
+ 10000170: b1 49 90 60 sth r10,-28576\(r9\)
+ 10000174: e9 4d 90 2a lwa r10,-28632\(r13\)
+ 10000178: 3d 2d 00 00 addis r9,r13,0
+ 1000017c: a9 49 90 30 lha r10,-28624\(r9\)
+
+0+10000180 <\.__tls_get_addr>:
+ 10000180: 4e 80 00 20 blr
Index: ld/testsuite/ld-powerpc/tls.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tls.g
diff -N ld/testsuite/ld-powerpc/tls.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tls.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,12 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -sj.got
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.got:
+ 100101e0 00000000 100181e0 ffffffff ffff8018 .*
+ 100101f0 ffffffff ffff8058 .*
Index: ld/testsuite/ld-powerpc/tls.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/tls.s
diff -N ld/testsuite/ld-powerpc/tls.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tls.s 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,92 @@
+ .section ".tbss","awT",@nobits
+ .global _start,gd0,ld0,ld1,ld2,ie0,le0,le1
+ .align 3
+gd0: .space 8
+ld0: .space 8
+ld1: .space 8
+ld2: .space 8
+ie0: .space 8
+le0: .space 8
+le1: .space 8
+
+ .section ".tdata","awT",@progbits
+ .align 3
+gd4: .quad 0x123456789abcdef0
+ld4: .quad 0x23456789abcdef01
+ld5: .quad 0x3456789abcdef012
+ld6: .quad 0x456789abcdef0123
+ie4: .quad 0x56789abcdef01234
+le4: .quad 0x6789abcdef012345
+le5: .quad 0x789abcdef0123456
+
+ .text
+_start:
+#extern syms
+#GD
+ addi 3,2,gd@got@tlsgd #R_PPC64_GOT_TLSGD16 gd
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+#LD
+ addi 3,2,ld@got@tlsld #R_PPC64_GOT_TLSLD16 ld
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+#global syms
+#GD
+ addi 3,2,gd0@got@tlsgd #R_PPC64_GOT_TLSGD16 gd0
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+#LD
+ addi 3,2,ld0@got@tlsld #R_PPC64_GOT_TLSLD16 ld0
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+ addi 9,3,ld0@dtprel #R_PPC64_DTPREL16 ld0
+
+ addis 9,3,ld1@dtprel@ha #R_PPC64_DTPREL16_HA ld1
+ lwz 10,ld1@dtprel@l(9) #R_PPC64_DTPREL16_LO ld1
+
+ ld 9,ld2@got@dtprel(2) #R_PPC64_GOT_DTPREL16_DS ld2
+ ldx 10,9,3
+
+#IE
+ ld 9,ie0@got@tprel(2) #R_PPC64_GOT_TPREL16_DS ie0
+ lhzx 10,9,ie0@tls #R_PPC64_TLS ie0
+
+#LE
+ lbz 10,le0@tprel(13) #R_PPC64_TPREL16 le0
+
+ addis 9,13,le1@tprel@ha #R_PPC64_TPREL16_HA le1
+ stb 10,le1@tprel@l(9) #R_PPC64_TPREL16_LO le1
+
+#local syms
+#GD
+ addi 3,2,gd4@got@tlsgd #R_PPC64_GOT_TLSGD16 gd4
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+#LD
+ addi 3,2,ld4@got@tlsld #R_PPC64_GOT_TLSLD16 ld4
+ bl .__tls_get_addr #R_PPC64_REL24 .__tls_get_addr
+ nop
+
+ std 10,ld4@dtprel(3) #R_PPC64_DTPREL16_DS ld4
+
+ addis 9,3,ld5@dtprel@ha #R_PPC64_DTPREL16_HA ld5
+ stw 10,ld5@dtprel@l(9) #R_PPC64_DTPREL16_LO ld5
+
+ ld 9,ld6@got@dtprel(2) #R_PPC64_GOT_DTPREL16_DS ld6
+ stdx 10,9,3
+
+#IE
+ ld 9,ie0@got@tprel(2) #R_PPC64_GOT_TPREL16_DS ie4
+ sthx 10,9,ie0@tls #R_PPC64_TLS ie4
+
+#LE
+ lwa 10,le4@tprel(13) #R_PPC64_TPREL16 le4
+
+ addis 9,13,le5@tprel@ha #R_PPC64_TPREL16_HA le5
+ lha 10,le5@tprel@l(9) #R_PPC64_TPREL16_LO le5
+
Index: ld/testsuite/ld-powerpc/tls.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tls.t
diff -N ld/testsuite/ld-powerpc/tls.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tls.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,14 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 10010188 12345678 9abcdef0 23456789 abcdef01 .*
+ 10010198 3456789a bcdef012 456789ab cdef0123 .*
+ 100101a8 56789abc def01234 6789abcd ef012345 .*
+ 100101b8 789abcde f0123456 00c0ffee .*
Index: ld/testsuite/ld-powerpc/tlsexe.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexe.d
diff -N ld/testsuite/ld-powerpc/tlsexe.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexe.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,49 @@
+#source: tls.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+0+10000378 <_start>:
+ 10000378: e8 62 80 10 ld r3,-32752\(r2\)
+ 1000037c: 60 00 00 00 nop
+ 10000380: 7c 63 6a 14 add r3,r3,r13
+ 10000384: e8 62 80 18 ld r3,-32744\(r2\)
+ 10000388: 60 00 00 00 nop
+ 1000038c: 7c 63 6a 14 add r3,r3,r13
+ 10000390: 3c 6d 00 00 addis r3,r13,0
+ 10000394: 60 00 00 00 nop
+ 10000398: 38 63 90 38 addi r3,r3,-28616
+ 1000039c: 3c 6d 00 00 addis r3,r13,0
+ 100003a0: 60 00 00 00 nop
+ 100003a4: 38 63 10 00 addi r3,r3,4096
+ 100003a8: 39 23 80 40 addi r9,r3,-32704
+ 100003ac: 3d 23 00 00 addis r9,r3,0
+ 100003b0: 81 49 80 48 lwz r10,-32696\(r9\)
+ 100003b4: e9 22 80 20 ld r9,-32736\(r2\)
+ 100003b8: 7d 49 18 2a ldx r10,r9,r3
+ 100003bc: 3d 2d 00 00 addis r9,r13,0
+ 100003c0: a1 49 90 58 lhz r10,-28584\(r9\)
+ 100003c4: 89 4d 90 60 lbz r10,-28576\(r13\)
+ 100003c8: 3d 2d 00 00 addis r9,r13,0
+ 100003cc: 99 49 90 68 stb r10,-28568\(r9\)
+ 100003d0: 3c 6d 00 00 addis r3,r13,0
+ 100003d4: 60 00 00 00 nop
+ 100003d8: 38 63 90 00 addi r3,r3,-28672
+ 100003dc: 3c 6d 00 00 addis r3,r13,0
+ 100003e0: 60 00 00 00 nop
+ 100003e4: 38 63 10 00 addi r3,r3,4096
+ 100003e8: f9 43 80 08 std r10,-32760\(r3\)
+ 100003ec: 3d 23 00 00 addis r9,r3,0
+ 100003f0: 91 49 80 10 stw r10,-32752\(r9\)
+ 100003f4: e9 22 80 08 ld r9,-32760\(r2\)
+ 100003f8: 7d 49 19 2a stdx r10,r9,r3
+ 100003fc: 3d 2d 00 00 addis r9,r13,0
+ 10000400: b1 49 90 58 sth r10,-28584\(r9\)
+ 10000404: e9 4d 90 2a lwa r10,-28632\(r13\)
+ 10000408: 3d 2d 00 00 addis r9,r13,0
+ 1000040c: a9 49 90 30 lha r10,-28624\(r9\)
Index: ld/testsuite/ld-powerpc/tlsexe.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexe.g
diff -N ld/testsuite/ld-powerpc/tlsexe.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexe.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,12 @@
+#source: tls.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.got:
+ 10010548 00000000 10018548 ffffffff ffff8018 .*
+ 10010558 00000000 00000000 00000000 00000000 .*
+ 10010568 00000000 00000000 .*
Index: ld/testsuite/ld-powerpc/tlsexe.r
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexe.r
diff -N ld/testsuite/ld-powerpc/tlsexe.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexe.r 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,120 @@
+#source: tls.s
+#source: tlslib.s
+#as: -a64
+#ld: -shared -melf64ppc
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are 20 section headers.*
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[ 1\] \.interp +PROGBITS +0+10000190 0+190 0+11 0+ +A +0 +0 +1
+ +\[ 2\] \.hash +HASH +0+100001a8 0+1a8 0+3c 04 +A +3 +0 +8
+ +\[ 3\] \.dynsym +DYNSYM +0+100001e8 0+1e8 0+f0 18 +A +4 +1 +8
+ +\[ 4\] \.dynstr +STRTAB +0+100002d8 0+2d8 0+51 0+ +A +0 +0 +1
+ +\[ 5\] \.rela\.dyn +RELA +0+10000330 0+330 0+48 18 +A +3 +0 +8
+ +\[ 6\] \.text +PROGBITS +0+10000378 0+378 0+98 0+ +AX +0 +0 +4
+ +\[ 7\] \.data +PROGBITS +0+10010410 0+410 0+ 0+ +WA +0 +0 +1
+ +\[ 8\] \.branch_lt +PROGBITS +0+10010410 0+410 0+ 0+ +WA +0 +0 +8
+ +\[ 9\] \.tdata +PROGBITS +0+10010410 0+410 0+38 0+ WAT +0 +0 +8
+ +\[10\] \.tbss +NOBITS +0+10010448 0+448 0+38 0+ WAT +0 +0 +8
+ +\[11\] \.dynamic +DYNAMIC +0+10010448 0+448 0+100 10 +WA +4 +0 +8
+ +\[12\] \.ctors +PROGBITS +0+10010548 0+570 0+ 0+ +W +0 +0 +1
+ +\[13\] \.dtors +PROGBITS +0+10010548 0+570 0+ 0+ +W +0 +0 +1
+ +\[14\] \.got +PROGBITS +0+10010548 0+548 0+28 08 +WA +0 +0 +8
+ +\[15\] \.sbss +PROGBITS +0+10010570 0+570 0+ 0+ +W +0 +0 +1
+ +\[16\] \.bss +NOBITS +0+10010570 0+570 0+ 0+ +WA +0 +0 +1
+ +\[17\] \.shstrtab +STRTAB +0+ 0+570 0+8e 0+ +0 +0 +1
+ +\[18\] \.symtab +SYMTAB +0+ 0+b00 0+408 18 +19 +1b +8
+ +\[19\] \.strtab +STRTAB +0+ 0+f08 0+7d 0+ +0 +0 +1
+#...
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x10000378
+There are 6 program headers.*
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +PHDR +0x0+40 0x0+10000040 0x0+10000040 0x0+150 0x0+150 R E 0x8
+ +INTERP +0x0+190 0x0+10000190 0x0+10000190 0x0+11 0x0+11 R +0x1
+ +\[Requesting program interpreter: .*\]
+ +LOAD +0x0+ 0x0+10000000 0x0+10000000 0x0+410 0x0+410 R E 0x10000
+ +LOAD +0x0+410 0x0+10010410 0x0+10010410 0x0+160 0x0+160 RW +0x10000
+ +DYNAMIC +0x0+448 0x0+10010448 0x0+10010448 0x0+100 0x0+100 RW +0x8
+ +TLS +0x0+410 0x0+10010410 0x0+10010410 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +00 +
+ +01 +\.interp
+ +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.text
+ +03 +\.tdata \.tbss \.dynamic \.got
+ +04 +\.tbss \.dynamic
+ +05 +\.tdata \.tbss
+
+Relocation section '\.rela\.dyn' at offset .* contains 3 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+10010558 +0+200000049 R_PPC64_TPREL64 +0+ gd \+ 0
+0+10010560 +0+400000049 R_PPC64_TPREL64 +0+ ld \+ 0
+0+10010568 +0+60000004e R_PPC64_DTPREL64 +0+50 ld2 \+ 0
+
+Symbol table '\.dynsym' contains 10 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+10010448 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +2: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
+ +3: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND \.__tls_get_addr
+ +4: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
+ +5: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +6: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +7: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +8: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +9: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+
+Symbol table '\.symtab' contains 43 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+10000190 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+100001a8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+100001e8 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+100002d8 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+10000330 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+10000378 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+10010410 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+10010410 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+10010410 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+10010448 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+10010448 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+10010548 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+10010548 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+10010548 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+10010570 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+10010570 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+ +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+ +0 SECTION LOCAL +DEFAULT +18
+ +19: 0+ +0 SECTION LOCAL +DEFAULT +19
+ +20: 0+ +0 TLS +LOCAL +DEFAULT +9 gd4
+ +21: 0+8 +0 TLS +LOCAL +DEFAULT +9 ld4
+ +22: 0+10 +0 TLS +LOCAL +DEFAULT +9 ld5
+ +23: 0+18 +0 TLS +LOCAL +DEFAULT +9 ld6
+ +24: 0+20 +0 TLS +LOCAL +DEFAULT +9 ie4
+ +25: 0+28 +0 TLS +LOCAL +DEFAULT +9 le4
+ +26: 0+30 +0 TLS +LOCAL +DEFAULT +9 le5
+ +27: 0+10010448 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +28: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
+ +29: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +30: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND \.__tls_get_addr
+ +31: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +32: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +33: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
+ +34: 0+10000378 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +35: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +36: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +37: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +38: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +39: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +40: 0+10010570 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +41: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +42: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
Index: ld/testsuite/ld-powerpc/tlsexe.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexe.t
diff -N ld/testsuite/ld-powerpc/tlsexe.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexe.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,13 @@
+#source: tls.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 10010410 12345678 9abcdef0 23456789 abcdef01 .*
+ 10010420 3456789a bcdef012 456789ab cdef0123 .*
+ 10010430 56789abc def01234 6789abcd ef012345 .*
+ 10010440 789abcde f0123456 .*
Index: ld/testsuite/ld-powerpc/tlsexetoc.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexetoc.d
diff -N ld/testsuite/ld-powerpc/tlsexetoc.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexetoc.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,33 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+0+10000338 <_start>:
+ 10000338: e8 62 80 08 ld r3,-32760\(r2\)
+ 1000033c: 60 00 00 00 nop
+ 10000340: 7c 63 6a 14 add r3,r3,r13
+ 10000344: e8 62 80 18 ld r3,-32744\(r2\)
+ 10000348: 60 00 00 00 nop
+ 1000034c: 7c 63 6a 14 add r3,r3,r13
+ 10000350: 3c 6d 00 00 addis r3,r13,0
+ 10000354: 60 00 00 00 nop
+ 10000358: 38 63 91 40 addi r3,r3,-28352
+ 1000035c: 3c 6d 00 00 addis r3,r13,0
+ 10000360: 60 00 00 00 nop
+ 10000364: 38 63 10 00 addi r3,r3,4096
+ 10000368: 39 23 80 40 addi r9,r3,-32704
+ 1000036c: 3d 23 00 00 addis r9,r3,0
+ 10000370: 81 49 80 48 lwz r10,-32696\(r9\)
+ 10000374: 3d 2d 00 00 addis r9,r13,0
+ 10000378: 7d 49 18 2a ldx r10,r9,r3
+ 1000037c: 3d 2d 00 00 addis r9,r13,0
+ 10000380: a1 49 91 88 lhz r10,-28280\(r9\)
+ 10000384: 89 4d 90 60 lbz r10,-28576\(r13\)
+ 10000388: 3d 2d 00 00 addis r9,r13,0
+ 1000038c: 99 49 90 68 stb r10,-28568\(r9\)
Index: ld/testsuite/ld-powerpc/tlsexetoc.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexetoc.g
diff -N ld/testsuite/ld-powerpc/tlsexetoc.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexetoc.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,14 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -sj.toc
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.toc:
+ 100104d0 00000000 00000000 00000000 00000000 .*
+ 100104e0 00000000 00000000 00000000 00000000 .*
+ 100104f0 00000000 00000001 00000000 00000000 .*
+ 10010500 00000000 00000001 00000000 00000000 .*
+ 10010510 ffffffff ffff8050 00000000 00000000 .*
Index: ld/testsuite/ld-powerpc/tlsexetoc.r
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexetoc.r
diff -N ld/testsuite/ld-powerpc/tlsexetoc.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexetoc.r 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,121 @@
+#source: tlslib.s
+#source: tlstoc.s
+#as: -a64
+#ld: -shared -melf64ppc
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are 21 section headers.*
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[ 1\] .interp +PROGBITS +0+10000190 0+190 0+11 0+ +A +0 +0 +1
+ +\[ 2\] .hash +HASH +0+100001a8 0+1a8 0+38 04 +A +3 +0 +8
+ +\[ 3\] .dynsym +DYNSYM +0+100001e0 0+1e0 0+d8 18 +A +4 +1 +8
+ +\[ 4\] .dynstr +STRTAB +0+100002b8 0+2b8 0+4d 0+ +A +0 +0 +1
+ +\[ 5\] .rela.dyn +RELA +0+10000308 0+308 0+30 18 +A +3 +0 +8
+ +\[ 6\] .text +PROGBITS +0+10000338 0+338 0+58 0+ +AX +0 +0 +4
+ +\[ 7\] .data +PROGBITS +0+10010390 0+390 0+ 0+ +WA +0 +0 +1
+ +\[ 8\] .branch_lt +PROGBITS +0+10010390 0+390 0+ 0+ +WA +0 +0 +8
+ +\[ 9\] .tdata +PROGBITS +0+10010390 0+390 0+38 0+ WAT +0 +0 +8
+ +\[10\] .tbss +NOBITS +0+100103c8 0+3c8 0+38 0+ WAT +0 +0 +8
+ +\[11\] .dynamic +DYNAMIC +0+100103c8 0+3c8 0+100 10 +WA +4 +0 +8
+ +\[12\] .ctors +PROGBITS +0+100104c8 0+520 0+ 0+ +W +0 +0 +1
+ +\[13\] .dtors +PROGBITS +0+100104c8 0+520 0+ 0+ +W +0 +0 +1
+ +\[14\] .got +PROGBITS +0+100104c8 0+4c8 0+8 08 +WA +0 +0 +8
+ +\[15\] .toc +PROGBITS +0+100104d0 0+4d0 0+50 0+ +WA +0 +0 +1
+ +\[16\] .sbss +PROGBITS +0+10010520 0+520 0+ 0+ +W +0 +0 +1
+ +\[17\] .bss +NOBITS +0+10010520 0+520 0+ 0+ +WA +0 +0 +1
+ +\[18\] .shstrtab +STRTAB +0+ 0+520 0+93 0+ +0 +0 +1
+ +\[19\] .symtab +SYMTAB +0+ 0+af8 0+438 18 +20 +1d +8
+ +\[20\] .strtab +STRTAB +0+ 0+f30 0+83 0+ +0 +0 +1
+#...
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x10000338
+There are 6 program headers.*
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +PHDR +0x0+40 0x0+10000040 0x0+10000040 0x0+150 0x0+150 R E 0x8
+ +INTERP +0x0+190 0x0+10000190 0x0+10000190 0x0+11 0x0+11 R +0x1
+ +\[Requesting program interpreter: .*\]
+ +LOAD +0x0+ 0x0+10000000 0x0+10000000 0x0+390 0x0+390 R E 0x10000
+ +LOAD +0x0+390 0x0+10010390 0x0+10010390 0x0+190 0x0+190 RW +0x10000
+ +DYNAMIC +0x0+3c8 0x0+100103c8 0x0+100103c8 0x0+100 0x0+100 RW +0x8
+ +TLS +0x0+390 0x0+10010390 0x0+10010390 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +00 +
+ +01 +\.interp
+ +02 +\.interp \.hash \.dynsym \.dynstr \.rela\.dyn \.text
+ +03 +\.tdata \.tbss \.dynamic \.got \.toc
+ +04 +\.tbss \.dynamic
+ +05 +\.tdata \.tbss
+
+Relocation section '\.rela\.dyn' at offset .* contains 2 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+100104d0 +0+200000049 R_PPC64_TPREL64 +0+ gd \+ 0
+0+100104e0 +0+400000049 R_PPC64_TPREL64 +0+ ld \+ 0
+
+Symbol table '\.dynsym' contains 9 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+100103c8 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +2: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
+ +3: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND \.__tls_get_addr
+ +4: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
+ +5: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +6: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +7: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +8: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+
+Symbol table '\.symtab' contains 45 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+10000190 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+100001a8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+100001e0 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+100002b8 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+10000308 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+10000338 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+10010390 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+10010390 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+10010390 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+100103c8 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+100103c8 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+100104c8 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+100104c8 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+100104c8 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+100104d0 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+10010520 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+10010520 +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+ +0 SECTION LOCAL +DEFAULT +18
+ +19: 0+ +0 SECTION LOCAL +DEFAULT +19
+ +20: 0+ +0 SECTION LOCAL +DEFAULT +20
+ +21: 0+ +0 TLS +LOCAL +DEFAULT +9 gd4
+ +22: 0+8 +0 TLS +LOCAL +DEFAULT +9 ld4
+ +23: 0+10 +0 TLS +LOCAL +DEFAULT +9 ld5
+ +24: 0+18 +0 TLS +LOCAL +DEFAULT +9 ld6
+ +25: 0+20 +0 TLS +LOCAL +DEFAULT +9 ie4
+ +26: 0+28 +0 TLS +LOCAL +DEFAULT +9 le4
+ +27: 0+30 +0 TLS +LOCAL +DEFAULT +9 le5
+ +28: 0+10010518 +0 NOTYPE +LOCAL +DEFAULT +15 \.Lie0
+ +29: 0+100103c8 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +30: 0+ +0 TLS +GLOBAL DEFAULT +UND gd
+ +31: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +32: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND \.__tls_get_addr
+ +33: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +34: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +35: 0+ +0 TLS +GLOBAL DEFAULT +UND ld
+ +36: 0+10000338 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +37: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +38: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +39: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +40: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +41: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +42: 0+10010520 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +43: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +44: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
Index: ld/testsuite/ld-powerpc/tlsexetoc.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsexetoc.t
diff -N ld/testsuite/ld-powerpc/tlsexetoc.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsexetoc.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,13 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 10010390 12345678 9abcdef0 23456789 abcdef01 .*
+ 100103a0 3456789a bcdef012 456789ab cdef0123 .*
+ 100103b0 56789abc def01234 6789abcd ef012345 .*
+ 100103c0 789abcde f0123456 .*
Index: ld/testsuite/ld-powerpc/tlslib.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlslib.s
diff -N ld/testsuite/ld-powerpc/tlslib.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlslib.s 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,20 @@
+ .global .__tls_get_addr,__tls_get_addr,gd,ld
+
+ .section ".opd","aw",@progbits
+__tls_get_addr:
+ .align 3
+ .quad .__tls_get_addr
+ .quad .TOC.@tocbase
+ .quad 0
+
+ .section ".tbss","awT",@nobits
+ .align 3
+gd: .space 8
+
+ .section ".tdata","awT",@progbits
+ .align 2
+ld: .long 0xc0ffee
+
+ .text
+.__tls_get_addr:
+ blr
Index: ld/testsuite/ld-powerpc/tlsso.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsso.d
diff -N ld/testsuite/ld-powerpc/tlsso.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsso.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,68 @@
+#source: tls.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+0+718 <\.__tls_get_addr>:
+ 718: 3d 82 00 00 addis r12,r2,0
+ 71c: f8 41 00 28 std r2,40\(r1\)
+ 720: e9 6c 80 78 ld r11,-32648\(r12\)
+ 724: e8 4c 80 80 ld r2,-32640\(r12\)
+ 728: 7d 69 03 a6 mtctr r11
+ 72c: e9 6c 80 88 ld r11,-32632\(r12\)
+ 730: 4e 80 04 20 bctr
+
+0+734 <_start>:
+ 734: 38 62 80 30 addi r3,r2,-32720
+ 738: 4b ff ff e1 bl 718 <\.__tls_get_addr>
+ 73c: e8 41 00 28 ld r2,40\(r1\)
+ 740: 38 62 80 08 addi r3,r2,-32760
+ 744: 4b ff ff d5 bl 718 <\.__tls_get_addr>
+ 748: e8 41 00 28 ld r2,40\(r1\)
+ 74c: 38 62 80 48 addi r3,r2,-32696
+ 750: 4b ff ff c9 bl 718 <\.__tls_get_addr>
+ 754: e8 41 00 28 ld r2,40\(r1\)
+ 758: 38 62 80 08 addi r3,r2,-32760
+ 75c: 4b ff ff bd bl 718 <\.__tls_get_addr>
+ 760: e8 41 00 28 ld r2,40\(r1\)
+ 764: 39 23 80 40 addi r9,r3,-32704
+ 768: 3d 23 00 00 addis r9,r3,0
+ 76c: 81 49 80 48 lwz r10,-32696\(r9\)
+ 770: e9 22 80 40 ld r9,-32704\(r2\)
+ 774: 7d 49 18 2a ldx r10,r9,r3
+ 778: e9 22 80 58 ld r9,-32680\(r2\)
+ 77c: 7d 49 6a 2e lhzx r10,r9,r13
+ 780: 89 4d 00 00 lbz r10,0\(r13\)
+ 784: 3d 2d 00 00 addis r9,r13,0
+ 788: 99 49 00 00 stb r10,0\(r9\)
+ 78c: 38 62 80 18 addi r3,r2,-32744
+ 790: 4b ff ff 89 bl 718 <\.__tls_get_addr>
+ 794: e8 41 00 28 ld r2,40\(r1\)
+ 798: 38 62 80 08 addi r3,r2,-32760
+ 79c: 4b ff ff 7d bl 718 <\.__tls_get_addr>
+ 7a0: e8 41 00 28 ld r2,40\(r1\)
+ 7a4: f9 43 80 08 std r10,-32760\(r3\)
+ 7a8: 3d 23 00 00 addis r9,r3,0
+ 7ac: 91 49 80 10 stw r10,-32752\(r9\)
+ 7b0: e9 22 80 28 ld r9,-32728\(r2\)
+ 7b4: 7d 49 19 2a stdx r10,r9,r3
+ 7b8: e9 22 80 58 ld r9,-32680\(r2\)
+ 7bc: 7d 49 6b 2e sthx r10,r9,r13
+ 7c0: e9 4d 90 2a lwa r10,-28632\(r13\)
+ 7c4: 3d 2d 00 00 addis r9,r13,0
+ 7c8: a9 49 90 30 lha r10,-28624\(r9\)
+ 7cc: e8 41 00 28 ld r2,40\(r1\)
+ 7d0: 3d 82 00 00 addis r12,r2,0
+ 7d4: e9 6c 80 60 ld r11,-32672\(r12\)
+ 7d8: e8 4c 80 68 ld r2,-32664\(r12\)
+ 7dc: 7d 69 03 a6 mtctr r11
+ 7e0: e9 6c 80 70 ld r11,-32656\(r12\)
+ 7e4: 4e 80 04 20 bctr
+ 7e8: 60 00 00 00 nop
+ 7ec: 38 00 00 00 li r0,0
+ 7f0: 4b ff ff dc b 7cc <_start\+0x98>
Index: ld/testsuite/ld-powerpc/tlsso.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsso.g
diff -N ld/testsuite/ld-powerpc/tlsso.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsso.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,15 @@
+#source: tls.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -sj.got
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.got:
+ 10980 00000000 00018980 00000000 00000000 .*
+ 10990 00000000 00000000 00000000 00000000 .*
+ 109a0 00000000 00000000 00000000 00000000 .*
+ 109b0 00000000 00000000 00000000 00000000 .*
+ 109c0 00000000 00000000 00000000 00000000 .*
+ 109d0 00000000 00000000 00000000 00000000 .*
Index: ld/testsuite/ld-powerpc/tlsso.r
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsso.r
diff -N ld/testsuite/ld-powerpc/tlsso.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsso.r 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,158 @@
+#source: tls.s
+#as: -a64
+#ld: -shared -melf64ppc
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are 21 section headers.*
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[ 1\] \.hash +HASH +0+120 0+120 0+d4 04 +A +2 +0 +8
+ +\[ 2\] \.dynsym +DYNSYM +0+1f8 0+1f8 0+330 18 +A +3 +12 +8
+ +\[ 3\] \.dynstr +STRTAB +0+528 0+528 0+54 0+ +A +0 +0 +1
+ +\[ 4\] \.rela\.dyn +RELA +0+580 0+580 0+180 18 +A +2 +0 +8
+ +\[ 5\] \.rela\.plt +RELA +0+700 0+700 0+18 18 +A +2 +10 +8
+ +\[ 6\] \.text +PROGBITS +0+718 0+718 0+dc 0+ +AX +0 +0 +4
+ +\[ 7\] \.data +PROGBITS +0+107f8 0+7f8 0+ 0+ +WA +0 +0 +1
+ +\[ 8\] \.branch_lt +PROGBITS +0+107f8 0+7f8 0+ 0+ +WA +0 +0 +8
+ +\[ 9\] \.tdata +PROGBITS +0+107f8 0+7f8 0+38 0+ WAT +0 +0 +8
+ +\[10\] \.tbss +NOBITS +0+10830 0+830 0+38 0+ WAT +0 +0 +8
+ +\[11\] \.dynamic +DYNAMIC +0+10830 0+830 0+150 10 +WA +3 +0 +8
+ +\[12\] \.ctors +PROGBITS +0+10980 0+9e0 0+ 0+ +W +0 +0 +1
+ +\[13\] \.dtors +PROGBITS +0+10980 0+9e0 0+ 0+ +W +0 +0 +1
+ +\[14\] \.got +PROGBITS +0+10980 0+980 0+60 08 +WA +0 +0 +8
+ +\[15\] \.sbss +PROGBITS +0+109e0 0+9e0 0+ 0+ +W +0 +0 +1
+ +\[16\] \.plt +NOBITS +0+109e0 0+9e0 0+30 18 +WA +0 +0 +8
+ +\[17\] \.bss +NOBITS +0+10a10 0+9e0 0+ 0+ +WA +0 +0 +1
+ +\[18\] \.shstrtab +STRTAB +0+ 0+9e0 0+90 0+ +0 +0 +1
+ +\[19\] \.symtab +SYMTAB +0+ 0+fb0 0+438 18 +20 +1d +8
+ +\[20\] \.strtab +STRTAB +0+ 0+13e8 0+8c 0+ +0 +0 +1
+#...
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x734
+There are 4 program headers.*
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +LOAD +0x0+ 0x0+ 0x0+ 0x0+7f4 0x0+7f4 R E 0x10000
+ +LOAD +0x0+7f8 0x0+107f8 0x0+107f8 0x0+1e8 0x0+218 RW +0x10000
+ +DYNAMIC +0x0+830 0x0+10830 0x0+10830 0x0+150 0x0+150 RW +0x8
+ +TLS +0x0+7f8 0x0+107f8 0x0+107f8 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text
+ +01 +\.tdata \.tbss \.dynamic \.got \.plt
+ +02 +\.tbss \.dynamic
+ +03 +\.tdata \.tbss
+
+Relocation section '\.rela\.dyn' at offset .* contains 16 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+782 +0+1400000045 R_PPC64_TPREL16 +0+60 le0 \+ 0
+0+786 +0+1700000048 R_PPC64_TPREL16_HA +0+68 le1 \+ 0
+0+78a +0+1700000046 R_PPC64_TPREL16_LO +0+68 le1 \+ 0
+0+7c2 +0+90000005f R_PPC64_TPREL16_DS +0+107f8 \.tdata \+ 28
+0+7c6 +0+900000048 R_PPC64_TPREL16_HA +0+107f8 \.tdata \+ 30
+0+7ca +0+900000046 R_PPC64_TPREL16_LO +0+107f8 \.tdata \+ 30
+0+10988 +0+44 R_PPC64_DTPMOD64 +0+
+0+10998 +0+44 R_PPC64_DTPMOD64 +0+
+0+109a0 +0+4e R_PPC64_DTPREL64 +0+107f8
+0+109a8 +0+4e R_PPC64_DTPREL64 +0+10810
+0+109b0 +0+1300000044 R_PPC64_DTPMOD64 +0+ gd \+ 0
+0+109b8 +0+130000004e R_PPC64_DTPREL64 +0+ gd \+ 0
+0+109c0 +0+1b0000004e R_PPC64_DTPREL64 +0+50 ld2 \+ 0
+0+109c8 +0+2000000044 R_PPC64_DTPMOD64 +0+38 gd0 \+ 0
+0+109d0 +0+200000004e R_PPC64_DTPREL64 +0+38 gd0 \+ 0
+0+109d8 +0+2100000049 R_PPC64_TPREL64 +0+58 ie0 \+ 0
+
+Relocation section '\.rela\.plt' at offset .* contains 1 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+109f8 +0+1500000015 R_PPC64_JMP_SLOT +0+ __tls_get_addr \+ 0
+
+Symbol table '\.dynsym' contains 34 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+120 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+1f8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+528 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+580 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+700 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+718 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+107f8 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+107f8 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+107f8 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+10830 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+10830 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+10980 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+10980 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+10980 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+109e0 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+109e0 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+10a10 +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+10830 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +19: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND gd
+ +20: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +21: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
+ +22: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +23: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +24: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND ld
+ +25: 0+734 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +26: 0+10a10 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +27: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +28: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +29: 0+109e0 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +30: 0+109e0 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +31: 0+10a10 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +32: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +33: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
+
+Symbol table '\.symtab' contains 45 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+120 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+1f8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+528 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+580 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+700 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+718 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+107f8 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+107f8 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+107f8 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+10830 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+10830 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+10980 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+10980 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+10980 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+109e0 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+109e0 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+10a10 +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+ +0 SECTION LOCAL +DEFAULT +18
+ +19: 0+ +0 SECTION LOCAL +DEFAULT +19
+ +20: 0+ +0 SECTION LOCAL +DEFAULT +20
+ +21: 0+ +0 TLS +LOCAL +DEFAULT +9 gd4
+ +22: 0+8 +0 TLS +LOCAL +DEFAULT +9 ld4
+ +23: 0+10 +0 TLS +LOCAL +DEFAULT +9 ld5
+ +24: 0+18 +0 TLS +LOCAL +DEFAULT +9 ld6
+ +25: 0+20 +0 TLS +LOCAL +DEFAULT +9 ie4
+ +26: 0+28 +0 TLS +LOCAL +DEFAULT +9 le4
+ +27: 0+30 +0 TLS +LOCAL +DEFAULT +9 le5
+ +28: 0+718 +0 NOTYPE +LOCAL +DEFAULT +6 \.__tls_get_addr
+ +29: 0+10830 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +30: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND gd
+ +31: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +32: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
+ +33: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +34: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +35: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND ld
+ +36: 0+734 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +37: 0+10a10 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +38: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +39: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +40: 0+109e0 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +41: 0+109e0 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +42: 0+10a10 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +43: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +44: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
Index: ld/testsuite/ld-powerpc/tlsso.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlsso.t
diff -N ld/testsuite/ld-powerpc/tlsso.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlsso.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,13 @@
+#source: tls.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 107f8 12345678 9abcdef0 23456789 abcdef01 .*
+ 10808 3456789a bcdef012 456789ab cdef0123 .*
+ 10818 56789abc def01234 6789abcd ef012345 .*
+ 10828 789abcde f0123456 .*
Index: ld/testsuite/ld-powerpc/tlstoc.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstoc.d
diff -N ld/testsuite/ld-powerpc/tlstoc.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstoc.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,37 @@
+#source: tlslib.s
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+00000000100000e8 <\.__tls_get_addr>:
+ 100000e8: 4e 80 00 20 blr
+
+00000000100000ec <_start>:
+ 100000ec: 3c 6d 00 00 addis r3,r13,0
+ 100000f0: 60 00 00 00 nop
+ 100000f4: 38 63 90 58 addi r3,r3,-28584
+ 100000f8: 3c 6d 00 00 addis r3,r13,0
+ 100000fc: 60 00 00 00 nop
+ 10000100: 38 63 10 00 addi r3,r3,4096
+ 10000104: 3c 6d 00 00 addis r3,r13,0
+ 10000108: 60 00 00 00 nop
+ 1000010c: 38 63 90 58 addi r3,r3,-28584
+ 10000110: 3c 6d 00 00 addis r3,r13,0
+ 10000114: 60 00 00 00 nop
+ 10000118: 38 63 10 00 addi r3,r3,4096
+ 1000011c: 39 23 80 50 addi r9,r3,-32688
+ 10000120: 3d 23 00 00 addis r9,r3,0
+ 10000124: 81 49 80 58 lwz r10,-32680\(r9\)
+ 10000128: 3d 2d 00 00 addis r9,r13,0
+ 1000012c: 7d 49 18 2a ldx r10,r9,r3
+ 10000130: 3d 2d 00 00 addis r9,r13,0
+ 10000134: a1 49 90 a0 lhz r10,-28512\(r9\)
+ 10000138: 89 4d 90 70 lbz r10,-28560\(r13\)
+ 1000013c: 3d 2d 00 00 addis r9,r13,0
+ 10000140: 99 49 90 78 stb r10,-28552\(r9\)
Index: ld/testsuite/ld-powerpc/tlstoc.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstoc.g
diff -N ld/testsuite/ld-powerpc/tlstoc.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstoc.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,15 @@
+#source: tlslib.s
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -sj.toc
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.toc:
+ 100101a0 00000000 00000001 00000000 00000000 .*
+ 100101b0 00000000 00000001 00000000 00000000 .*
+ 100101c0 00000000 00000001 00000000 00000000 .*
+ 100101d0 00000000 00000001 00000000 00000000 .*
+ 100101e0 ffffffff ffff8060 00000000 00000000 .*
Index: ld/testsuite/ld-powerpc/tlstoc.s
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstoc.s
diff -N ld/testsuite/ld-powerpc/tlstoc.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstoc.s 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,88 @@
+ .section ".tbss","awT",@nobits
+ .global _start,gd0,ld0,ld1,ld2,ie0,le0,le1
+ .align 3
+gd0: .space 8
+ld0: .space 8
+ld1: .space 8
+ld2: .space 8
+ie0: .space 8
+le0: .space 8
+le1: .space 8
+
+ .section ".tdata","awT",@progbits
+ .align 3
+gd4: .quad 0x123456789abcdef0
+ld4: .quad 0x23456789abcdef01
+ld5: .quad 0x3456789abcdef012
+ld6: .quad 0x456789abcdef0123
+ie4: .quad 0x56789abcdef01234
+le4: .quad 0x6789abcdef012345
+le5: .quad 0x789abcdef0123456
+
+ .text
+_start:
+#extern syms
+#GD
+ addi 3,2,.Lgd@toc
+ bl .__tls_get_addr
+ nop
+ .section .toc,"aw",@progbits
+.Lgd:
+ .quad gd@dtpmod
+ .quad gd@dtprel
+ .text
+#LD
+ addi 3,2,.Lld@toc
+ bl .__tls_get_addr
+ nop
+ .section .toc,"aw",@progbits
+.Lld:
+ .quad ld@dtpmod
+ .quad 0
+ .text
+
+#global syms
+#GD
+ addi 3,2,.Lgd0@toc
+ bl .__tls_get_addr
+ nop
+ .section .toc,"aw",@progbits
+.Lgd0:
+ .quad gd0@dtpmod
+ .quad gd0@dtprel
+ .text
+#LD
+ addi 3,2,.Lld0@toc
+ bl .__tls_get_addr
+ nop
+ .section .toc,"aw",@progbits
+.Lld0:
+ .quad ld0@dtpmod
+ .quad 0
+ .text
+
+ addi 9,3,ld0@dtprel
+
+ addis 9,3,ld1@dtprel@ha
+ lwz 10,ld1@dtprel@l(9)
+
+ ld 9,.Lld2@toc(2)
+ ldx 10,9,3
+ .section .toc,"aw",@progbits
+.Lld2:
+ .quad ld2@dtprel
+ .text
+
+#IE
+ ld 9,.Lie0@toc(2)
+ lhzx 10,9,.Lie0@tls
+ .section .toc,"aw",@progbits
+.Lie0:
+ .quad ie0@tprel
+ .text
+
+#LE
+ lbz 10,le0@tprel(13) #R_PPC64_TPREL16 le0
+
+ addis 9,13,le1@tprel@ha #R_PPC64_TPREL16_HA le1
+ stb 10,le1@tprel@l(9) #R_PPC64_TPREL16_LO le1
Index: ld/testsuite/ld-powerpc/tlstoc.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstoc.t
diff -N ld/testsuite/ld-powerpc/tlstoc.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstoc.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,14 @@
+#source: tlslib.s
+#source: tlstoc.s
+#as: -a64
+#ld: -melf64ppc
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 10010148 00c0ffee 00000000 12345678 9abcdef0 .*
+ 10010158 23456789 abcdef01 3456789a bcdef012 .*
+ 10010168 456789ab cdef0123 56789abc def01234 .*
+ 10010178 6789abcd ef012345 789abcde f0123456 .*
Index: ld/testsuite/ld-powerpc/tlstocso.d
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstocso.d
diff -N ld/testsuite/ld-powerpc/tlstocso.d
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstocso.d 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,52 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -dr
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Disassembly of section \.text:
+
+0+6b8 <\.__tls_get_addr>:
+ 6b8: 3d 82 00 00 addis r12,r2,0
+ 6bc: f8 41 00 28 std r2,40\(r1\)
+ 6c0: e9 6c 80 70 ld r11,-32656\(r12\)
+ 6c4: e8 4c 80 78 ld r2,-32648\(r12\)
+ 6c8: 7d 69 03 a6 mtctr r11
+ 6cc: e9 6c 80 80 ld r11,-32640\(r12\)
+ 6d0: 4e 80 04 20 bctr
+
+0+6d4 <_start>:
+ 6d4: 38 62 80 08 addi r3,r2,-32760
+ 6d8: 4b ff ff e1 bl 6b8 <\.__tls_get_addr>
+ 6dc: e8 41 00 28 ld r2,40\(r1\)
+ 6e0: 38 62 80 18 addi r3,r2,-32744
+ 6e4: 4b ff ff d5 bl 6b8 <\.__tls_get_addr>
+ 6e8: e8 41 00 28 ld r2,40\(r1\)
+ 6ec: 38 62 80 28 addi r3,r2,-32728
+ 6f0: 4b ff ff c9 bl 6b8 <\.__tls_get_addr>
+ 6f4: e8 41 00 28 ld r2,40\(r1\)
+ 6f8: 38 62 80 38 addi r3,r2,-32712
+ 6fc: 4b ff ff bd bl 6b8 <\.__tls_get_addr>
+ 700: e8 41 00 28 ld r2,40\(r1\)
+ 704: 39 23 80 40 addi r9,r3,-32704
+ 708: 3d 23 00 00 addis r9,r3,0
+ 70c: 81 49 80 48 lwz r10,-32696\(r9\)
+ 710: 3d 2d 00 00 addis r9,r13,0
+ 714: 7d 49 18 2a ldx r10,r9,r3
+ 718: e9 22 80 50 ld r9,-32688\(r2\)
+ 71c: 7d 49 6a 2e lhzx r10,r9,r13
+ 720: 89 4d 00 00 lbz r10,0\(r13\)
+ 724: 3d 2d 00 00 addis r9,r13,0
+ 728: 99 49 00 00 stb r10,0\(r9\)
+ 72c: e8 41 00 28 ld r2,40\(r1\)
+ 730: 3d 82 00 00 addis r12,r2,0
+ 734: e9 6c 80 58 ld r11,-32680\(r12\)
+ 738: e8 4c 80 60 ld r2,-32672\(r12\)
+ 73c: 7d 69 03 a6 mtctr r11
+ 740: e9 6c 80 68 ld r11,-32664\(r12\)
+ 744: 4e 80 04 20 bctr
+ 748: 60 00 00 00 nop
+ 74c: 38 00 00 00 li r0,0
+ 750: 4b ff ff dc b 72c <_start\+0x58>
Index: ld/testsuite/ld-powerpc/tlstocso.g
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstocso.g
diff -N ld/testsuite/ld-powerpc/tlstocso.g
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstocso.g 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,14 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -sj.toc
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.toc:
+ 108e8 00000000 00000000 00000000 00000000 .*
+ 108f8 00000000 00000000 00000000 00000000 .*
+ 10908 00000000 00000000 00000000 00000000 .*
+ 10918 00000000 00000000 00000000 00000000 .*
+ 10928 00000000 00000000 00000000 00000000 .*
Index: ld/testsuite/ld-powerpc/tlstocso.r
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstocso.r
diff -N ld/testsuite/ld-powerpc/tlstocso.r
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstocso.r 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,157 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -shared -melf64ppc
+#readelf: -WSsrl
+#target: powerpc64*-*-*
+
+There are 22 section headers.*
+
+Section Headers:
+ +\[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+ +\[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+ +\[ 1\] \.hash +HASH +0+120 0+120 0+d8 04 +A +2 +0 +8
+ +\[ 2\] \.dynsym +DYNSYM +0+1f8 0+1f8 0+348 18 +A +3 +13 +8
+ +\[ 3\] \.dynstr +STRTAB +0+540 0+540 0+54 0+ +A +0 +0 +1
+ +\[ 4\] \.rela\.dyn +RELA +0+598 0+598 0+108 18 +A +2 +0 +8
+ +\[ 5\] \.rela\.plt +RELA +0+6a0 0+6a0 0+18 18 +A +2 +11 +8
+ +\[ 6\] \.text +PROGBITS +0+6b8 0+6b8 0+9c 0+ +AX +0 +0 +4
+ +\[ 7\] \.data +PROGBITS +0+10758 0+758 0+ 0+ +WA +0 +0 +1
+ +\[ 8\] \.branch_lt +PROGBITS +0+10758 0+758 0+ 0+ +WA +0 +0 +8
+ +\[ 9\] \.tdata +PROGBITS +0+10758 0+758 0+38 0+ WAT +0 +0 +8
+ +\[10\] \.tbss +NOBITS +0+10790 0+790 0+38 0+ WAT +0 +0 +8
+ +\[11\] \.dynamic +DYNAMIC +0+10790 0+790 0+150 10 +WA +3 +0 +8
+ +\[12\] \.ctors +PROGBITS +0+108e0 0+938 0+ 0+ +W +0 +0 +1
+ +\[13\] \.dtors +PROGBITS +0+108e0 0+938 0+ 0+ +W +0 +0 +1
+ +\[14\] \.got +PROGBITS +0+108e0 0+8e0 0+8 08 +WA +0 +0 +8
+ +\[15\] \.toc +PROGBITS +0+108e8 0+8e8 0+50 0+ +WA +0 +0 +1
+ +\[16\] \.sbss +PROGBITS +0+10938 0+938 0+ 0+ +W +0 +0 +1
+ +\[17\] \.plt +NOBITS +0+10938 0+938 0+30 18 +WA +0 +0 +8
+ +\[18\] \.bss +NOBITS +0+10968 0+938 0+ 0+ +WA +0 +0 +1
+ +\[19\] \.shstrtab +STRTAB +0+ 0+938 0+95 0+ +0 +0 +1
+ +\[20\] \.symtab +SYMTAB +0+ 0+f50 0+468 18 +21 +1f +8
+ +\[21\] \.strtab +STRTAB +0+ 0+13b8 0+92 0+ +0 +0 +1
+#...
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x6d4
+There are 4 program headers.*
+
+Program Headers:
+ +Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+ +LOAD +0x0+ 0x0+ 0x0+ 0x0+754 0x0+754 R E 0x10000
+ +LOAD +0x0+758 0x0+10758 0x0+10758 0x0+1e0 0x0+210 RW +0x10000
+ +DYNAMIC +0x0+790 0x0+10790 0x0+10790 0x0+150 0x0+150 RW +0x8
+ +TLS +0x0+758 0x0+10758 0x0+10758 0x0+38 0x0+70 R +0x8
+
+ Section to Segment mapping:
+ +Segment Sections\.\.\.
+ +0+ +\.hash \.dynsym \.dynstr \.rela\.dyn \.rela\.plt \.text
+ +01 +\.tdata \.tbss \.dynamic \.got \.toc \.plt
+ +02 +\.tbss \.dynamic
+ +03 +\.tdata \.tbss
+
+Relocation section '\.rela\.dyn' at offset .* contains 11 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+712 +0+f00000048 R_PPC64_TPREL16_HA +0+108e8 \.toc \+ 40
+0+722 +0+1500000045 R_PPC64_TPREL16 +0+60 le0 \+ 0
+0+726 +0+1800000048 R_PPC64_TPREL16_HA +0+68 le1 \+ 0
+0+108e8 +0+1400000044 R_PPC64_DTPMOD64 +0+ gd \+ 0
+0+108f0 +0+140000004e R_PPC64_DTPREL64 +0+ gd \+ 0
+0+108f8 +0+1900000044 R_PPC64_DTPMOD64 +0+ ld \+ 0
+0+10908 +0+2100000044 R_PPC64_DTPMOD64 +0+38 gd0 \+ 0
+0+10910 +0+210000004e R_PPC64_DTPREL64 +0+38 gd0 \+ 0
+0+10918 +0+1700000044 R_PPC64_DTPMOD64 +0+40 ld0 \+ 0
+0+10928 +0+1c0000004e R_PPC64_DTPREL64 +0+50 ld2 \+ 0
+0+10930 +0+2200000049 R_PPC64_TPREL64 +0+58 ie0 \+ 0
+
+Relocation section '\.rela\.plt' at offset 0x6a0 contains 1 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+10950 +0+1600000015 R_PPC64_JMP_SLOT +0+ __tls_get_addr \+ 0
+
+Symbol table '\.dynsym' contains 35 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+120 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+1f8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+540 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+598 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+6a0 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+6b8 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+10758 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+10758 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+10758 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+10790 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+10790 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+108e0 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+108e0 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+108e0 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+108e8 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+10938 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+10938 +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+10968 +0 SECTION LOCAL +DEFAULT +18
+ +19: 0+10790 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +20: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND gd
+ +21: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +22: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
+ +23: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +24: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +25: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND ld
+ +26: 0+6d4 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +27: 0+10968 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +28: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +29: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +30: 0+10938 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +31: 0+10938 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +32: 0+10968 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +33: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +34: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
+
+Symbol table '\.symtab' contains 47 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +0: 0+ +0 NOTYPE +LOCAL +DEFAULT +UND
+ +1: 0+120 +0 SECTION LOCAL +DEFAULT +1
+ +2: 0+1f8 +0 SECTION LOCAL +DEFAULT +2
+ +3: 0+540 +0 SECTION LOCAL +DEFAULT +3
+ +4: 0+598 +0 SECTION LOCAL +DEFAULT +4
+ +5: 0+6a0 +0 SECTION LOCAL +DEFAULT +5
+ +6: 0+6b8 +0 SECTION LOCAL +DEFAULT +6
+ +7: 0+10758 +0 SECTION LOCAL +DEFAULT +7
+ +8: 0+10758 +0 SECTION LOCAL +DEFAULT +8
+ +9: 0+10758 +0 SECTION LOCAL +DEFAULT +9
+ +10: 0+10790 +0 SECTION LOCAL +DEFAULT +10
+ +11: 0+10790 +0 SECTION LOCAL +DEFAULT +11
+ +12: 0+108e0 +0 SECTION LOCAL +DEFAULT +12
+ +13: 0+108e0 +0 SECTION LOCAL +DEFAULT +13
+ +14: 0+108e0 +0 SECTION LOCAL +DEFAULT +14
+ +15: 0+108e8 +0 SECTION LOCAL +DEFAULT +15
+ +16: 0+10938 +0 SECTION LOCAL +DEFAULT +16
+ +17: 0+10938 +0 SECTION LOCAL +DEFAULT +17
+ +18: 0+10968 +0 SECTION LOCAL +DEFAULT +18
+ +19: 0+ +0 SECTION LOCAL +DEFAULT +19
+ +20: 0+ +0 SECTION LOCAL +DEFAULT +20
+ +21: 0+ +0 SECTION LOCAL +DEFAULT +21
+ +22: 0+ +0 TLS +LOCAL +DEFAULT +9 gd4
+ +23: 0+8 +0 TLS +LOCAL +DEFAULT +9 ld4
+ +24: 0+10 +0 TLS +LOCAL +DEFAULT +9 ld5
+ +25: 0+18 +0 TLS +LOCAL +DEFAULT +9 ld6
+ +26: 0+20 +0 TLS +LOCAL +DEFAULT +9 ie4
+ +27: 0+28 +0 TLS +LOCAL +DEFAULT +9 le4
+ +28: 0+30 +0 TLS +LOCAL +DEFAULT +9 le5
+ +29: 0+10930 +0 NOTYPE +LOCAL +DEFAULT +15 \.Lie0
+ +30: 0+6b8 +0 NOTYPE +LOCAL +DEFAULT +6 \.__tls_get_addr
+ +31: 0+10790 +0 OBJECT +GLOBAL DEFAULT +ABS _DYNAMIC
+ +32: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND gd
+ +33: 0+60 +0 TLS +GLOBAL DEFAULT +10 le0
+ +34: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND __tls_get_addr
+ +35: 0+40 +0 TLS +GLOBAL DEFAULT +10 ld0
+ +36: 0+68 +0 TLS +GLOBAL DEFAULT +10 le1
+ +37: 0+ +0 NOTYPE +GLOBAL DEFAULT +UND ld
+ +38: 0+6d4 +0 NOTYPE +GLOBAL DEFAULT +6 _start
+ +39: 0+10968 +0 NOTYPE +GLOBAL DEFAULT +ABS __end
+ +40: 0+50 +0 TLS +GLOBAL DEFAULT +10 ld2
+ +41: 0+48 +0 TLS +GLOBAL DEFAULT +10 ld1
+ +42: 0+10938 +0 NOTYPE +GLOBAL DEFAULT +ABS __bss_start
+ +43: 0+10938 +0 NOTYPE +GLOBAL DEFAULT +ABS _edata
+ +44: 0+10968 +0 NOTYPE +GLOBAL DEFAULT +ABS _end
+ +45: 0+38 +0 TLS +GLOBAL DEFAULT +10 gd0
+ +46: 0+58 +0 TLS +GLOBAL DEFAULT +10 ie0
Index: ld/testsuite/ld-powerpc/tlstocso.t
===================================================================
RCS file: ld/testsuite/ld-powerpc/tlstocso.t
diff -N ld/testsuite/ld-powerpc/tlstocso.t
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-powerpc/tlstocso.t 4 Feb 2003 14:12:04 -0000
@@ -0,0 +1,13 @@
+#source: tlstoc.s
+#as: -a64
+#ld: -shared -melf64ppc
+#objdump: -sj.tdata
+#target: powerpc64*-*-*
+
+.*: +file format elf64-powerpc
+
+Contents of section \.tdata:
+ 10758 12345678 9abcdef0 23456789 abcdef01 .*
+ 10768 3456789a bcdef012 456789ab cdef0123 .*
+ 10778 56789abc def01234 6789abcd ef012345 .*
+ 10788 789abcde f0123456 .*