Skip to content

Commit

Permalink
PowerPC32 treatment of absolute symbols
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
amodra committed May 4, 2022
1 parent 24ef0d4 commit 7a9361c
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 62 deletions.
129 changes: 67 additions & 62 deletions bfd/elf32-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2929,20 +2929,27 @@ 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;
bfd_vma addend;

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.
Expand All @@ -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. */
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -3507,20 +3492,14 @@ 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)
s = sec;

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;
Expand Down Expand Up @@ -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)))
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-pie.d
Original file line number Diff line number Diff line change
@@ -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 .*
9 changes: 9 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-pie.r
Original file line number Diff line number Diff line change
@@ -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
22 changes: 22 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-reloc.s
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-shared.d
Original file line number Diff line number Diff line change
@@ -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 .*
13 changes: 13 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-shared.r
Original file line number Diff line number Diff line change
@@ -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
26 changes: 26 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-static.d
Original file line number Diff line number Diff line change
@@ -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_>:
\.\.\.
6 changes: 6 additions & 0 deletions ld/testsuite/ld-powerpc/abs32-static.r
Original file line number Diff line number Diff line change
@@ -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.
12 changes: 12 additions & 0 deletions ld/testsuite/ld-powerpc/powerpc.exp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 7a9361c

Please sign in to comment.