aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-i386.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-04-21 12:03:14 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-04-21 12:03:26 -0700
commite133d00576f3da89e7772149e8d2b6a059d26919 (patch)
treeb1ac9f41d4f96706a1806d54cf45095651d0b811 /bfd/elf32-i386.c
parent3c5fce9bc29b216af7d10f8d6e4d8c3f11a48359 (diff)
downloadgdb-e133d00576f3da89e7772149e8d2b6a059d26919.zip
gdb-e133d00576f3da89e7772149e8d2b6a059d26919.tar.gz
gdb-e133d00576f3da89e7772149e8d2b6a059d26919.tar.bz2
i386: Avoid dynamic symbol with GOT reference in PIE
GOT reference to global symbol in PIE will lead to dynamic symbol. It becomes a problem when "time" or "times" is defined as a variable in an executable, clashing with functions of the same name in libc. If a symbol isn't undefined weak symbol, don't make it dynamic in PIE and generate R_386_RELATIVE relocation. bfd/ PR ld/21402 * elf32-i386.c (elf_i386_link_hash_entry): Add no_finish_dynamic_symbol. (elf_i386_link_hash_newfunc): Set no_finish_dynamic_symbol to 0. (elf_i386_allocate_dynrelocs): If a symbol isn't undefined weak symbol, don't make it dynamic in PIE. (elf_i386_relocate_section): If a symbol isn't dynamic in PIE, set no_finish_dynamic_symbol and generate R_386_RELATIVE relocation for R_386_GOT32 (elf_i386_finish_dynamic_symbol): Abort if no_finish_dynamic_symbol isn't 0. ld/ PR ld/21402 * testsuite/ld-elf/indirect.exp: Don't skip PIE indirect5 and indirect6 tests on i386.
Diffstat (limited to 'bfd/elf32-i386.c')
-rw-r--r--bfd/elf32-i386.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 7af6863..9e71974 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -820,6 +820,9 @@ struct elf_i386_link_hash_entry
/* Symbol has non-GOT/non-PLT relocations in text sections. */
unsigned int has_non_got_reloc : 1;
+ /* Don't call finish_dynamic_symbol on this symbol. */
+ unsigned int no_finish_dynamic_symbol : 1;
+
/* 0: symbol isn't ___tls_get_addr.
1: symbol is ___tls_get_addr.
2: symbol is unknown. */
@@ -959,6 +962,7 @@ elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
eh->gotoff_ref = 0;
eh->has_got_reloc = 0;
eh->has_non_got_reloc = 0;
+ eh->no_finish_dynamic_symbol = 0;
eh->tls_get_addr = 2;
eh->func_pointer_refcount = 0;
eh->plt_got.offset = (bfd_vma) -1;
@@ -2863,10 +2867,14 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
int tls_type = elf_i386_hash_entry(h)->tls_type;
/* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
+ Undefined weak syms won't yet be marked as dynamic.
+ PR ld/21402: If this symbol isn't undefined weak symbol,
+ don't make it dynamic in PIE. */
if (h->dynindx == -1
&& !h->forced_local
- && !resolved_to_zero)
+ && !resolved_to_zero
+ && (h->root.type == bfd_link_hash_undefweak
+ || !bfd_link_pie (info)))
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
@@ -3818,6 +3826,7 @@ elf_i386_relocate_section (bfd *output_bfd,
bfd_vma st_size;
asection *resolved_plt;
bfd_boolean resolved_to_zero;
+ bfd_boolean relative_reloc;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_386_GNU_VTINHERIT
@@ -4268,6 +4277,7 @@ r_386_got32:
if (htab->elf.sgot == NULL)
abort ();
+ relative_reloc = FALSE;
if (h != NULL)
{
bfd_boolean dyn;
@@ -4301,6 +4311,17 @@ r_386_got32:
bfd_put_32 (output_bfd, relocation,
htab->elf.sgot->contents + off);
h->got.offset |= 1;
+
+ if (h->dynindx == -1
+ && !h->forced_local
+ && h->root.type != bfd_link_hash_undefweak
+ && bfd_link_pie (info))
+ {
+ /* PR ld/21402: If this symbol isn't dynamic
+ in PIE, generate R_386_RELATIVE here. */
+ eh->no_finish_dynamic_symbol = 1;
+ relative_reloc = TRUE;
+ }
}
}
else
@@ -4322,27 +4343,29 @@ r_386_got32:
{
bfd_put_32 (output_bfd, relocation,
htab->elf.sgot->contents + off);
+ local_got_offsets[r_symndx] |= 1;
if (bfd_link_pic (info))
- {
- asection *s;
- Elf_Internal_Rela outrel;
-
- s = htab->elf.srelgot;
- if (s == NULL)
- abort ();
-
- outrel.r_offset = (htab->elf.sgot->output_section->vma
- + htab->elf.sgot->output_offset
- + off);
- outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
- elf_append_rel (output_bfd, s, &outrel);
- }
-
- local_got_offsets[r_symndx] |= 1;
+ relative_reloc = TRUE;
}
}
+ if (relative_reloc)
+ {
+ asection *s;
+ Elf_Internal_Rela outrel;
+
+ s = htab->elf.srelgot;
+ if (s == NULL)
+ abort ();
+
+ outrel.r_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off);
+ outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ elf_append_rel (output_bfd, s, &outrel);
+ }
+
if (off >= (bfd_vma) -2)
abort ();
@@ -5321,6 +5344,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd);
eh = (struct elf_i386_link_hash_entry *) h;
+ if (eh->no_finish_dynamic_symbol)
+ abort ();
/* We keep PLT/GOT entries without dynamic PLT/GOT relocations for
resolved undefined weak symbols in executable so that their