mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 12:23:31 +08:00
bfd/
* elfxx-mips.c (mips_elf_recreate_got): Don't change the entry; create another one if necessary. (mips_elf_set_gotidx): New function. (mips_elf_set_global_gotidx): Use it. (mips_elf_initialize_tls_index): Likewise. Take a mips_elf_traverse_got_arg as argument. (mips_elf_lay_out_got): Update use of mips_elf_initialize_tls_index. (mips_elf_multi_got): Likewise. Cope with error returns from mips_elf_set_global_gotidx.
This commit is contained in:
@ -1,3 +1,15 @@
|
|||||||
|
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* elfxx-mips.c (mips_elf_recreate_got): Don't change the entry;
|
||||||
|
create another one if necessary.
|
||||||
|
(mips_elf_set_gotidx): New function.
|
||||||
|
(mips_elf_set_global_gotidx): Use it.
|
||||||
|
(mips_elf_initialize_tls_index): Likewise. Take a
|
||||||
|
mips_elf_traverse_got_arg as argument.
|
||||||
|
(mips_elf_lay_out_got): Update use of mips_elf_initialize_tls_index.
|
||||||
|
(mips_elf_multi_got): Likewise. Cope with error returns from
|
||||||
|
mips_elf_set_global_gotidx.
|
||||||
|
|
||||||
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* elfxx-mips.c (mips_got_info): Add relocs field.
|
* elfxx-mips.c (mips_got_info): Add relocs field.
|
||||||
|
104
bfd/elfxx-mips.c
104
bfd/elfxx-mips.c
@ -3991,22 +3991,28 @@ static int
|
|||||||
mips_elf_recreate_got (void **entryp, void *data)
|
mips_elf_recreate_got (void **entryp, void *data)
|
||||||
{
|
{
|
||||||
htab_t *new_got;
|
htab_t *new_got;
|
||||||
struct mips_got_entry *entry;
|
struct mips_got_entry new_entry, *entry;
|
||||||
void **slot;
|
void **slot;
|
||||||
|
|
||||||
new_got = (htab_t *) data;
|
new_got = (htab_t *) data;
|
||||||
entry = (struct mips_got_entry *) *entryp;
|
entry = (struct mips_got_entry *) *entryp;
|
||||||
if (entry->abfd != NULL && entry->symndx == -1)
|
if (entry->abfd != NULL
|
||||||
|
&& entry->symndx == -1
|
||||||
|
&& (entry->d.h->root.root.type == bfd_link_hash_indirect
|
||||||
|
|| entry->d.h->root.root.type == bfd_link_hash_warning))
|
||||||
{
|
{
|
||||||
struct mips_elf_link_hash_entry *h;
|
struct mips_elf_link_hash_entry *h;
|
||||||
|
|
||||||
|
new_entry = *entry;
|
||||||
|
entry = &new_entry;
|
||||||
h = entry->d.h;
|
h = entry->d.h;
|
||||||
while (h->root.root.type == bfd_link_hash_indirect
|
do
|
||||||
|| h->root.root.type == bfd_link_hash_warning)
|
|
||||||
{
|
{
|
||||||
BFD_ASSERT (h->global_got_area == GGA_NONE);
|
BFD_ASSERT (h->global_got_area == GGA_NONE);
|
||||||
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
|
h = (struct mips_elf_link_hash_entry *) h->root.root.u.i.link;
|
||||||
}
|
}
|
||||||
|
while (h->root.root.type == bfd_link_hash_indirect
|
||||||
|
|| h->root.root.type == bfd_link_hash_warning);
|
||||||
entry->d.h = h;
|
entry->d.h = h;
|
||||||
}
|
}
|
||||||
slot = htab_find_slot (*new_got, entry, INSERT);
|
slot = htab_find_slot (*new_got, entry, INSERT);
|
||||||
@ -4016,7 +4022,19 @@ mips_elf_recreate_got (void **entryp, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*slot == NULL)
|
if (*slot == NULL)
|
||||||
|
{
|
||||||
|
if (entry == &new_entry)
|
||||||
|
{
|
||||||
|
entry = bfd_alloc (entry->abfd, sizeof (*entry));
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
*new_got = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*entry = new_entry;
|
||||||
|
}
|
||||||
*slot = entry;
|
*slot = entry;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4349,23 +4367,54 @@ mips_elf_merge_gots (void **bfd2got_, void *p)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the TLS GOT index for the GOT entry in ENTRYP. ENTRYP's NEXT field
|
/* ENTRYP is a hash table entry for a mips_got_entry. Set its gotidx
|
||||||
is null iff there is just a single GOT. */
|
to GOTIDX, duplicating the entry if it has already been assigned
|
||||||
|
an index in a different GOT. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
mips_elf_set_gotidx (void **entryp, long gotidx)
|
||||||
|
{
|
||||||
|
struct mips_got_entry *entry;
|
||||||
|
|
||||||
|
entry = (struct mips_got_entry *) *entryp;
|
||||||
|
if (entry->gotidx > 0)
|
||||||
|
{
|
||||||
|
struct mips_got_entry *new_entry;
|
||||||
|
|
||||||
|
new_entry = bfd_alloc (entry->abfd, sizeof (*entry));
|
||||||
|
if (!new_entry)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*new_entry = *entry;
|
||||||
|
*entryp = new_entry;
|
||||||
|
entry = new_entry;
|
||||||
|
}
|
||||||
|
entry->gotidx = gotidx;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the TLS GOT index for the GOT entry in ENTRYP. DATA points to a
|
||||||
|
mips_elf_traverse_got_arg in which DATA->value is the size of one
|
||||||
|
GOT entry. Set DATA->g to null on failure. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mips_elf_initialize_tls_index (void **entryp, void *p)
|
mips_elf_initialize_tls_index (void **entryp, void *data)
|
||||||
{
|
{
|
||||||
struct mips_got_entry *entry = (struct mips_got_entry *)*entryp;
|
struct mips_got_entry *entry;
|
||||||
struct mips_got_info *g = p;
|
struct mips_elf_traverse_got_arg *arg;
|
||||||
|
struct mips_got_info *g;
|
||||||
bfd_vma next_index;
|
bfd_vma next_index;
|
||||||
unsigned char tls_type;
|
unsigned char tls_type;
|
||||||
|
|
||||||
/* We're only interested in TLS symbols. */
|
/* We're only interested in TLS symbols. */
|
||||||
|
entry = (struct mips_got_entry *) *entryp;
|
||||||
tls_type = (entry->tls_type & GOT_TLS_TYPE);
|
tls_type = (entry->tls_type & GOT_TLS_TYPE);
|
||||||
if (tls_type == 0)
|
if (tls_type == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
next_index = MIPS_ELF_GOT_SIZE (entry->abfd) * (long) g->tls_assigned_gotno;
|
arg = (struct mips_elf_traverse_got_arg *) data;
|
||||||
|
g = arg->g;
|
||||||
|
next_index = arg->value * g->tls_assigned_gotno;
|
||||||
|
|
||||||
if (entry->symndx == -1 && g->next == NULL)
|
if (entry->symndx == -1 && g->next == NULL)
|
||||||
{
|
{
|
||||||
@ -4401,7 +4450,11 @@ mips_elf_initialize_tls_index (void **entryp, void *p)
|
|||||||
}
|
}
|
||||||
g->tls_ldm_offset = next_index;
|
g->tls_ldm_offset = next_index;
|
||||||
}
|
}
|
||||||
entry->gotidx = next_index;
|
if (!mips_elf_set_gotidx (entryp, next_index))
|
||||||
|
{
|
||||||
|
arg->g = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Account for the entries we've just allocated. */
|
/* Account for the entries we've just allocated. */
|
||||||
@ -4431,7 +4484,7 @@ mips_elf_set_global_got_area (void **entryp, void *data)
|
|||||||
/* A htab_traverse callback for secondary GOT entries, where DATA points
|
/* A htab_traverse callback for secondary GOT entries, where DATA points
|
||||||
to a mips_elf_traverse_got_arg. Assign GOT indices to global entries
|
to a mips_elf_traverse_got_arg. Assign GOT indices to global entries
|
||||||
and record the number of relocations they require. DATA->value is
|
and record the number of relocations they require. DATA->value is
|
||||||
the size of one GOT entry. */
|
the size of one GOT entry. Set DATA->g to null on failure. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mips_elf_set_global_gotidx (void **entryp, void *data)
|
mips_elf_set_global_gotidx (void **entryp, void *data)
|
||||||
@ -4445,7 +4498,13 @@ mips_elf_set_global_gotidx (void **entryp, void *data)
|
|||||||
&& entry->symndx == -1
|
&& entry->symndx == -1
|
||||||
&& entry->d.h->global_got_area != GGA_NONE)
|
&& entry->d.h->global_got_area != GGA_NONE)
|
||||||
{
|
{
|
||||||
entry->gotidx = arg->value * (long) arg->g->assigned_gotno++;
|
if (!mips_elf_set_gotidx (entryp, arg->value * arg->g->assigned_gotno))
|
||||||
|
{
|
||||||
|
arg->g = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arg->g->assigned_gotno += 1;
|
||||||
|
|
||||||
if (arg->info->shared
|
if (arg->info->shared
|
||||||
|| (elf_hash_table (arg->info)->dynamic_sections_created
|
|| (elf_hash_table (arg->info)->dynamic_sections_created
|
||||||
&& entry->d.h->root.def_dynamic
|
&& entry->d.h->root.def_dynamic
|
||||||
@ -4646,7 +4705,11 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
|
|||||||
/* Set up any TLS entries. We always place the TLS entries after
|
/* Set up any TLS entries. We always place the TLS entries after
|
||||||
all non-TLS entries. */
|
all non-TLS entries. */
|
||||||
g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
|
g->tls_assigned_gotno = g->local_gotno + g->global_gotno;
|
||||||
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
|
tga.g = g;
|
||||||
|
tga.value = MIPS_ELF_GOT_SIZE (abfd);
|
||||||
|
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, &tga);
|
||||||
|
if (!tga.g)
|
||||||
|
return FALSE;
|
||||||
BFD_ASSERT (g->tls_assigned_gotno == assign);
|
BFD_ASSERT (g->tls_assigned_gotno == assign);
|
||||||
|
|
||||||
/* Move onto the next GOT. It will be a secondary GOT if nonull. */
|
/* Move onto the next GOT. It will be a secondary GOT if nonull. */
|
||||||
@ -4674,9 +4737,11 @@ mips_elf_multi_got (bfd *abfd, struct bfd_link_info *info,
|
|||||||
tga.value = MIPS_ELF_GOT_SIZE (abfd);
|
tga.value = MIPS_ELF_GOT_SIZE (abfd);
|
||||||
tga.g = g;
|
tga.g = g;
|
||||||
htab_traverse (g->got_entries, mips_elf_set_global_gotidx, &tga);
|
htab_traverse (g->got_entries, mips_elf_set_global_gotidx, &tga);
|
||||||
BFD_ASSERT (g->assigned_gotno - g->local_gotno <= g->global_gotno);
|
if (!tga.g)
|
||||||
|
return FALSE;
|
||||||
|
BFD_ASSERT (g->assigned_gotno == g->local_gotno + g->global_gotno);
|
||||||
g->assigned_gotno = save_assign;
|
g->assigned_gotno = save_assign;
|
||||||
|
|
||||||
if (info->shared)
|
if (info->shared)
|
||||||
{
|
{
|
||||||
g->relocs += g->local_gotno - g->assigned_gotno;
|
g->relocs += g->local_gotno - g->assigned_gotno;
|
||||||
@ -8877,7 +8942,12 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
|
|||||||
{
|
{
|
||||||
/* Set up TLS entries. */
|
/* Set up TLS entries. */
|
||||||
g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
|
g->tls_assigned_gotno = g->global_gotno + g->local_gotno;
|
||||||
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, g);
|
tga.info = info;
|
||||||
|
tga.g = g;
|
||||||
|
tga.value = MIPS_ELF_GOT_SIZE (output_bfd);
|
||||||
|
htab_traverse (g->got_entries, mips_elf_initialize_tls_index, &tga);
|
||||||
|
if (!tga.g)
|
||||||
|
return FALSE;
|
||||||
BFD_ASSERT (g->tls_assigned_gotno
|
BFD_ASSERT (g->tls_assigned_gotno
|
||||||
== g->global_gotno + g->local_gotno + g->tls_gotno);
|
== g->global_gotno + g->local_gotno + g->tls_gotno);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user