aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2018-02-05 08:38:16 -0800
committerH.J. Lu <hjl.tools@gmail.com>2018-02-05 08:38:16 -0800
commitcd04836359da82ae1dc67e5a05565536f4427b51 (patch)
treefc72f6593a58e26174caadbfe9515204901fb318 /bfd
parentb8df6ca79e69678a07d3216b9b2b552fce27cda8 (diff)
downloadgdb-cd04836359da82ae1dc67e5a05565536f4427b51.zip
gdb-cd04836359da82ae1dc67e5a05565536f4427b51.tar.gz
gdb-cd04836359da82ae1dc67e5a05565536f4427b51.tar.bz2
x86: Remove the unused _GLOBAL_OFFSET_TABLE_
Since _GLOBAL_OFFSET_TABLE_ may be referenced implicitly on x86, checking ref_regular_nonweak leaves the unused _GLOBAL_OFFSET_TABLE_ in output. This patch checks explicit GOT references instead. ld-i386/discarded1.s and ld-x86-64/discarded1.s are updated to avoid linker optimization which removes GOT references. bfd/ PR ld/22782 * elf32-i386.c (elf_i386_check_relocs): Set got_referenced if _GLOBAL_OFFSET_TABLE_ is referenced or GOT is needed to resolve undefined weak symbol to 0. * elf64-x86-64.c (elf_x86_64_check_relocs): Set got_referenced if _GLOBAL_OFFSET_TABLE_ is referenced. * elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Check got_referenced instead of ref_regular_nonweak. Remove the unused _GLOBAL_OFFSET_TABLE_ from symbol table. * elfxx-x86.h (elf_x86_link_hash_table): Add got_referenced. ld/ PR ld/22782 * testsuite/ld-i386/discarded1.s: Replace mov with div. * testsuite/ld-x86-64/discarded1.s: Likewise. * testsuite/ld-i386/i386.exp: Run pr22782. * testsuite/ld-i386/load1-nacl.d: Updated for removing _GLOBAL_OFFSET_TABLE_ from output. * testsuite/ld-i386/load1.d: Likewise. * testsuite/ld-x86-64/load1a-nacl.d: Likewise. * testsuite/ld-x86-64/load1a.d: Likewise. * testsuite/ld-x86-64/load1b-nacl.d: Likewise. * testsuite/ld-x86-64/load1b.d: Likewise. * testsuite/ld-i386/pr22782.d: New file. * testsuite/ld-i386/pr22782.s: Likewise. * testsuite/ld-x86-64/pr22782.s: Likewise. * testsuite/ld-x86-64/pr22782a.d: Likewise. * testsuite/ld-x86-64/pr22782b.d: Likewise. * testsuite/ld-x86-64/x86-64.exp: Run pr22782a and pr22782b.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog13
-rw-r--r--bfd/elf32-i386.c16
-rw-r--r--bfd/elf64-x86-64.c4
-rw-r--r--bfd/elfxx-x86.c17
-rw-r--r--bfd/elfxx-x86.h3
5 files changed, 49 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ecd1c7b..e9accbd 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,16 @@
+2018-02-05 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/22782
+ * elf32-i386.c (elf_i386_check_relocs): Set got_referenced if
+ _GLOBAL_OFFSET_TABLE_ is referenced or GOT is needed to resolve
+ undefined weak symbol to 0.
+ * elf64-x86-64.c (elf_x86_64_check_relocs): Set got_referenced
+ if _GLOBAL_OFFSET_TABLE_ is referenced.
+ * elfxx-x86.c (_bfd_x86_elf_size_dynamic_sections): Check
+ got_referenced instead of ref_regular_nonweak. Remove the
+ unused _GLOBAL_OFFSET_TABLE_ from symbol table.
+ * elfxx-x86.h (elf_x86_link_hash_table): Add got_referenced.
+
2018-02-05 Maciej W. Rozycki <macro@mips.com>
* elfnn-riscv.c (_bfd_riscv_relax_pc): Use `memset' to
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 1f380db..1bdf3d4 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1578,6 +1578,10 @@ elf_i386_check_relocs (bfd *abfd,
rel, rel_end, h, r_symndx, FALSE))
goto error_return;
+ /* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
+ if (h == htab->elf.hgot)
+ htab->got_referenced = TRUE;
+
switch (r_type)
{
case R_386_TLS_LDM:
@@ -1720,11 +1724,19 @@ elf_i386_check_relocs (bfd *abfd,
case R_386_GOTOFF:
case R_386_GOTPC:
- create_got:
+create_got:
if (r_type != R_386_TLS_IE)
{
if (eh != NULL)
- eh->zero_undefweak &= 0x2;
+ {
+ eh->zero_undefweak &= 0x2;
+
+ /* Need GOT to resolve undefined weak symbol to 0. */
+ if (r_type == R_386_GOTOFF
+ && h->root.type == bfd_link_hash_undefweak
+ && bfd_link_executable (info))
+ htab->got_referenced = TRUE;
+ }
break;
}
/* Fall through */
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index ba4f47b..aad9b85 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -1927,6 +1927,10 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
rel, rel_end, h, r_symndx, FALSE))
goto error_return;
+ /* Check if _GLOBAL_OFFSET_TABLE_ is referenced. */
+ if (h == htab->elf.hgot)
+ htab->got_referenced = TRUE;
+
eh = (struct elf_x86_link_hash_entry *) h;
switch (r_type)
{
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index a7db5d9..dbda542 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -1086,7 +1086,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
/* Don't allocate .got.plt section if there are no GOT nor PLT
entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */
if ((htab->elf.hgot == NULL
- || !htab->elf.hgot->ref_regular_nonweak)
+ || !htab->got_referenced)
&& (htab->elf.sgotplt->size == bed->got_header_size)
&& (htab->elf.splt == NULL
|| htab->elf.splt->size == 0)
@@ -1096,7 +1096,20 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
|| htab->elf.iplt->size == 0)
&& (htab->elf.igotplt == NULL
|| htab->elf.igotplt->size == 0))
- htab->elf.sgotplt->size = 0;
+ {
+ htab->elf.sgotplt->size = 0;
+ if (htab->elf.hgot != NULL)
+ {
+ /* Remove the unused _GLOBAL_OFFSET_TABLE_ from symbol
+ table. */
+ htab->elf.hgot->root.type = bfd_link_hash_undefined;
+ htab->elf.hgot->root.u.undef.abfd
+ = htab->elf.hgot->root.u.def.section->owner;
+ htab->elf.hgot->root.linker_def = 0;
+ htab->elf.hgot->ref_regular = 0;
+ htab->elf.hgot->def_regular = 0;
+ }
+ }
}
if (_bfd_elf_eh_frame_present (info))
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index e2a83ad..b515ee6 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -478,6 +478,9 @@ struct elf_x86_link_hash_table
is only used for i386. */
bfd_byte plt0_pad_byte;
+ /* TRUE if GOT is referenced. */
+ unsigned int got_referenced : 1;
+
bfd_vma (*r_info) (bfd_vma, bfd_vma);
bfd_vma (*r_sym) (bfd_vma);
bfd_boolean (*is_reloc_section) (const char *);