This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] x86: Add _bfd_x86_elf_get_synthetic_symtab


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f493882dab762fb49ecb8685c18a85edfab5e6d3

commit f493882dab762fb49ecb8685c18a85edfab5e6d3
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Aug 30 12:27:17 2017 -0700

    x86: Add _bfd_x86_elf_get_synthetic_symtab
    
    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.

Diff:
---
 bfd/ChangeLog      |  19 +++++
 bfd/elf32-i386.c   | 213 +++-------------------------------------------
 bfd/elf64-x86-64.c | 188 ++---------------------------------------
 bfd/elfxx-x86.c    | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 bfd/elfxx-x86.h    |  25 ++++++
 5 files changed, 303 insertions(+), 383 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9c7e2ba..bda958a 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
 
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 8e41c6e..7b6d21f 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 3bf465b..0edb174 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
index d040ee3..eb02ed2 100644
--- a/bfd/elfxx-x86.c
+++ b/bfd/elfxx-x86.c
@@ -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
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index 21e16a2..45f2458 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]