PowerPC32 treatment of absolute symbols

As already done for PowerPC64, fix dynamic relocs for absolute symbols.
The patch also tidies the dynamic reloc handling code in check_relocs,
removing leftover comments and code from when check_relocs was called
as each object file was read in.

bfd/
	* elf32-ppc.c (ppc_elf_check_relocs): Set isym and ifunc earlier.
	Rearrange tests for dynamic relocs, handling absolute symbols.
	(allocate_dynrelocs): Don't allocate dynamic relocs for locally
	defined absolute symbols.
	(ppc_elf_size_dynamic_sections): Similarly.
	(ppc_elf_relocate_section): Similarly.
ld/
	* testsuite/ld-powerpc/abs32-pie.d,
	* testsuite/ld-powerpc/abs32-pie.r,
	* testsuite/ld-powerpc/abs32-reloc.s,
	* testsuite/ld-powerpc/abs32-shared.d,
	* testsuite/ld-powerpc/abs32-shared.r,
	* testsuite/ld-powerpc/abs32-static.d,
	* testsuite/ld-powerpc/abs32-static.r: New tests.
	* testsuite/ld-powerpc/powerpc.exp: Run them.
This commit is contained in:
Alan Modra
2022-03-31 07:41:03 +10:30
parent 24ef0d41ac
commit 7a9361c00d
9 changed files with 205 additions and 62 deletions

View File

@@ -2929,6 +2929,7 @@ ppc_elf_check_relocs (bfd *abfd,
unsigned long r_symndx;
enum elf_ppc_reloc_type r_type;
struct elf_link_hash_entry *h;
Elf_Internal_Sym *isym;
int tls_type;
struct plt_entry **ifunc;
struct plt_entry **pltent;
@@ -2936,13 +2937,19 @@ ppc_elf_check_relocs (bfd *abfd,
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
{
h = NULL;
isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
if (isym == NULL)
return false;
}
else
{
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;
isym = NULL;
}
/* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
@@ -2962,13 +2969,16 @@ ppc_elf_check_relocs (bfd *abfd,
tls_type = 0;
r_type = ELF32_R_TYPE (rel->r_info);
ifunc = NULL;
if (h == NULL && htab->elf.target_os != is_vxworks)
if (h != NULL)
{
if (h->type == STT_GNU_IFUNC)
{
h->needs_plt = 1;
ifunc = &h->plt.plist;
}
}
else if (htab->elf.target_os != is_vxworks)
{
Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return false;
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
/* Set PLT_IFUNC flag for this sym, no GOT entry yet. */
@@ -3294,12 +3304,10 @@ ppc_elf_check_relocs (bfd *abfd,
htab->plt_type = PLT_OLD;
htab->old_bfd = abfd;
}
if (h != NULL && h->type == STT_GNU_IFUNC)
{
h->needs_plt = 1;
if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
return false;
}
if (h != NULL
&& ifunc != NULL
&& !update_plt_info (abfd, ifunc, NULL, 0))
return false;
break;
/* This relocation describes the C++ object vtable hierarchy.
@@ -3347,12 +3355,6 @@ ppc_elf_check_relocs (bfd *abfd,
reliably deduce the GOT pointer value needed for
PLT call stubs. */
asection *s;
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return false;
s = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (s == got2)
@@ -3421,38 +3423,21 @@ ppc_elf_check_relocs (bfd *abfd,
}
dodyn:
/* If we are creating a shared library, and this is a reloc
against a global symbol, or a non PC relative reloc
against a local symbol, then we need to copy the reloc
into the shared library. However, if we are linking with
-Bsymbolic, we do not need to copy a reloc against a
global symbol which is defined in an object we are
including in the link (i.e., DEF_REGULAR is set). At
this point we have not seen all the input files, so it is
possible that DEF_REGULAR is not set now but will be set
later (it is never cleared). In case of a weak definition,
DEF_REGULAR may be cleared later by a strong definition in
a shared library. We account for that possibility below by
storing information in the dyn_relocs field of the hash
table entry. A similar situation occurs when creating
shared libraries and symbol visibility changes render the
symbol local.
If on the other hand, we are creating an executable, we
may need to keep relocations for symbols satisfied by a
dynamic library if we manage to avoid copy relocs for the
symbol. */
if ((bfd_link_pic (info)
&& (must_be_dyn_reloc (info, r_type)
|| (h != NULL
&& (!SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular)))
/* Set up information for symbols that might need dynamic
relocations. At this point in linking we have read all
the input files and resolved most symbols, but have not
yet decided whether symbols are dynamic or finalized
symbol flags. In some cases we might be setting dynamic
reloc info for symbols that do not end up needing such.
That's OK, adjust_dynamic_symbol and allocate_dynrelocs
work together with this code. */
if ((h != NULL
&& !SYMBOL_REFERENCES_LOCAL (info, h))
|| (bfd_link_pic (info)
&& (h != NULL
? !bfd_is_abs_symbol (&h->root)
: isym->st_shndx != SHN_ABS)
&& must_be_dyn_reloc (info, r_type)))
{
#ifdef DEBUG
fprintf (stderr,
@@ -3507,12 +3492,6 @@ ppc_elf_check_relocs (bfd *abfd,
bool is_ifunc;
asection *s;
void *vpp;
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return false;
s = bfd_section_from_elf_index (abfd, isym->st_shndx);
if (s == NULL)
@@ -3520,7 +3499,7 @@ ppc_elf_check_relocs (bfd *abfd,
vpp = &elf_section_data (s)->local_dynrel;
rel_head = (struct ppc_dyn_relocs **) vpp;
is_ifunc = ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC;
is_ifunc = ifunc != NULL;
p = *rel_head;
if (p != NULL && p->sec == sec && p->ifunc != is_ifunc)
p = p->next;
@@ -5170,7 +5149,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (((bfd_link_pic (info)
&& !((eh->tls_mask & TLS_TLS) != 0
&& bfd_link_executable (info)
&& SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
&& SYMBOL_REFERENCES_LOCAL (info, &eh->elf))
&& !bfd_is_abs_symbol (&h->root))
|| (htab->elf.dynamic_sections_created
&& eh->elf.dynindx != -1
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
@@ -5540,6 +5520,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
char *lgot_masks;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *local_syms;
Elf_Internal_Sym *isym;
if (!is_ppc_elf (ibfd))
continue;
@@ -5596,8 +5578,18 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
local_plt = (struct plt_entry **) end_local_got;
end_local_plt = local_plt + locsymcount;
lgot_masks = (char *) end_local_plt;
local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
if (local_syms == NULL && locsymcount != 0)
{
local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, locsymcount,
0, NULL, NULL, NULL);
if (local_syms == NULL)
return false;
}
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
for (isym = local_syms;
local_got < end_local_got;
++local_got, ++lgot_masks, ++isym)
if (*local_got > 0)
{
unsigned int need;
@@ -5611,7 +5603,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
*local_got = allocate_got (htab, need);
if (bfd_link_pic (info)
&& !((*lgot_masks & TLS_TLS) != 0
&& bfd_link_executable (info)))
&& bfd_link_executable (info))
&& isym->st_shndx != SHN_ABS)
{
asection *srel;
@@ -5684,6 +5677,15 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
else
ent->plt.offset = (bfd_vma) -1;
}
if (local_syms != NULL
&& symtab_hdr->contents != (unsigned char *) local_syms)
{
if (!info->keep_memory)
free (local_syms);
else
symtab_hdr->contents = (unsigned char *) local_syms;
}
}
/* Allocate space for global sym dynamic relocs. */
@@ -7796,7 +7798,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
&& !(tls_ty != 0
&& bfd_link_executable (info)
&& SYMBOL_REFERENCES_LOCAL (info, h))))
&& SYMBOL_REFERENCES_LOCAL (info, h))
&& (h != NULL
? !bfd_is_abs_symbol (&h->root)
: sym->st_shndx != SHN_ABS)))
{
asection *rsec = htab->elf.srelgot;
bfd_byte * loc;

View File

@@ -0,0 +1,26 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#objdump: -dr
.*: file format .*
Disassembly of section \.text:
00000138 <_start>:
138: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\)
13c: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\)
140: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\)
144: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\)
Disassembly of section \.got:
000101d8 <\.got>:
101d8: (00 00 00 02|02 00 00 00) .*
101dc: (00 00 00 00|00 00 00 00) .*
101e0: (12 34 56 78|78 56 34 12) .*
101e4: (00 00 00 01|01 00 00 00) .*
101e8: (4e 80 00 21|21 00 80 4e) blrl
000101ec <_GLOBAL_OFFSET_TABLE_>:
101ec: (00 01 01 48|48 01 01 00) 00 00 00 00 00 00 00 00 .*

View File

@@ -0,0 +1,9 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#readelf: -rW
Relocation section '\.rela\.dyn' at offset .* contains 2 entries:
Offset Info Type Sym\. Value Symbol's Name \+ Addend
000101c8 00000016 R_PPC_RELATIVE 101c8
000101dc 00000016 R_PPC_RELATIVE 101c8

View File

@@ -0,0 +1,22 @@
.globl x
.hidden x
.data
.p2align 2
x:
.long x
.long a
.long b
.long c
.text
.p2align 2
.globl _start
.type _start,@function
_start:
0:
lwz 7,x@got(30)
lwz 8,a@got(30)
lwz 9,b@got(30)
lwz 10,c@got(30)
.size _start,.-_start

View File

@@ -0,0 +1,24 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#objdump: -dr
.*: file format .*
Disassembly of section \.text:
00000160 <_start>:
160: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\)
164: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\)
168: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\)
16c: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\)
Disassembly of section \.got:
000101f0 <\.got>:
101f0: (00 00 00 02|02 00 00 00) .*
.\.\.
10200: (4e 80 00 21|21 00 80 4e) blrl
00010204 <_GLOBAL_OFFSET_TABLE_>:
10204: (00 01 01 70|70 01 01 00) 00 00 00 00 00 00 00 00 .*

View File

@@ -0,0 +1,13 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#readelf: -rW
Relocation section '\.rela\.dyn' at offset .* contains 6 entries:
Offset Info Type Sym\. Value Symbol's Name \+ Addend
000101e0 00000016 R_PPC_RELATIVE 101e0
000101f4 00000016 R_PPC_RELATIVE 101e0
000101e4 00000401 R_PPC_ADDR32 00000001 a \+ 0
000101fc 00000414 R_PPC_GLOB_DAT 00000001 a \+ 0
000101ec 00000301 R_PPC_ADDR32 12345678 c \+ 0
000101f8 00000314 R_PPC_GLOB_DAT 12345678 c \+ 0

View File

@@ -0,0 +1,26 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#objdump: -dr
.*: file format .*
Disassembly of section \.text:
01800074 <_start>:
1800074: (80 fe ff f0|f0 ff fe 80) lwz r7,-16\(r30\)
1800078: (81 1e ff f8|f8 ff 1e 81) lwz r8,-8\(r30\)
180007c: (81 3e ff ec|ec ff 3e 81) lwz r9,-20\(r30\)
1800080: (81 5e ff f4|f4 ff 5e 81) lwz r10,-12\(r30\)
Disassembly of section \.got:
01810094 <\.got>:
1810094: (00 00 00 02|02 00 00 00) .*
1810098: (01 81 00 84|84 00 81 01) .*
181009c: (12 34 56 78|78 56 34 12) .*
18100a0: (00 00 00 01|01 00 00 00) .*
18100a4: (4e 80 00 21|21 00 80 4e) blrl
018100a8 <_GLOBAL_OFFSET_TABLE_>:
\.\.\.

View File

@@ -0,0 +1,6 @@
#source: abs32-reloc.s
#as: -a32
#ld: -melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678
#readelf: -rW
There are no relocations in this file.

View File

@@ -173,6 +173,18 @@ set ppcelftests {
{{objdump -dr relaxrl.d}}
"rrelax"}
{"build empty shared library" "-shared" "" "" "empty.s" {} "empty.so"}
{"abs32-static" "-melf32ppc -static --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" ""
"-a32" {abs32-reloc.s}
{{objdump {-dr} abs32-static.d}
{readelf {-rW} abs32-static.r}} "abs32-static"}
{"abs32-pie" "-melf32ppc -pie --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" ""
"-a32" {abs32-reloc.s}
{{objdump {-dr} abs32-pie.d}
{readelf {-rW} abs32-pie.r}} "abs32-pie"}
{"abs32-shared" "-melf32ppc -shared --hash-style=sysv --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x12345678" ""
"-a32" {abs32-reloc.s}
{{objdump {-dr} abs32-shared.d}
{readelf {-rW} abs32-shared.r}} "abs32-shared"}
}
set ppc64elftests {