bfd/
* elfxx-mips.c (mips_elf_obj_tdata): Add a got field. (mips_elf_bfd_got, mips_elf_record_got_entry): New functions. (mips_elf_record_global_got_symbol): Update the hash entry before adding the mips_got_entry. Use mips_elf_record_got_entry to do the latter. (mips_elf_record_local_got_symbol): Use mips_elf_record_got_entry. (mips_elf_record_got_page_entry): Record the entry in both the master and bfd GOTs.
This commit is contained in:
parent
72e7511a70
commit
ee227692d7
2 changed files with 112 additions and 56 deletions
|
@ -1,3 +1,14 @@
|
||||||
|
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* elfxx-mips.c (mips_elf_obj_tdata): Add a got field.
|
||||||
|
(mips_elf_bfd_got, mips_elf_record_got_entry): New functions.
|
||||||
|
(mips_elf_record_global_got_symbol): Update the hash entry before
|
||||||
|
adding the mips_got_entry. Use mips_elf_record_got_entry to do
|
||||||
|
the latter.
|
||||||
|
(mips_elf_record_local_got_symbol): Use mips_elf_record_got_entry.
|
||||||
|
(mips_elf_record_got_page_entry): Record the entry in both the
|
||||||
|
master and bfd GOTs.
|
||||||
|
|
||||||
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* elfxx-mips.c (mips_elf_recreate_got): Don't change the entry;
|
* elfxx-mips.c (mips_elf_recreate_got): Don't change the entry;
|
||||||
|
|
157
bfd/elfxx-mips.c
157
bfd/elfxx-mips.c
|
@ -512,6 +512,9 @@ struct mips_elf_obj_tdata
|
||||||
|
|
||||||
/* Input BFD providing Tag_GNU_MIPS_ABI_FP attribute for output. */
|
/* Input BFD providing Tag_GNU_MIPS_ABI_FP attribute for output. */
|
||||||
bfd *abi_fp_bfd;
|
bfd *abi_fp_bfd;
|
||||||
|
|
||||||
|
/* The GOT requirements of input bfds. */
|
||||||
|
struct mips_got_info *got;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Get MIPS ELF private object data from BFD's tdata. */
|
/* Get MIPS ELF private object data from BFD's tdata. */
|
||||||
|
@ -2883,6 +2886,23 @@ mips_elf_create_got_info (bfd *abfd, bfd_boolean master_got_p)
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the GOT info for input bfd ABFD, trying to create a new one if
|
||||||
|
CREATE_P and if ABFD doesn't already have a GOT. */
|
||||||
|
|
||||||
|
static struct mips_got_info *
|
||||||
|
mips_elf_bfd_got (bfd *abfd, bfd_boolean create_p)
|
||||||
|
{
|
||||||
|
struct mips_elf_obj_tdata *tdata;
|
||||||
|
|
||||||
|
if (!is_mips_elf (abfd))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
tdata = mips_elf_tdata (abfd);
|
||||||
|
if (!tdata->got && create_p)
|
||||||
|
tdata->got = mips_elf_create_got_info (abfd, FALSE);
|
||||||
|
return tdata->got;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the dynamic relocation section. If it doesn't exist, try to
|
/* Return the dynamic relocation section. If it doesn't exist, try to
|
||||||
create a new it if CREATE_P, otherwise return NULL. Also return NULL
|
create a new it if CREATE_P, otherwise return NULL. Also return NULL
|
||||||
if creation fails. */
|
if creation fails. */
|
||||||
|
@ -3706,6 +3726,53 @@ mips_elf_sort_hash_table_f (struct mips_elf_link_hash_entry *h, void *data)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Record that input bfd ABFD requires a GOT entry like *LOOKUP
|
||||||
|
(which is owned by the caller and shouldn't be added to the
|
||||||
|
hash table directly). */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
mips_elf_record_got_entry (struct bfd_link_info *info, bfd *abfd,
|
||||||
|
struct mips_got_entry *lookup)
|
||||||
|
{
|
||||||
|
struct mips_elf_link_hash_table *htab;
|
||||||
|
struct mips_got_entry *entry;
|
||||||
|
struct mips_got_info *g;
|
||||||
|
void **loc, **bfd_loc;
|
||||||
|
|
||||||
|
/* Make sure there's a slot for this entry in the master GOT. */
|
||||||
|
htab = mips_elf_hash_table (info);
|
||||||
|
g = htab->got_info;
|
||||||
|
loc = htab_find_slot (g->got_entries, lookup, INSERT);
|
||||||
|
if (!loc)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Populate the entry if it isn't already. */
|
||||||
|
entry = (struct mips_got_entry *) *loc;
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
entry = (struct mips_got_entry *) bfd_alloc (abfd, sizeof (*entry));
|
||||||
|
if (!entry)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
lookup->gotidx = -1;
|
||||||
|
*entry = *lookup;
|
||||||
|
*loc = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reuse the same GOT entry for the BFD's GOT. */
|
||||||
|
g = mips_elf_bfd_got (abfd, TRUE);
|
||||||
|
if (!g)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
bfd_loc = htab_find_slot (g->got_entries, lookup, INSERT);
|
||||||
|
if (!bfd_loc)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!*bfd_loc)
|
||||||
|
*bfd_loc = entry;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* ABFD has a GOT relocation of type R_TYPE against H. Reserve a GOT
|
/* ABFD has a GOT relocation of type R_TYPE against H. Reserve a GOT
|
||||||
entry for it. FOR_CALL is true if the caller is only interested in
|
entry for it. FOR_CALL is true if the caller is only interested in
|
||||||
using the GOT entry for calls. */
|
using the GOT entry for calls. */
|
||||||
|
@ -3717,8 +3784,8 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
|
||||||
{
|
{
|
||||||
struct mips_elf_link_hash_table *htab;
|
struct mips_elf_link_hash_table *htab;
|
||||||
struct mips_elf_link_hash_entry *hmips;
|
struct mips_elf_link_hash_entry *hmips;
|
||||||
struct mips_got_entry entry, **loc;
|
struct mips_got_entry entry;
|
||||||
struct mips_got_info *g;
|
unsigned char tls_type;
|
||||||
|
|
||||||
htab = mips_elf_hash_table (info);
|
htab = mips_elf_hash_table (info);
|
||||||
BFD_ASSERT (htab != NULL);
|
BFD_ASSERT (htab != NULL);
|
||||||
|
@ -3742,40 +3809,19 @@ mips_elf_record_global_got_symbol (struct elf_link_hash_entry *h,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we have a GOT to put this entry into. */
|
tls_type = mips_elf_reloc_tls_type (r_type);
|
||||||
g = htab->got_info;
|
if (tls_type == GOT_NORMAL && hmips->global_got_area > GGA_NORMAL)
|
||||||
BFD_ASSERT (g != NULL);
|
hmips->global_got_area = GGA_NORMAL;
|
||||||
|
else if (tls_type == GOT_TLS_IE && hmips->tls_ie_type == 0)
|
||||||
|
hmips->tls_ie_type = tls_type;
|
||||||
|
else if (tls_type == GOT_TLS_GD && hmips->tls_gd_type == 0)
|
||||||
|
hmips->tls_gd_type = tls_type;
|
||||||
|
|
||||||
entry.abfd = abfd;
|
entry.abfd = abfd;
|
||||||
entry.symndx = -1;
|
entry.symndx = -1;
|
||||||
entry.d.h = (struct mips_elf_link_hash_entry *) h;
|
entry.d.h = (struct mips_elf_link_hash_entry *) h;
|
||||||
entry.tls_type = mips_elf_reloc_tls_type (r_type);
|
entry.tls_type = tls_type;
|
||||||
|
return mips_elf_record_got_entry (info, abfd, &entry);
|
||||||
loc = (struct mips_got_entry **) htab_find_slot (g->got_entries, &entry,
|
|
||||||
INSERT);
|
|
||||||
|
|
||||||
/* If we've already marked this entry as needing GOT space, we don't
|
|
||||||
need to do it again. */
|
|
||||||
if (*loc)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
*loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
|
|
||||||
|
|
||||||
if (! *loc)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
entry.gotidx = -1;
|
|
||||||
|
|
||||||
memcpy (*loc, &entry, sizeof entry);
|
|
||||||
|
|
||||||
if (entry.tls_type == GOT_NORMAL)
|
|
||||||
hmips->global_got_area = GGA_NORMAL;
|
|
||||||
else if (entry.tls_type == GOT_TLS_IE)
|
|
||||||
hmips->tls_ie_type = entry.tls_type;
|
|
||||||
else if (entry.tls_type == GOT_TLS_GD)
|
|
||||||
hmips->tls_gd_type = entry.tls_type;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ABFD has a GOT relocation of type R_TYPE against symbol SYMNDX + ADDEND,
|
/* ABFD has a GOT relocation of type R_TYPE against symbol SYMNDX + ADDEND,
|
||||||
|
@ -3787,7 +3833,7 @@ mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
|
||||||
{
|
{
|
||||||
struct mips_elf_link_hash_table *htab;
|
struct mips_elf_link_hash_table *htab;
|
||||||
struct mips_got_info *g;
|
struct mips_got_info *g;
|
||||||
struct mips_got_entry entry, **loc;
|
struct mips_got_entry entry;
|
||||||
|
|
||||||
htab = mips_elf_hash_table (info);
|
htab = mips_elf_hash_table (info);
|
||||||
BFD_ASSERT (htab != NULL);
|
BFD_ASSERT (htab != NULL);
|
||||||
|
@ -3799,22 +3845,7 @@ mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
|
||||||
entry.symndx = symndx;
|
entry.symndx = symndx;
|
||||||
entry.d.addend = addend;
|
entry.d.addend = addend;
|
||||||
entry.tls_type = mips_elf_reloc_tls_type (r_type);
|
entry.tls_type = mips_elf_reloc_tls_type (r_type);
|
||||||
loc = (struct mips_got_entry **)
|
return mips_elf_record_got_entry (info, abfd, &entry);
|
||||||
htab_find_slot (g->got_entries, &entry, INSERT);
|
|
||||||
|
|
||||||
if (*loc)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
entry.gotidx = -1;
|
|
||||||
|
|
||||||
*loc = (struct mips_got_entry *)bfd_alloc (abfd, sizeof entry);
|
|
||||||
|
|
||||||
if (! *loc)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
memcpy (*loc, &entry, sizeof entry);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the maximum number of GOT page entries required for RANGE. */
|
/* Return the maximum number of GOT page entries required for RANGE. */
|
||||||
|
@ -3837,22 +3868,22 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
||||||
long symndx, bfd_signed_vma addend)
|
long symndx, bfd_signed_vma addend)
|
||||||
{
|
{
|
||||||
struct mips_elf_link_hash_table *htab;
|
struct mips_elf_link_hash_table *htab;
|
||||||
struct mips_got_info *g;
|
struct mips_got_info *g1, *g2;
|
||||||
struct mips_got_page_entry lookup, *entry;
|
struct mips_got_page_entry lookup, *entry;
|
||||||
struct mips_got_page_range **range_ptr, *range;
|
struct mips_got_page_range **range_ptr, *range;
|
||||||
bfd_vma old_pages, new_pages;
|
bfd_vma old_pages, new_pages;
|
||||||
void **loc;
|
void **loc, **bfd_loc;
|
||||||
|
|
||||||
htab = mips_elf_hash_table (info);
|
htab = mips_elf_hash_table (info);
|
||||||
BFD_ASSERT (htab != NULL);
|
BFD_ASSERT (htab != NULL);
|
||||||
|
|
||||||
g = htab->got_info;
|
g1 = htab->got_info;
|
||||||
BFD_ASSERT (g != NULL);
|
BFD_ASSERT (g1 != NULL);
|
||||||
|
|
||||||
/* Find the mips_got_page_entry hash table entry for this symbol. */
|
/* Find the mips_got_page_entry hash table entry for this symbol. */
|
||||||
lookup.abfd = abfd;
|
lookup.abfd = abfd;
|
||||||
lookup.symndx = symndx;
|
lookup.symndx = symndx;
|
||||||
loc = htab_find_slot (g->got_page_entries, &lookup, INSERT);
|
loc = htab_find_slot (g1->got_page_entries, &lookup, INSERT);
|
||||||
if (loc == NULL)
|
if (loc == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -3872,6 +3903,18 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
||||||
*loc = entry;
|
*loc = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add the same entry to the BFD's GOT. */
|
||||||
|
g2 = mips_elf_bfd_got (abfd, TRUE);
|
||||||
|
if (!g2)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
bfd_loc = htab_find_slot (g2->got_page_entries, &lookup, INSERT);
|
||||||
|
if (!bfd_loc)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!*bfd_loc)
|
||||||
|
*bfd_loc = entry;
|
||||||
|
|
||||||
/* Skip over ranges whose maximum extent cannot share a page entry
|
/* Skip over ranges whose maximum extent cannot share a page entry
|
||||||
with ADDEND. */
|
with ADDEND. */
|
||||||
range_ptr = &entry->ranges;
|
range_ptr = &entry->ranges;
|
||||||
|
@ -3894,7 +3937,8 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
||||||
|
|
||||||
*range_ptr = range;
|
*range_ptr = range;
|
||||||
entry->num_pages++;
|
entry->num_pages++;
|
||||||
g->page_gotno++;
|
g1->page_gotno++;
|
||||||
|
g2->page_gotno++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3921,7 +3965,8 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
||||||
if (old_pages != new_pages)
|
if (old_pages != new_pages)
|
||||||
{
|
{
|
||||||
entry->num_pages += new_pages - old_pages;
|
entry->num_pages += new_pages - old_pages;
|
||||||
g->page_gotno += new_pages - old_pages;
|
g1->page_gotno += new_pages - old_pages;
|
||||||
|
g2->page_gotno += new_pages - old_pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Add table
Reference in a new issue