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.
This commit is contained in:
H.J. Lu
2017-08-30 12:27:17 -07:00
parent 5b86dbf454
commit f493882dab
5 changed files with 303 additions and 383 deletions

View File

@ -1,3 +1,22 @@
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

View 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

View 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

View 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

View 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);