mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-26 05:47:26 +08:00
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:
@ -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
|
||||
|
213
bfd/elf32-i386.c
213
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
|
||||
|
@ -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
|
||||
|
241
bfd/elfxx-x86.c
241
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
|
||||
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user