Fix PR ld/17277: bogus dynamic relocs and TEXTREL for ARM PC-relative relocs

bfd/
	PR ld/17277
	* elf32-arm.c (elf32_arm_check_relocs): Increment P->pc_count for
	all reloc types with pc_relative set in the howto, not just for
	R_ARM_REL32 and R_ARM_REL32_NOI.
	(allocate_dynrelocs_for_symbol): Update comment.
	(elf32_arm_gc_sweep_hook): For all reloc types with pc_relative
	set in the howto, set call_reloc_p and may_need_local_target_p but
	not may_become_dynamic_p; not only for R_ARM_REL32 and R_ARM_REL32_NOI.
	(elf32_arm_check_relocs): Likewise.

ld/testsuite/
	PR ld/17277
	* ld-arm/pcrel-shared.s: New file.
	* ld-arm/pcrel-shared.rd: New file.
	* ld-arm/arm-elf.exp (armelftests_common): Add it.
This commit is contained in:
Roland McGrath
2014-08-20 10:12:57 -07:00
parent 01e6c1a48d
commit 469a34932a
6 changed files with 76 additions and 12 deletions

View File

@ -1,3 +1,15 @@
2014-08-20 Roland McGrath <mcgrathr@google.com>
PR ld/17277
* elf32-arm.c (elf32_arm_check_relocs): Increment P->pc_count for
all reloc types with pc_relative set in the howto, not just for
R_ARM_REL32 and R_ARM_REL32_NOI.
(allocate_dynrelocs_for_symbol): Update comment.
(elf32_arm_gc_sweep_hook): For all reloc types with pc_relative
set in the howto, set call_reloc_p and may_need_local_target_p but
not may_become_dynamic_p; not only for R_ARM_REL32 and R_ARM_REL32_NOI.
(elf32_arm_check_relocs): Likewise.
2014-08-20 Will Newton <will.newton@linaro.org> 2014-08-20 Will Newton <will.newton@linaro.org>
* config.bfd: Default armeb-*-eabi* to big endian. * config.bfd: Default armeb-*-eabi* to big endian.

View File

@ -2172,7 +2172,7 @@ static const bfd_vma elf32_thumb2_plt0_entry [] =
an instruction maybe encoded to one or two array elements. */ an instruction maybe encoded to one or two array elements. */
0xf8dfb500, /* push {lr} */ 0xf8dfb500, /* push {lr} */
0x44fee008, /* ldr.w lr, [pc, #8] */ 0x44fee008, /* ldr.w lr, [pc, #8] */
/* add lr, pc */ /* add lr, pc */
0xff08f85e, /* ldr.w pc, [lr, #8]! */ 0xff08f85e, /* ldr.w pc, [lr, #8]! */
0x00000000, /* &GOT[0] - . */ 0x00000000, /* &GOT[0] - . */
}; };
@ -2187,7 +2187,7 @@ static const bfd_vma elf32_thumb2_plt_entry [] =
0x0c00f2c0, /* movt ip, #0xNNNN */ 0x0c00f2c0, /* movt ip, #0xNNNN */
0xf8dc44fc, /* add ip, pc */ 0xf8dc44fc, /* add ip, pc */
0xbf00f000 /* ldr.w pc, [ip] */ 0xbf00f000 /* ldr.w pc, [ip] */
/* nop */ /* nop */
}; };
/* The format of the first entry in the procedure linkage table /* The format of the first entry in the procedure linkage table
@ -7760,7 +7760,7 @@ elf32_arm_populate_plt_entry (bfd *output_bfd, struct bfd_link_info *info,
else if (using_thumb_only (htab)) else if (using_thumb_only (htab))
{ {
/* PR ld/16017: Generate thumb only PLT entries. */ /* PR ld/16017: Generate thumb only PLT entries. */
if (!using_thumb2 (htab)) if (!using_thumb2 (htab))
{ {
/* FIXME: We ought to be able to generate thumb-1 PLT /* FIXME: We ought to be able to generate thumb-1 PLT
instructions... */ instructions... */
@ -12500,7 +12500,7 @@ elf32_arm_gc_sweep_hook (bfd * abfd,
&& (sec->flags & SEC_ALLOC) != 0) && (sec->flags & SEC_ALLOC) != 0)
{ {
if (h == NULL if (h == NULL
&& (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) && elf32_arm_howto_from_type (r_type)->pc_relative)
{ {
call_reloc_p = TRUE; call_reloc_p = TRUE;
may_need_local_target_p = TRUE; may_need_local_target_p = TRUE;
@ -12826,7 +12826,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
&& (sec->flags & SEC_ALLOC) != 0) && (sec->flags & SEC_ALLOC) != 0)
{ {
if (h == NULL if (h == NULL
&& (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI)) && elf32_arm_howto_from_type (r_type)->pc_relative)
{ {
/* In shared libraries and relocatable executables, /* In shared libraries and relocatable executables,
we treat local relative references as calls; we treat local relative references as calls;
@ -12972,7 +12972,7 @@ elf32_arm_check_relocs (bfd *abfd, struct bfd_link_info *info,
p->pc_count = 0; p->pc_count = 0;
} }
if (r_type == R_ARM_REL32 || r_type == R_ARM_REL32_NOI) if (elf32_arm_howto_from_type (r_type)->pc_relative)
p->pc_count += 1; p->pc_count += 1;
p->count += 1; p->count += 1;
} }
@ -13551,12 +13551,12 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
if (info->shared || htab->root.is_relocatable_executable) if (info->shared || htab->root.is_relocatable_executable)
{ {
/* The only relocs that use pc_count are R_ARM_REL32 and /* Relocs that use pc_count are PC-relative forms, which will appear
R_ARM_REL32_NOI, which will appear on something like on something like ".long foo - ." or "movw REG, foo - .". We want
".long foo - .". We want calls to protected symbols to resolve calls to protected symbols to resolve directly to the function
directly to the function rather than going via the plt. If people rather than going via the plt. If people want function pointer
want function pointer comparisons to work as expected then they comparisons to work as expected then they should avoid writing
should avoid writing assembly like ".long foo - .". */ assembly like ".long foo - .". */
if (SYMBOL_CALLS_LOCAL (info, h)) if (SYMBOL_CALLS_LOCAL (info, h))
{ {
struct elf_dyn_relocs **pp; struct elf_dyn_relocs **pp;

View File

@ -1,3 +1,10 @@
2014-08-20 Roland McGrath <mcgrathr@google.com>
PR ld/17277
* ld-arm/pcrel-shared.s: New file.
* ld-arm/pcrel-shared.rd: New file.
* ld-arm/arm-elf.exp (armelftests_common): Add it.
2014-08-18 Alan Modra <amodra@gmail.com> 2014-08-18 Alan Modra <amodra@gmail.com>
* ld-plugin/lto.exp: Use gcc -print-file-name to find lto plugin. * ld-plugin/lto.exp: Use gcc -print-file-name to find lto plugin.

View File

@ -203,6 +203,10 @@ set armelftests_common {
{"EABI ABI flags ld -r" "-r" "" "-mfloat-abi=soft -meabi=5" {eabi-soft-float.s} {"EABI ABI flags ld -r" "-r" "" "-mfloat-abi=soft -meabi=5" {eabi-soft-float.s}
{{readelf -h eabi-soft-float-r.d}} {{readelf -h eabi-soft-float-r.d}}
"eabi-soft-float-r.o"} "eabi-soft-float-r.o"}
{"PC-relative in -shared" "-shared" ""
"" {pcrel-shared.s}
{{readelf -dr pcrel-shared.rd}}
"pcrel-shared.so"}
} }
set armelftests_nonacl { set armelftests_nonacl {

View File

@ -0,0 +1,16 @@
Dynamic section at offset 0x[0-9a-f]+ contains \d+ entries:
\s+Tag\s+Type\s+Name/Value
\s*0x[0-9a-f]+ \(HASH\).*
\s*0x[0-9a-f]+ \(STRTAB\).*
\s*0x[0-9a-f]+ \(SYMTAB\).*
\s*0x[0-9a-f]+ \(STRSZ\).*
\s*0x[0-9a-f]+ \(SYMENT\).*
# Specifically want *not* to see here:
# (REL)
# (RELSZ)
# (RELENT)
# (TEXTREL)
#...
\s*0x[0-9a-f]+ \(NULL\).*
There are no relocations in this file\.

View File

@ -0,0 +1,25 @@
# This tests PR ld/17277, wherein ld -shared for cross-section PC-relative
# relocs (other than plain R_ARM_REL32, as in data) produce bogus dynamic
# relocs and TEXTREL markers.
.syntax unified
.arm
.arch armv7-a
.text
.globl foo
.type foo,%function
foo: movw r0, #:lower16:symbol - 1f - 8
movt r0, #:upper16:symbol - 1f - 8
1: add r0, pc
@ And now a case with a local symbol.
movw r0, #:lower16:3f - 2f - 8
movt r0, #:upper16:3f - 2f - 8
2: add r0, pc
bx lr
.data
.globl symbol
.hidden symbol
symbol: .long 23
3: .long 17