x86: Add _bfd_x86_elf_get_synthetic_symtab
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 30 Aug 2017 19:27:17 +0000 (12:27 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 30 Aug 2017 19:27:30 +0000 (12:27 -0700)
Move the common codes in elf_i386_get_synthetic_symtab and
elf_x86_64_get_synthetic_symtab to _bfd_x86_elf_get_synthetic_symtab.

* elf32-i386.c (elf_i386_plt_type): Removed.
(elf_i386_plt): Likewise.
(elf_i386_get_synthetic_symtab): Updated.   Call
_bfd_x86_elf_get_synthetic_symtab.
* elf64-x86-64.c (elf_x86_64_plt_type): Removed.
(elf_x86_64_plt): Likewise.
(elf_x86_64_get_synthetic_symtab): Updated.  Call
_bfd_x86_elf_get_synthetic_symtab.
* elfxx-x86.c (elf_i386_get_plt_got_vma): New function.
(elf_x86_64_get_plt_got_vma): Likewise.
(elf_i386_valid_plt_reloc_p): Likewise.
(elf_x86_64_valid_plt_reloc_p): Likewise.
(_bfd_x86_elf_get_synthetic_symtab): Likewise.
* elfxx-x86.h (elf_x86_plt_type): New.
(elf_x86_plt): Likewise.
(_bfd_x86_elf_get_synthetic_symtab): Likewise.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elfxx-x86.c
bfd/elfxx-x86.h

index 9c7e2ba..bda958a 100644 (file)
@@ -1,5 +1,24 @@
 2017-08-30  H.J. Lu  <hongjiu.lu@intel.com>
 
+       * elf32-i386.c (elf_i386_plt_type): Removed.
+       (elf_i386_plt): Likewise.
+       (elf_i386_get_synthetic_symtab): Updated.   Call
+       _bfd_x86_elf_get_synthetic_symtab.
+       * elf64-x86-64.c (elf_x86_64_plt_type): Removed.
+       (elf_x86_64_plt): Likewise.
+       (elf_x86_64_get_synthetic_symtab): Updated.  Call
+       _bfd_x86_elf_get_synthetic_symtab.
+       * elfxx-x86.c (elf_i386_get_plt_got_vma): New function.
+       (elf_x86_64_get_plt_got_vma): Likewise.
+       (elf_i386_valid_plt_reloc_p): Likewise.
+       (elf_x86_64_valid_plt_reloc_p): Likewise.
+       (_bfd_x86_elf_get_synthetic_symtab): Likewise.
+       * elfxx-x86.h (elf_x86_plt_type): New.
+       (elf_x86_plt): Likewise.
+       (_bfd_x86_elf_get_synthetic_symtab): Likewise.
+
+2017-08-30  H.J. Lu  <hongjiu.lu@intel.com>
+
        * elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Check
        target_id instead of elf_machine_code.
 
index 8e41c6e..7b6d21f 100644 (file)
@@ -5618,26 +5618,6 @@ elf_i386_output_arch_local_syms
   return TRUE;
 }
 
-enum elf_i386_plt_type
-{
-  plt_non_lazy = 0,
-  plt_lazy = 1 << 0,
-  plt_pic = 1 << 1,
-  plt_second = 1 << 2,
-  plt_unknown = -1
-};
-
-struct elf_i386_plt
-{
-  const char *name;
-  asection *sec;
-  bfd_byte *contents;
-  enum elf_i386_plt_type type;
-  unsigned int plt_got_offset;
-  unsigned int plt_entry_size;
-  long count;
-};
-
 /* Forward declaration.  */
 static const struct elf_x86_lazy_plt_layout elf_i386_nacl_plt;
 
@@ -5652,27 +5632,23 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
                               asymbol **dynsyms,
                               asymbol **ret)
 {
-  long size, count, i, n, len;
+  long count, i, n;
   int j;
-  unsigned int plt_got_offset, plt_entry_size;
-  asymbol *s;
   bfd_byte *plt_contents;
-  long dynrelcount, relsize;
-  arelent **dynrelbuf, *p;
+  long relsize;
   const struct elf_x86_lazy_plt_layout *lazy_plt;
   const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
   const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
   const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
   asection *plt;
   bfd_vma got_addr;
-  char *names;
-  enum elf_i386_plt_type plt_type;
-  struct elf_i386_plt plts[] =
+  enum elf_x86_plt_type plt_type;
+  struct elf_x86_plt plts[] =
     {
-      { ".plt", NULL, NULL, plt_unknown, 0, 0, 0 },
-      { ".plt.got", NULL, NULL, plt_non_lazy, 0, 0, 0 },
-      { ".plt.sec", NULL, NULL, plt_second, 0, 0, 0 },
-      { NULL, NULL, NULL, plt_non_lazy, 0, 0, 0 }
+      { ".plt", NULL, NULL, plt_unknown, 0, 0, 0, 0 },
+      { ".plt.got", NULL, NULL, plt_non_lazy, 0, 0, 0, 0 },
+      { ".plt.sec", NULL, NULL, plt_second, 0, 0, 0, 0 },
+      { NULL, NULL, NULL, plt_non_lazy, 0, 0, 0, 0 }
     };
 
   *ret = NULL;
@@ -5838,176 +5814,9 @@ elf_i386_get_synthetic_symtab (bfd *abfd,
        got_addr = (bfd_vma) -1;
     }
 
-  if (count == 0)
-    return -1;
-
-  dynrelbuf = (arelent **) bfd_malloc (relsize);
-  if (dynrelbuf == NULL)
-    return -1;
-
-  dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
-                                               dynsyms);
-
-  /* Sort the relocs by address.  */
-  qsort (dynrelbuf, dynrelcount, sizeof (arelent *),
-        _bfd_x86_elf_compare_relocs);
-
-  size = count * sizeof (asymbol);
-
-  /* Allocate space for @plt suffixes.  */
-  n = 0;
-  for (i = 0; i < dynrelcount; i++)
-    {
-      p = dynrelbuf[i];
-      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
-      if (p->addend != 0)
-       size += sizeof ("+0x") - 1 + 8;
-    }
-
-  s = *ret = (asymbol *) bfd_zmalloc (size);
-  if (s == NULL)
-    goto bad_return;
-
-  if (got_addr)
-    {
-      /* Check .got.plt and then .got to get the _GLOBAL_OFFSET_TABLE_
-        address.  */
-      asection *sec = bfd_get_section_by_name (abfd, ".got.plt");
-      if (sec != NULL)
-       got_addr = sec->vma;
-      else
-       {
-         sec = bfd_get_section_by_name (abfd, ".got");
-         if (sec != NULL)
-           got_addr = sec->vma;
-       }
-
-      if (got_addr == (bfd_vma) -1)
-       goto bad_return;
-    }
-
-  /* Check for each PLT section.  */
-  names = (char *) (s + count);
-  size = 0;
-  n = 0;
-  for (j = 0; plts[j].name != NULL; j++)
-    if ((plt_contents = plts[j].contents) != NULL)
-      {
-       long k;
-       bfd_vma offset;
-
-       plt_got_offset = plts[j].plt_got_offset;
-       plt_entry_size = plts[j].plt_entry_size;
-
-       plt = plts[j].sec;
-
-       if ((plts[j].type & plt_lazy))
-         {
-           /* Skip PLT0 in lazy PLT.  */
-           k = 1;
-           offset = plt_entry_size;
-         }
-       else
-         {
-           k = 0;
-           offset = 0;
-         }
-
-       /* Check each PLT entry against dynamic relocations.  */
-       for (; k < plts[j].count; k++)
-         {
-           int off;
-           bfd_vma got_vma;
-           long min, max, mid;
-
-           /* Get the GOT offset, a signed 32-bit integer.  */
-           off = H_GET_32 (abfd, (plt_contents + offset
-                                  + plt_got_offset));
-           got_vma = got_addr + off;
-
-           /* Binary search.  */
-           p = dynrelbuf[0];
-           min = 0;
-           max = dynrelcount;
-           while ((min + 1) < max)
-             {
-               arelent *r;
-
-               mid = (min + max) / 2;
-               r = dynrelbuf[mid];
-               if (got_vma > r->address)
-                 min = mid;
-               else if (got_vma < r->address)
-                 max = mid;
-               else
-                 {
-                   p = r;
-                   break;
-                 }
-             }
-
-           /* Skip unknown relocation.  PR 17512: file: bc9d6cf5.  */
-           if (got_vma == p->address
-               && p->howto != NULL
-               && (p->howto->type == R_386_JUMP_SLOT
-                   || p->howto->type == R_386_GLOB_DAT
-                   || p->howto->type == R_386_IRELATIVE))
-             {
-               *s = **p->sym_ptr_ptr;
-               /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL
-                  set.  Since we are defining a symbol, ensure one
-                  of them is set.  */
-               if ((s->flags & BSF_LOCAL) == 0)
-                 s->flags |= BSF_GLOBAL;
-               s->flags |= BSF_SYNTHETIC;
-               /* This is no longer a section symbol.  */
-               s->flags &= ~BSF_SECTION_SYM;
-               s->section = plt;
-               s->the_bfd = plt->owner;
-               s->value = offset;
-               s->udata.p = NULL;
-               s->name = names;
-               len = strlen ((*p->sym_ptr_ptr)->name);
-               memcpy (names, (*p->sym_ptr_ptr)->name, len);
-               names += len;
-               if (p->addend != 0)
-                 {
-                   char buf[30], *a;
-
-                   memcpy (names, "+0x", sizeof ("+0x") - 1);
-                   names += sizeof ("+0x") - 1;
-                   bfd_sprintf_vma (abfd, buf, p->addend);
-                   for (a = buf; *a == '0'; ++a)
-                     ;
-                   size = strlen (a);
-                   memcpy (names, a, size);
-                   names += size;
-                 }
-               memcpy (names, "@plt", sizeof ("@plt"));
-               names += sizeof ("@plt");
-               n++;
-               s++;
-             }
-           offset += plt_entry_size;
-         }
-      }
-
-  /* PLT entries with R_386_TLS_DESC relocations are skipped.  */
-  if (n == 0)
-    {
-bad_return:
-      count = -1;
-    }
-  else
-    count = n;
-
-  for (j = 0; plts[j].name != NULL; j++)
-    if (plts[j].contents != NULL)
-      free (plts[j].contents);
-
-  free (dynrelbuf);
-
-  return count;
+  return _bfd_x86_elf_get_synthetic_symtab (abfd, count, relsize,
+                                           got_addr, plts, dynsyms,
+                                           ret);
 }
 
 /* Set up i386 GNU properties.  Return the first relocatable ELF input
index 3bf465b..0edb174 100644 (file)
@@ -5995,26 +5995,6 @@ elf_x86_64_output_arch_local_syms
   return TRUE;
 }
 
-enum elf_x86_64_plt_type
-{
-  plt_non_lazy = 0,
-  plt_lazy = 1 << 0,
-  plt_second = 1 << 1,
-  plt_unknown = -1
-};
-
-struct elf_x86_64_plt
-{
-  const char *name;
-  asection *sec;
-  bfd_byte *contents;
-  enum elf_x86_64_plt_type type;
-  unsigned int plt_got_offset;
-  unsigned int plt_got_insn_size;
-  unsigned int plt_entry_size;
-  long count;
-};
-
 /* Forward declaration.  */
 static const struct elf_x86_lazy_plt_layout elf_x86_64_nacl_plt;
 
@@ -6029,13 +6009,10 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
                                 asymbol **dynsyms,
                                 asymbol **ret)
 {
-  long size, count, i, n, len;
+  long count, i, n;
   int j;
-  unsigned int plt_got_offset, plt_entry_size, plt_got_insn_size;
-  asymbol *s;
   bfd_byte *plt_contents;
-  long dynrelcount, relsize;
-  arelent **dynrelbuf, *p;
+  long relsize;
   const struct elf_x86_lazy_plt_layout *lazy_plt;
   const struct elf_x86_non_lazy_plt_layout *non_lazy_plt;
   const struct elf_x86_lazy_plt_layout *lazy_bnd_plt;
@@ -6043,9 +6020,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
   const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
   const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
   asection *plt;
-  char *names;
-  enum elf_x86_64_plt_type plt_type;
-  struct elf_x86_64_plt plts[] =
+  enum elf_x86_plt_type plt_type;
+  struct elf_x86_plt plts[] =
     {
       { ".plt", NULL, NULL, plt_unknown, 0, 0, 0, 0 },
       { ".plt.got", NULL, NULL, plt_non_lazy, 0, 0, 0, 0 },
@@ -6213,159 +6189,9 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
       plts[j].contents = plt_contents;
     }
 
-  if (count == 0)
-    return -1;
-
-  dynrelbuf = (arelent **) bfd_malloc (relsize);
-  if (dynrelbuf == NULL)
-    return -1;
-
-  dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
-                                               dynsyms);
-
-  /* Sort the relocs by address.  */
-  qsort (dynrelbuf, dynrelcount, sizeof (arelent *),
-        _bfd_x86_elf_compare_relocs);
-
-  size = count * sizeof (asymbol);
-
-  /* Allocate space for @plt suffixes.  */
-  n = 0;
-  for (i = 0; i < dynrelcount; i++)
-    {
-      p = dynrelbuf[i];
-      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
-      if (p->addend != 0)
-       size += sizeof ("+0x") - 1 + 8 + 8 * ABI_64_P (abfd);
-    }
-
-  s = *ret = (asymbol *) bfd_zmalloc (size);
-  if (s == NULL)
-    goto bad_return;
-
-  /* Check for each PLT section.  */
-  names = (char *) (s + count);
-  size = 0;
-  n = 0;
-  for (j = 0; plts[j].name != NULL; j++)
-    if ((plt_contents = plts[j].contents) != NULL)
-      {
-       long k;
-       bfd_vma offset;
-
-       plt_got_offset = plts[j].plt_got_offset;
-       plt_got_insn_size = plts[j].plt_got_insn_size;
-       plt_entry_size = plts[j].plt_entry_size;
-
-       plt = plts[j].sec;
-
-       if ((plts[j].type & plt_lazy))
-         {
-           /* Skip PLT0 in lazy PLT.  */
-           k = 1;
-           offset = plt_entry_size;
-         }
-       else
-         {
-           k = 0;
-           offset = 0;
-         }
-
-       /* Check each PLT entry against dynamic relocations.  */
-       for (; k < plts[j].count; k++)
-         {
-           int off;
-           bfd_vma got_vma;
-           long min, max, mid;
-
-           /* Get the PC-relative offset, a signed 32-bit integer.  */
-           off = H_GET_32 (abfd, (plt_contents + offset
-                                  + plt_got_offset));
-           got_vma = plt->vma + offset + off + plt_got_insn_size;
-
-           /* Binary search.  */
-           p = dynrelbuf[0];
-           min = 0;
-           max = dynrelcount;
-           while ((min + 1) < max)
-             {
-               arelent *r;
-
-               mid = (min + max) / 2;
-               r = dynrelbuf[mid];
-               if (got_vma > r->address)
-                 min = mid;
-               else if (got_vma < r->address)
-                 max = mid;
-               else
-                 {
-                   p = r;
-                   break;
-                 }
-             }
-
-           /* Skip unknown relocation.  PR 17512: file: bc9d6cf5.  */
-           if (got_vma == p->address
-               && p->howto != NULL
-               && (p->howto->type == R_X86_64_JUMP_SLOT
-                   || p->howto->type == R_X86_64_GLOB_DAT
-                   || p->howto->type == R_X86_64_IRELATIVE))
-             {
-               *s = **p->sym_ptr_ptr;
-               /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL
-                  set.  Since we are defining a symbol, ensure one
-                  of them is set.  */
-               if ((s->flags & BSF_LOCAL) == 0)
-                 s->flags |= BSF_GLOBAL;
-               s->flags |= BSF_SYNTHETIC;
-               /* This is no longer a section symbol.  */
-               s->flags &= ~BSF_SECTION_SYM;
-               s->section = plt;
-               s->the_bfd = plt->owner;
-               s->value = offset;
-               s->udata.p = NULL;
-               s->name = names;
-               len = strlen ((*p->sym_ptr_ptr)->name);
-               memcpy (names, (*p->sym_ptr_ptr)->name, len);
-               names += len;
-               if (p->addend != 0)
-                 {
-                   char buf[30], *a;
-
-                   memcpy (names, "+0x", sizeof ("+0x") - 1);
-                   names += sizeof ("+0x") - 1;
-                   bfd_sprintf_vma (abfd, buf, p->addend);
-                   for (a = buf; *a == '0'; ++a)
-                     ;
-                   size = strlen (a);
-                   memcpy (names, a, size);
-                   names += size;
-                 }
-               memcpy (names, "@plt", sizeof ("@plt"));
-               names += sizeof ("@plt");
-               n++;
-               s++;
-             }
-           offset += plt_entry_size;
-         }
-      }
-
-  /* PLT entries with R_X86_64_TLSDESC relocations are skipped.  */
-  if (n == 0)
-    {
-bad_return:
-      count = -1;
-    }
-  else
-    count = n;
-
-  for (j = 0; plts[j].name != NULL; j++)
-    if (plts[j].contents != NULL)
-      free (plts[j].contents);
-
-  free (dynrelbuf);
-
-  return count;
+  return _bfd_x86_elf_get_synthetic_symtab (abfd, count, relsize,
+                                           (bfd_vma) 0, plts, dynsyms,
+                                           ret);
 }
 
 /* Handle an x86-64 specific section when reading an object file.  This
index d040ee3..eb02ed2 100644 (file)
@@ -530,6 +530,247 @@ _bfd_x86_elf_hash_symbol (struct elf_link_hash_entry *h)
   return _bfd_elf_hash_symbol (h);
 }
 
+static bfd_vma
+elf_i386_get_plt_got_vma (struct elf_x86_plt *plt_p ATTRIBUTE_UNUSED,
+                         bfd_vma off,
+                         bfd_vma offset ATTRIBUTE_UNUSED,
+                         bfd_vma got_addr)
+{
+  return got_addr + off;
+}
+
+static bfd_vma
+elf_x86_64_get_plt_got_vma (struct elf_x86_plt *plt_p,
+                           bfd_vma off,
+                           bfd_vma offset,
+                           bfd_vma got_addr ATTRIBUTE_UNUSED)
+{
+  return plt_p->sec->vma + offset + off + plt_p->plt_got_insn_size;
+}
+
+static bfd_boolean
+elf_i386_valid_plt_reloc_p (unsigned int type)
+{
+  return (type == R_386_JUMP_SLOT
+         || type == R_386_GLOB_DAT
+         || type == R_386_IRELATIVE);
+}
+
+static bfd_boolean
+elf_x86_64_valid_plt_reloc_p (unsigned int type)
+{
+  return (type == R_X86_64_JUMP_SLOT
+         || type == R_X86_64_GLOB_DAT
+         || type == R_X86_64_IRELATIVE);
+}
+
+long
+_bfd_x86_elf_get_synthetic_symtab (bfd *abfd,
+                                  long count,
+                                  long relsize,
+                                  bfd_vma got_addr,
+                                  struct elf_x86_plt plts[],
+                                  asymbol **dynsyms,
+                                  asymbol **ret)
+{
+  long size, i, n, len;
+  int j;
+  unsigned int plt_got_offset, plt_entry_size;
+  asymbol *s;
+  bfd_byte *plt_contents;
+  long dynrelcount;
+  arelent **dynrelbuf, *p;
+  char *names;
+  const struct elf_backend_data *bed;
+  bfd_vma (*get_plt_got_vma) (struct elf_x86_plt *, bfd_vma, bfd_vma,
+                             bfd_vma);
+  bfd_boolean (*valid_plt_reloc_p) (unsigned int);
+
+  if (count == 0)
+    return -1;
+
+  dynrelbuf = (arelent **) bfd_malloc (relsize);
+  if (dynrelbuf == NULL)
+    return -1;
+
+  dynrelcount = bfd_canonicalize_dynamic_reloc (abfd, dynrelbuf,
+                                               dynsyms);
+
+  /* Sort the relocs by address.  */
+  qsort (dynrelbuf, dynrelcount, sizeof (arelent *),
+        _bfd_x86_elf_compare_relocs);
+
+  size = count * sizeof (asymbol);
+
+  /* Allocate space for @plt suffixes.  */
+  n = 0;
+  for (i = 0; i < dynrelcount; i++)
+    {
+      p = dynrelbuf[i];
+      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+      if (p->addend != 0)
+       size += sizeof ("+0x") - 1 + 8 + 8 * ABI_64_P (abfd);
+    }
+
+  s = *ret = (asymbol *) bfd_zmalloc (size);
+  if (s == NULL)
+    goto bad_return;
+
+  bed = get_elf_backend_data (abfd);
+
+  if (bed->target_id == X86_64_ELF_DATA)
+    {
+      get_plt_got_vma = elf_x86_64_get_plt_got_vma;
+      valid_plt_reloc_p = elf_x86_64_valid_plt_reloc_p;
+    }
+  else
+    {
+      get_plt_got_vma = elf_i386_get_plt_got_vma;
+      valid_plt_reloc_p = elf_i386_valid_plt_reloc_p;
+      if (got_addr)
+       {
+         /* Check .got.plt and then .got to get the _GLOBAL_OFFSET_TABLE_
+            address.  */
+         asection *sec = bfd_get_section_by_name (abfd, ".got.plt");
+         if (sec != NULL)
+           got_addr = sec->vma;
+         else
+           {
+             sec = bfd_get_section_by_name (abfd, ".got");
+             if (sec != NULL)
+               got_addr = sec->vma;
+           }
+
+         if (got_addr == (bfd_vma) -1)
+           goto bad_return;
+       }
+    }
+
+  /* Check for each PLT section.  */
+  names = (char *) (s + count);
+  size = 0;
+  n = 0;
+  for (j = 0; plts[j].name != NULL; j++)
+    if ((plt_contents = plts[j].contents) != NULL)
+      {
+       long k;
+       bfd_vma offset;
+       asection *plt;
+       struct elf_x86_plt *plt_p = &plts[j];
+
+       plt_got_offset = plt_p->plt_got_offset;
+       plt_entry_size = plt_p->plt_entry_size;
+
+       plt = plt_p->sec;
+
+       if ((plt_p->type & plt_lazy))
+         {
+           /* Skip PLT0 in lazy PLT.  */
+           k = 1;
+           offset = plt_entry_size;
+         }
+       else
+         {
+           k = 0;
+           offset = 0;
+         }
+
+       /* Check each PLT entry against dynamic relocations.  */
+       for (; k < plt_p->count; k++)
+         {
+           int off;
+           bfd_vma got_vma;
+           long min, max, mid;
+
+           /* Get the GOT offset for i386 or the PC-relative offset
+              for x86-64, a signed 32-bit integer.  */
+           off = H_GET_32 (abfd, (plt_contents + offset
+                                  + plt_got_offset));
+           got_vma = get_plt_got_vma (plt_p, off, offset, got_addr);
+
+           /* Binary search.  */
+           p = dynrelbuf[0];
+           min = 0;
+           max = dynrelcount;
+           while ((min + 1) < max)
+             {
+               arelent *r;
+
+               mid = (min + max) / 2;
+               r = dynrelbuf[mid];
+               if (got_vma > r->address)
+                 min = mid;
+               else if (got_vma < r->address)
+                 max = mid;
+               else
+                 {
+                   p = r;
+                   break;
+                 }
+             }
+
+           /* Skip unknown relocation.  PR 17512: file: bc9d6cf5.  */
+           if (got_vma == p->address
+               && p->howto != NULL
+               && valid_plt_reloc_p (p->howto->type))
+             {
+               *s = **p->sym_ptr_ptr;
+               /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL
+                  set.  Since we are defining a symbol, ensure one
+                  of them is set.  */
+               if ((s->flags & BSF_LOCAL) == 0)
+                 s->flags |= BSF_GLOBAL;
+               s->flags |= BSF_SYNTHETIC;
+               /* This is no longer a section symbol.  */
+               s->flags &= ~BSF_SECTION_SYM;
+               s->section = plt;
+               s->the_bfd = plt->owner;
+               s->value = offset;
+               s->udata.p = NULL;
+               s->name = names;
+               len = strlen ((*p->sym_ptr_ptr)->name);
+               memcpy (names, (*p->sym_ptr_ptr)->name, len);
+               names += len;
+               if (p->addend != 0)
+                 {
+                   char buf[30], *a;
+
+                   memcpy (names, "+0x", sizeof ("+0x") - 1);
+                   names += sizeof ("+0x") - 1;
+                   bfd_sprintf_vma (abfd, buf, p->addend);
+                   for (a = buf; *a == '0'; ++a)
+                     ;
+                   size = strlen (a);
+                   memcpy (names, a, size);
+                   names += size;
+                 }
+               memcpy (names, "@plt", sizeof ("@plt"));
+               names += sizeof ("@plt");
+               n++;
+               s++;
+             }
+           offset += plt_entry_size;
+         }
+      }
+
+  /* PLT entries with R_386_TLS_DESC relocations are skipped.  */
+  if (n == 0)
+    {
+bad_return:
+      count = -1;
+    }
+  else
+    count = n;
+
+  for (j = 0; plts[j].name != NULL; j++)
+    if (plts[j].contents != NULL)
+      free (plts[j].contents);
+
+  free (dynrelbuf);
+
+  return count;
+}
+
 /* Parse x86 GNU properties.  */
 
 enum elf_property_kind
index 21e16a2..45f2458 100644 (file)
@@ -315,6 +315,27 @@ struct elf_x86_obj_tdata
   bfd_vma *local_tlsdesc_gotent;
 };
 
+enum elf_x86_plt_type
+{
+  plt_non_lazy = 0,
+  plt_lazy = 1 << 0,
+  plt_pic = 1 << 1,
+  plt_second = 1 << 2,
+  plt_unknown = -1
+};
+
+struct elf_x86_plt
+{
+  const char *name;
+  asection *sec;
+  bfd_byte *contents;
+  enum elf_x86_plt_type type;
+  unsigned int plt_got_offset;
+  unsigned int plt_entry_size;
+  unsigned int plt_got_insn_size;      /* Only used for x86-64.  */
+  long count;
+};
+
 #define elf_x86_tdata(abfd) \
   ((struct elf_x86_obj_tdata *) (abfd)->tdata.any)
 
@@ -372,6 +393,10 @@ extern bfd_boolean _bfd_x86_elf_fixup_symbol
 extern bfd_boolean _bfd_x86_elf_hash_symbol
   (struct elf_link_hash_entry *);
 
+extern long _bfd_x86_elf_get_synthetic_symtab
+  (bfd *, long, long, bfd_vma, struct elf_x86_plt [], asymbol **,
+   asymbol **);
+
 extern enum elf_property_kind _bfd_x86_elf_parse_gnu_properties
   (bfd *, unsigned int, bfd_byte *, unsigned int);