From b436d85411e682b845d3d0d1d385e00504a4411a Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Mon, 14 Mar 2011 15:52:53 +0000 Subject: [PATCH] bfd/ * elf32-arm.c (elf32_arm_final_link_relocate): Always fill in the GOT entry here, rather than leaving it to finish_dynamic_symbol. Only create a dynamic relocation for local references if info->shared. (allocate_dynrelocs_for_symbol): Update dynamic relocation allocation accordingly. (elf32_arm_finish_dynamic_symbol): Don't initialise the GOT entry here. ld/testsuite/ * ld-arm/exec-got-1a.s, ld-arm/exec-got-1b.s, ld-arm/exec-got-1.d, ld-arm/unresolved-1.s, ld-arm/unresolved-1.d, ld-arm/unresolved-1-dyn.d: New tests. * ld-arm/arm-elf.exp: Run them. --- bfd/ChangeLog | 10 ++ bfd/elf32-arm.c | 139 +++++++++++-------------- ld/testsuite/ChangeLog | 7 ++ ld/testsuite/ld-arm/arm-elf.exp | 10 ++ ld/testsuite/ld-arm/exec-got-1.d | 4 + ld/testsuite/ld-arm/exec-got-1a.s | 5 + ld/testsuite/ld-arm/exec-got-1b.s | 10 ++ ld/testsuite/ld-arm/unresolved-1-dyn.d | 8 ++ ld/testsuite/ld-arm/unresolved-1.d | 8 ++ ld/testsuite/ld-arm/unresolved-1.s | 6 ++ 10 files changed, 127 insertions(+), 80 deletions(-) create mode 100644 ld/testsuite/ld-arm/exec-got-1.d create mode 100644 ld/testsuite/ld-arm/exec-got-1a.s create mode 100644 ld/testsuite/ld-arm/exec-got-1b.s create mode 100644 ld/testsuite/ld-arm/unresolved-1-dyn.d create mode 100644 ld/testsuite/ld-arm/unresolved-1.d create mode 100644 ld/testsuite/ld-arm/unresolved-1.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4412a176419..bb59da14525 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2011-03-14 Richard Sandiford + + * elf32-arm.c (elf32_arm_final_link_relocate): Always fill in the + GOT entry here, rather than leaving it to finish_dynamic_symbol. + Only create a dynamic relocation for local references if + info->shared. + (allocate_dynrelocs_for_symbol): Update dynamic relocation + allocation accordingly. + (elf32_arm_finish_dynamic_symbol): Don't initialise the GOT entry here. + 2011-03-14 Richard Sandiford * elf32-arm.c (elf32_arm_allocate_dynrelocs): New function. diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 1a967312a8f..13830901875 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -8278,45 +8278,67 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto, if (h != NULL) { bfd_vma off; - bfd_boolean dyn; off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); - dyn = globals->root.dynamic_sections_created; - - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - || (info->shared - && SYMBOL_REFERENCES_LOCAL (info, h)) - || (ELF_ST_VISIBILITY (h->other) - && h->root.type == bfd_link_hash_undefweak)) + if ((off & 1) != 0) { - /* This is actually a static link, or it is a -Bsymbolic link - and the symbol is defined locally. We must initialize this - entry in the global offset table. Since the offset must - always be a multiple of 4, we use the least significant bit - to record whether we have initialized it already. - - When doing a dynamic link, we create a .rel(a).got relocation - entry to initialize the value. This is done in the - finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; + /* We have already processsed one GOT relocation against + this symbol. */ + off &= ~1; + if (globals->root.dynamic_sections_created + && !SYMBOL_REFERENCES_LOCAL (info, h)) + *unresolved_reloc_p = FALSE; + } + else + { + Elf_Internal_Rela outrel; + + if (!SYMBOL_REFERENCES_LOCAL (info, h)) + { + /* If the symbol doesn't resolve locally in a static + object, we have an undefined reference. If the + symbol doesn't resolve locally in a dynamic object, + it should be resolved by the dynamic linker. */ + if (globals->root.dynamic_sections_created) + { + outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT); + *unresolved_reloc_p = FALSE; + } + else + outrel.r_info = 0; + outrel.r_addend = 0; + } else { - /* If we are addressing a Thumb function, we need to - adjust the address by one, so that attempts to - call the function pointer will correctly - interpret it as Thumb code. */ + if (info->shared) + outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); + else + outrel.r_info = 0; + outrel.r_addend = value; if (sym_flags == STT_ARM_TFUNC) - value |= 1; + outrel.r_addend |= 1; + } - bfd_put_32 (output_bfd, value, sgot->contents + off); - h->got.offset |= 1; + /* The GOT entry is initialized to zero by default. + See if we should install a different value. */ + if (outrel.r_addend != 0 + && (outrel.r_info == 0 || globals->use_rel)) + { + bfd_put_32 (output_bfd, outrel.r_addend, + sgot->contents + off); + outrel.r_addend = 0; } - } - else - *unresolved_reloc_p = FALSE; + if (outrel.r_info != 0) + { + outrel.r_offset = (sgot->output_section->vma + + sgot->output_offset + + off); + elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel); + } + h->got.offset |= 1; + } value = sgot->output_offset + off; } else @@ -12222,10 +12244,14 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf) if ((tls_type & GOT_TLS_GD) && indx != 0) elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1); } - else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || h->root.type != bfd_link_hash_undefweak) - && (info->shared - || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) + else if (!SYMBOL_REFERENCES_LOCAL (info, h)) + { + if (htab->root.dynamic_sections_created) + /* Reserve room for the GOT entry's R_ARM_GLOB_DAT relocation. */ + elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1); + } + else if (info->shared) + /* Reserve room for the GOT entry's R_ARM_RELATIVE relocation. */ elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1); } } @@ -13016,53 +13042,6 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd, } } - if (h->got.offset != (bfd_vma) -1 - && (! GOT_TLS_GD_ANY_P (elf32_arm_hash_entry (h)->tls_type)) - && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0) - { - asection * sgot; - asection * srel; - Elf_Internal_Rela rel; - bfd_vma offset; - - /* This symbol has an entry in the global offset table. Set it - up. */ - sgot = htab->root.sgot; - srel = htab->root.srelgot; - BFD_ASSERT (sgot != NULL && srel != NULL); - - offset = (h->got.offset & ~(bfd_vma) 1); - rel.r_addend = 0; - rel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + offset); - - /* 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 - && SYMBOL_REFERENCES_LOCAL (info, h)) - { - BFD_ASSERT ((h->got.offset & 1) != 0); - rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE); - if (!htab->use_rel) - { - rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + offset); - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset); - } - } - else - { - BFD_ASSERT ((h->got.offset & 1) == 0); - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset); - rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT); - } - - elf32_arm_add_dynreloc (output_bfd, info, srel, &rel); - } - if (h->needs_copy) { asection * s; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 603089ceddd..fdeaf77c1b9 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-03-14 Richard Sandiford + + * ld-arm/exec-got-1a.s, ld-arm/exec-got-1b.s, ld-arm/exec-got-1.d, + ld-arm/unresolved-1.s, ld-arm/unresolved-1.d, + ld-arm/unresolved-1-dyn.d: New tests. + * ld-arm/arm-elf.exp: Run them. + 2011-03-12 H.J. Lu * ld-x86-64/tlsgd4.dd: New. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 798b2cb5af3..dcdc2310d44 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -295,6 +295,14 @@ set armelftests { {"Data only mapping symbols" "-T data-only-map.ld -Map map" "" {data-only-map.s} {{objdump -dr data-only-map.d}} "data-only-map"} + {"GOT relocations in executables (setup)" "-shared" + "" {exec-got-1a.s} + {} + "exec-got-1.so"} + {"GOT relocations in executables" "tmpdir/exec-got-1.so" + "" {exec-got-1b.s} + {{readelf --relocs exec-got-1.d}} + "exec-got-1"} } run_ld_link_tests $armelftests @@ -582,3 +590,5 @@ run_dump_test "attr-merge-vfp-5r" run_dump_test "attr-merge-vfp-6" run_dump_test "attr-merge-vfp-6r" run_dump_test "attr-merge-incompatible" +run_dump_test "unresolved-1" +run_dump_test "unresolved-1-dyn" diff --git a/ld/testsuite/ld-arm/exec-got-1.d b/ld/testsuite/ld-arm/exec-got-1.d new file mode 100644 index 00000000000..af067d3dd29 --- /dev/null +++ b/ld/testsuite/ld-arm/exec-got-1.d @@ -0,0 +1,4 @@ + +Relocation section '\.rel\.dyn' .* + Offset .* +.* R_ARM_GLOB_DAT * 00000000 * foo diff --git a/ld/testsuite/ld-arm/exec-got-1a.s b/ld/testsuite/ld-arm/exec-got-1a.s new file mode 100644 index 00000000000..6a7637c2fbf --- /dev/null +++ b/ld/testsuite/ld-arm/exec-got-1a.s @@ -0,0 +1,5 @@ + .globl foo + .type foo,%object + .size foo,4 + .data +foo: .word 1 diff --git a/ld/testsuite/ld-arm/exec-got-1b.s b/ld/testsuite/ld-arm/exec-got-1b.s new file mode 100644 index 00000000000..71546d74a01 --- /dev/null +++ b/ld/testsuite/ld-arm/exec-got-1b.s @@ -0,0 +1,10 @@ + .globl _start + .type _start,%function +_start: + ldr r1,1f + ldr r1,2f +1: + .word foo(GOT) +2: + .word _start(GOT) + .size _start,.-_start diff --git a/ld/testsuite/ld-arm/unresolved-1-dyn.d b/ld/testsuite/ld-arm/unresolved-1-dyn.d new file mode 100644 index 00000000000..21cd9599c68 --- /dev/null +++ b/ld/testsuite/ld-arm/unresolved-1-dyn.d @@ -0,0 +1,8 @@ +#source: unresolved-1.s +#ld: --warn-unresolved tmpdir/mixed-lib.so +#warning: \(\.text\+0x8\): warning: undefined reference to `foo' +#readelf: -r + +Relocation section '\.rel\.dyn' .* + Offset .* +.* R_ARM_GLOB_DAT +00000000 +foo diff --git a/ld/testsuite/ld-arm/unresolved-1.d b/ld/testsuite/ld-arm/unresolved-1.d new file mode 100644 index 00000000000..cfc1b04c0d7 --- /dev/null +++ b/ld/testsuite/ld-arm/unresolved-1.d @@ -0,0 +1,8 @@ +#ld: --warn-unresolved +#warning: \(\.text\+0x8\): warning: undefined reference to `foo' +#objdump: -sj.rel.dyn -sj.got + +.* + +Contents of section \.got: + *[^ ]* 00000000 00000000 00000000 00000000 .* diff --git a/ld/testsuite/ld-arm/unresolved-1.s b/ld/testsuite/ld-arm/unresolved-1.s new file mode 100644 index 00000000000..4db4aea840f --- /dev/null +++ b/ld/testsuite/ld-arm/unresolved-1.s @@ -0,0 +1,6 @@ + .globl _start +_start: + ldr r4,1f + mov pc,lr +1: + .word foo(GOT) -- 2.30.2