Check symbol defined by assignment in linker script
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 26 Oct 2015 23:32:34 +0000 (16:32 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 26 Oct 2015 23:32:55 +0000 (16:32 -0700)
Symbol symbol defined by an assignment in a linker script has type
bfd_link_hash_new.  elf_i386_convert_load and elf_x86_64_convert_load
should check bfd_link_hash_new to see if a symbol is defined by a linker
script.

bfd/

PR ld/19175
* elf32-i386.c (elf_i386_convert_load): Check bfd_link_hash_new
instead of calling bfd_link_get_defined_symbol.
* elf64-x86-64.c (elf_x86_64_convert_load): Likewise.  Skip
relocation overflow for bfd_link_hash_new.
* linker.c (bfd_link_get_defined_symbol): Removed.
* bfd-in2.h: Regenerated.

ld/testsuite/

PR ld/19175
* ld-i386/i386.exp: Run pr19175.
* ld-x86-64/x86-64.exp: Likewise.
* ld-i386/pr19175.d: New file.
* ld-i386/pr19175.s: Likewise.
* ld-i386/pr19175.t: Likewise.
* ld-x86-64/pr19175.d: Likewise.
* ld-x86-64/pr19175.s: Likewise.
* ld-x86-64/pr19175.t: Likewise.

14 files changed:
bfd/ChangeLog
bfd/bfd-in2.h
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/linker.c
ld/testsuite/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/pr19175.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr19175.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr19175.t [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19175.d [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19175.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/pr19175.t [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index c838043d808b3345ec798cc22ea10cea4bdfb377..29c974d6322447fb4b897516ac0b861c965c0562 100644 (file)
@@ -1,3 +1,13 @@
+2015-10-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19175
+       * elf32-i386.c (elf_i386_convert_load): Check bfd_link_hash_new
+       instead of calling bfd_link_get_defined_symbol.
+       * elf64-x86-64.c (elf_x86_64_convert_load): Likewise.  Skip
+       relocation overflow for bfd_link_hash_new.
+       * linker.c (bfd_link_get_defined_symbol): Removed.
+       * bfd-in2.h: Regenerated.
+
 2015-10-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/19171
index 57d31f291389258a88ac83929d84c9da12d6b6df..9345e8846c4b4eb77b90359c29fe51d94a0cf3d3 100644 (file)
@@ -7515,10 +7515,6 @@ struct bfd_elf_version_tree * bfd_find_version_for_sym
 bfd_boolean bfd_hide_sym_by_version
    (struct bfd_elf_version_tree *verdefs, const char *sym_name);
 
-bfd_boolean bfd_link_get_defined_symbol
-   (struct bfd_link_info *info, struct bfd_link_hash_entry *h,
-    asection **sec, bfd_vma *value);
-
 /* Extracted from simple.c.  */
 bfd_byte *bfd_simple_get_relocated_section_contents
    (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
index 9717062307725a337335617ba758d7e570698485..fca7663ba99ffc56aa2aa1f6826a96ef213e0e1b 100644 (file)
@@ -2976,8 +2976,11 @@ convert_branch:
          if (h == htab->elf.hdynamic)
            continue;
 
-         if (bfd_link_get_defined_symbol (link_info, &h->root, NULL,
-                                          NULL)
+         /* bfd_link_hash_new is set by an assignment in a linker
+            script in bfd_elf_record_link_assignment.  */
+         if ((h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak
+              || h->root.type == bfd_link_hash_new)
              && SYMBOL_REFERENCES_LOCAL (link_info, h))
            {
 convert_load:
index 9778f2fa49604db6ece9a6482f41cb7c550db980..deaee91a8d31af82635869571917ce42a2df5277 100644 (file)
@@ -3116,8 +3116,6 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
        }
       else
        {
-         bfd_boolean defined;
-
          indx = r_symndx - symtab_hdr->sh_info;
          h = elf_sym_hashes (abfd)[indx];
          BFD_ASSERT (h != NULL);
@@ -3126,17 +3124,26 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-         defined = bfd_link_get_defined_symbol (link_info, &h->root,
-                                                &tsec, &toff);
-
          /* STT_GNU_IFUNC must keep GOTPCREL relocations.  We also
             avoid optimizing GOTPCREL relocations againt _DYNAMIC
             since ld.so may use its link-time address.  */
-         if (defined
+         if ((h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak
+              || h->root.type == bfd_link_hash_new)
              && h->type != STT_GNU_IFUNC
              && h != htab->elf.hdynamic
              && SYMBOL_REFERENCES_LOCAL (link_info, h))
-           symtype = h->type;
+           {
+             /* bfd_link_hash_new is set by an assignment in a linker
+                script in bfd_elf_record_link_assignment.  FIXME: If
+                we ever get a linker error due relocation overflow, we
+                will skip this optimization.  */
+             if (h->root.type == bfd_link_hash_new)
+               goto convert;
+             tsec = h->root.u.def.section;
+             toff = h->root.u.def.value;
+             symtype = h->type;
+           }
          else
            continue;
        }
@@ -3213,6 +3220,7 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
            continue;
        }
 
+convert:
       if (opcode == 0xff)
        {
          /* We have "call/jmp *foo@GOTPCREL(%rip)".  */
index f2290e0ccdf99210fb81f864e2ec3f3f50c47d4a..86a7a1945ba7527b4280045c51472d1a9dc44435 100644 (file)
@@ -3303,92 +3303,3 @@ bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs,
   bfd_find_version_for_sym (verdefs, sym_name, &hidden);
   return hidden;
 }
-
-/*
-FUNCTION
-       bfd_link_get_defined_symbol
-
-SYNOPSIS
-       bfd_boolean bfd_link_get_defined_symbol
-         (struct bfd_link_info *info, struct bfd_link_hash_entry *h,
-          asection **sec, bfd_vma *value);
-
-DESCRIPTION
-       Return TRUE, store symbol section and value in @var{*sec} and
-       @var{*value} if symbol @var{h} is defined during a final link.
-*/
-
-bfd_boolean
-bfd_link_get_defined_symbol (struct bfd_link_info *info,
-                            struct bfd_link_hash_entry *h,
-                            asection **sec, bfd_vma *value)
-{
-  if (h->type == bfd_link_hash_defined
-      || h->type == bfd_link_hash_defweak)
-    {
-      if (sec)
-       *sec = h->u.def.section;
-      if (value)
-       *value = h->u.def.value;
-      return TRUE;
-    }
-
-  if (h->type == bfd_link_hash_new
-      || h->type == bfd_link_hash_undefined
-      || h->type == bfd_link_hash_undefweak)
-    {
-      /* Check yet undefined reference to __start_XXX or __stop_XXX
-        symbols.  The linker will later define such symbols for output
-        sections that have a name representable as a C identifier.  */
-      const char *sec_name;
-      if (strncmp (h->root.string, "__start_", 8) == 0)
-       sec_name = h->root.string + 8;
-      else if (strncmp (h->root.string, "__stop_", 7) == 0)
-       sec_name = h->root.string + 7;
-      else
-       sec_name = NULL;
-
-      if (sec_name != NULL && *sec_name != '\0')
-       {
-         bfd *i;
-
-         for (i = info->input_bfds; i != NULL; i = i->link.next)
-           {
-             asection *s = bfd_get_section_by_name (i, sec_name);
-             if (s != NULL)
-               {
-                 asection *asect;
-                 bfd_vma size;
-
-                 if (sec)
-                   *sec = s;
-
-                 if (!value)
-                   return TRUE;
-                 if (sec_name == (h->root.string + 8))
-                   {
-                     /* Set __start_XXX symbol value.  */
-                     *value = 0;
-                     return TRUE;
-                   }
-
-                 /* Get the size of the output XXX section for
-                    __stop_XXX symbol value.  */
-                 size = 0;
-                 for (asect = s->output_section->map_head.s;
-                      asect != NULL;
-                      asect = asect->map_head.s)
-                   {
-                     size = align_power (size, asect->alignment_power);
-                     size += asect->size;
-                   }
-
-                 *value = size;
-                 return TRUE;
-               }
-           }
-       }
-    }
-
-  return FALSE;
-}
index 42558baa073810ecd45e8526fdec302846edc011..79466444e5ff3f5f7c296163554a7b262fe8bfe3 100644 (file)
@@ -1,3 +1,15 @@
+2015-10-26  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19175
+       * ld-i386/i386.exp: Run pr19175.
+       * ld-x86-64/x86-64.exp: Likewise.
+       * ld-i386/pr19175.d: New file.
+       * ld-i386/pr19175.s: Likewise.
+       * ld-i386/pr19175.t: Likewise.
+       * ld-x86-64/pr19175.d: Likewise.
+       * ld-x86-64/pr19175.s: Likewise.
+       * ld-x86-64/pr19175.t: Likewise.
+
 2015-10-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/19171
index 9bf08da83fbe5eeb5997ffb36b2eebc1760ae803..84a63e882babf8606780bc9be9f959af96298d94 100644 (file)
@@ -315,6 +315,7 @@ run_dump_test "load4b"
 run_dump_test "load5a"
 run_dump_test "load5b"
 run_dump_test "load6"
+run_dump_test "pr19175"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
diff --git a/ld/testsuite/ld-i386/pr19175.d b/ld/testsuite/ld-i386/pr19175.d
new file mode 100644 (file)
index 0000000..3f2edb1
--- /dev/null
@@ -0,0 +1,13 @@
+#source: pr19175.s
+#as: --32
+#ld: -Bsymbolic -shared -melf_i386 -T pr19175.t
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+#...
+[      ]*[a-f0-9]+:    8d 81 ([0-9a-f]{2} ){4} *       lea    -0x[a-f0-9]+\(%ecx\),%eax
+#pass
diff --git a/ld/testsuite/ld-i386/pr19175.s b/ld/testsuite/ld-i386/pr19175.s
new file mode 100644 (file)
index 0000000..dc846a9
--- /dev/null
@@ -0,0 +1,5 @@
+       .globl  _start
+       .type   _start, @function
+_start:
+       movl    _text@GOT(%ecx), %eax
+       .size   _start, .-_start
diff --git a/ld/testsuite/ld-i386/pr19175.t b/ld/testsuite/ld-i386/pr19175.t
new file mode 100644 (file)
index 0000000..1018e9e
--- /dev/null
@@ -0,0 +1,11 @@
+EXTERN(_start)
+ENTRY(_start)
+
+SECTIONS
+{
+  .text :
+  {
+    _text = .;
+    *(.text*)
+  }
+}
diff --git a/ld/testsuite/ld-x86-64/pr19175.d b/ld/testsuite/ld-x86-64/pr19175.d
new file mode 100644 (file)
index 0000000..70e5689
--- /dev/null
@@ -0,0 +1,13 @@
+#source: pr19175.s
+#as: --64
+#ld: -Bsymbolic -shared -melf_x86_64 -T pr19175.t
+#objdump: -dw
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+#...
+[      ]*[a-f0-9]+:    48 8d 05 ([0-9a-f]{2} ){4} *    lea    -0x[a-f0-9]+\(%rip\),%rax        # [a-f0-9]+ <_start>
+#pass
diff --git a/ld/testsuite/ld-x86-64/pr19175.s b/ld/testsuite/ld-x86-64/pr19175.s
new file mode 100644 (file)
index 0000000..2548e07
--- /dev/null
@@ -0,0 +1,5 @@
+       .globl  _start
+       .type   _start, @function
+_start:
+       movq    _text@GOTPCREL(%rip), %rax
+       .size   _start, .-_start
diff --git a/ld/testsuite/ld-x86-64/pr19175.t b/ld/testsuite/ld-x86-64/pr19175.t
new file mode 100644 (file)
index 0000000..1018e9e
--- /dev/null
@@ -0,0 +1,11 @@
+EXTERN(_start)
+ENTRY(_start)
+
+SECTIONS
+{
+  .text :
+  {
+    _text = .;
+    *(.text*)
+  }
+}
index 6caea5f4d5ba89cd7d004a447dfbb963373e9a84..869cbe516700fa5cee3e33fc082c6b83bd9b2724 100644 (file)
@@ -347,6 +347,7 @@ run_dump_test "pr18815"
 run_dump_test "pr19013"
 run_dump_test "pr19013-x32"
 run_dump_test "pr19013-nacl"
+run_dump_test "pr19175"
 
 # Add $PLT_CFLAGS if PLT is expected.
 global PLT_CFLAGS