mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-20 14:22:35 +08:00
bfd/
* elfxx-mips.c (mips_got_page_ref): New structure. (mips_got_page_entry): Use a section rather than a (bfd, symndx) pair to represent the anchor point. (mips_got_info): Add a got_page_refs field. (mips_elf_link_hash_table): Add a sym_cache field. (mips_got_page_ref_hash, mips_got_page_ref_eq): New functions. (mips_got_page_entry_hash, mips_got_page_entry_eq): Update for new anchor representation. (mips_elf_create_got_info): Create got_page_refs rather than got_page_entries. (mips_elf_record_got_page_ref): New function. (mips_elf_pages_for_range): Move further down file. (mips_elf_record_got_page_entry): Likewise. Take a got as argument. Use a section rather than a (bfd, symndx) pair to represent the anchor point. (mips_elf_resolve_got_page_ref): New function. (mips_elf_resolve_final_got_entries): Use it to populate got_page_entries. (_bfd_mips_elf_check_relocs): Call mips_elf_record_got_page_ref rather than mips_elf_record_got_page_entry. Only nullify h afterwards. (mips_elf_lay_out_got): Call mips_elf_resolve_final_got_entries earlier. ld/testsuite/ * ld-mips-elf/mips16-pic-2.dd, ld-mips-elf/mips16-pic-2.gd: Remove 3 unused local GOT entries. * ld-mips-elf/got-page-4a.s, ld-mips-elf/got-page-4b.s, ld-mips-elf/got-page-4a.d, ld-mips-elf/got-page-4a.got, ld-mips-elf/got-page-4b.d, ld-mips-elf/got-page-4b.got, ld-mips-elf/got-page-5.s, ld-mips-elf/got-page-5.d, ld-mips-elf/got-page-5.got, ld-mips-elf/got-page-6.s, ld-mips-elf/got-page-6.d, ld-mips-elf/got-page-6.got, ld-mips-elf/got-page-7a.s, ld-mips-elf/got-page-7b.s, ld-mips-elf/got-page-7c.s, ld-mips-elf/got-page-7d.s, ld-mips-elf/got-page-7e.s, ld-mips-elf/got-page-7.d, ld-mips-elf/got-page-7.got: New tests. * ld-mips-elf/mips-elf.exp: Run them.
This commit is contained in:
@ -1,3 +1,29 @@
|
|||||||
|
2013-02-13 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* elfxx-mips.c (mips_got_page_ref): New structure.
|
||||||
|
(mips_got_page_entry): Use a section rather than a (bfd, symndx)
|
||||||
|
pair to represent the anchor point.
|
||||||
|
(mips_got_info): Add a got_page_refs field.
|
||||||
|
(mips_elf_link_hash_table): Add a sym_cache field.
|
||||||
|
(mips_got_page_ref_hash, mips_got_page_ref_eq): New functions.
|
||||||
|
(mips_got_page_entry_hash, mips_got_page_entry_eq): Update for
|
||||||
|
new anchor representation.
|
||||||
|
(mips_elf_create_got_info): Create got_page_refs rather than
|
||||||
|
got_page_entries.
|
||||||
|
(mips_elf_record_got_page_ref): New function.
|
||||||
|
(mips_elf_pages_for_range): Move further down file.
|
||||||
|
(mips_elf_record_got_page_entry): Likewise. Take a got as argument.
|
||||||
|
Use a section rather than a (bfd, symndx) pair to represent the
|
||||||
|
anchor point.
|
||||||
|
(mips_elf_resolve_got_page_ref): New function.
|
||||||
|
(mips_elf_resolve_final_got_entries): Use it to populate
|
||||||
|
got_page_entries.
|
||||||
|
(_bfd_mips_elf_check_relocs): Call mips_elf_record_got_page_ref
|
||||||
|
rather than mips_elf_record_got_page_entry. Only nullify h
|
||||||
|
afterwards.
|
||||||
|
(mips_elf_lay_out_got): Call mips_elf_resolve_final_got_entries
|
||||||
|
earlier.
|
||||||
|
|
||||||
2013-02-12 Richard Sandiford <rdsandiford@googlemail.com>
|
2013-02-12 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* elfxx-mips.c (mips_elf_lay_out_got): Count VxWorks GOT relocs
|
* elfxx-mips.c (mips_elf_lay_out_got): Count VxWorks GOT relocs
|
||||||
|
416
bfd/elfxx-mips.c
416
bfd/elfxx-mips.c
@ -108,6 +108,27 @@ struct mips_got_entry
|
|||||||
long gotidx;
|
long gotidx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* This structure represents a GOT page reference from an input bfd.
|
||||||
|
Each instance represents a symbol + ADDEND, where the representation
|
||||||
|
of the symbol depends on whether it is local to the input bfd.
|
||||||
|
If it is, then SYMNDX >= 0, and the symbol has index SYMNDX in U.ABFD.
|
||||||
|
Otherwise, SYMNDX < 0 and U.H points to the symbol's hash table entry.
|
||||||
|
|
||||||
|
Page references with SYMNDX >= 0 always become page references
|
||||||
|
in the output. Page references with SYMNDX < 0 only become page
|
||||||
|
references if the symbol binds locally; in other cases, the page
|
||||||
|
reference decays to a global GOT reference. */
|
||||||
|
struct mips_got_page_ref
|
||||||
|
{
|
||||||
|
long symndx;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct mips_elf_link_hash_entry *h;
|
||||||
|
bfd *abfd;
|
||||||
|
} u;
|
||||||
|
bfd_vma addend;
|
||||||
|
};
|
||||||
|
|
||||||
/* This structure describes a range of addends: [MIN_ADDEND, MAX_ADDEND].
|
/* This structure describes a range of addends: [MIN_ADDEND, MAX_ADDEND].
|
||||||
The structures form a non-overlapping list that is sorted by increasing
|
The structures form a non-overlapping list that is sorted by increasing
|
||||||
MIN_ADDEND. */
|
MIN_ADDEND. */
|
||||||
@ -119,13 +140,11 @@ struct mips_got_page_range
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* This structure describes the range of addends that are applied to page
|
/* This structure describes the range of addends that are applied to page
|
||||||
relocations against a given symbol. */
|
relocations against a given section. */
|
||||||
struct mips_got_page_entry
|
struct mips_got_page_entry
|
||||||
{
|
{
|
||||||
/* The input bfd in which the symbol is defined. */
|
/* The section that these entries are based on. */
|
||||||
bfd *abfd;
|
asection *sec;
|
||||||
/* The index of the symbol, as stored in the relocation r_info. */
|
|
||||||
long symndx;
|
|
||||||
/* The ranges for this page entry. */
|
/* The ranges for this page entry. */
|
||||||
struct mips_got_page_range *ranges;
|
struct mips_got_page_range *ranges;
|
||||||
/* The maximum number of page entries needed for RANGES. */
|
/* The maximum number of page entries needed for RANGES. */
|
||||||
@ -155,6 +174,8 @@ struct mips_got_info
|
|||||||
unsigned int assigned_gotno;
|
unsigned int assigned_gotno;
|
||||||
/* A hash table holding members of the got. */
|
/* A hash table holding members of the got. */
|
||||||
struct htab *got_entries;
|
struct htab *got_entries;
|
||||||
|
/* A hash table holding mips_got_page_ref structures. */
|
||||||
|
struct htab *got_page_refs;
|
||||||
/* A hash table of mips_got_page_entry structures. */
|
/* A hash table of mips_got_page_entry structures. */
|
||||||
struct htab *got_page_entries;
|
struct htab *got_page_entries;
|
||||||
/* In multi-got links, a pointer to the next got (err, rather, most
|
/* In multi-got links, a pointer to the next got (err, rather, most
|
||||||
@ -444,6 +465,9 @@ struct mips_elf_link_hash_table
|
|||||||
The function returns the new section on success, otherwise it
|
The function returns the new section on success, otherwise it
|
||||||
returns null. */
|
returns null. */
|
||||||
asection *(*add_stub_section) (const char *, asection *, asection *);
|
asection *(*add_stub_section) (const char *, asection *, asection *);
|
||||||
|
|
||||||
|
/* Small local sym cache. */
|
||||||
|
struct sym_cache sym_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Get the MIPS ELF linker hash table from a link_info structure. */
|
/* Get the MIPS ELF linker hash table from a link_info structure. */
|
||||||
@ -2770,13 +2794,39 @@ mips_elf_got_entry_eq (const void *entry1, const void *entry2)
|
|||||||
: e2->abfd && e1->d.h == e2->d.h));
|
: e2->abfd && e1->d.h == e2->d.h));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hashval_t
|
||||||
|
mips_got_page_ref_hash (const void *ref_)
|
||||||
|
{
|
||||||
|
const struct mips_got_page_ref *ref;
|
||||||
|
|
||||||
|
ref = (const struct mips_got_page_ref *) ref_;
|
||||||
|
return ((ref->symndx >= 0
|
||||||
|
? (hashval_t) (ref->u.abfd->id + ref->symndx)
|
||||||
|
: ref->u.h->root.root.root.hash)
|
||||||
|
+ mips_elf_hash_bfd_vma (ref->addend));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
mips_got_page_ref_eq (const void *ref1_, const void *ref2_)
|
||||||
|
{
|
||||||
|
const struct mips_got_page_ref *ref1, *ref2;
|
||||||
|
|
||||||
|
ref1 = (const struct mips_got_page_ref *) ref1_;
|
||||||
|
ref2 = (const struct mips_got_page_ref *) ref2_;
|
||||||
|
return (ref1->symndx == ref2->symndx
|
||||||
|
&& (ref1->symndx < 0
|
||||||
|
? ref1->u.h == ref2->u.h
|
||||||
|
: ref1->u.abfd == ref2->u.abfd)
|
||||||
|
&& ref1->addend == ref2->addend);
|
||||||
|
}
|
||||||
|
|
||||||
static hashval_t
|
static hashval_t
|
||||||
mips_got_page_entry_hash (const void *entry_)
|
mips_got_page_entry_hash (const void *entry_)
|
||||||
{
|
{
|
||||||
const struct mips_got_page_entry *entry;
|
const struct mips_got_page_entry *entry;
|
||||||
|
|
||||||
entry = (const struct mips_got_page_entry *) entry_;
|
entry = (const struct mips_got_page_entry *) entry_;
|
||||||
return entry->abfd->id + entry->symndx;
|
return entry->sec->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2786,7 +2836,7 @@ mips_got_page_entry_eq (const void *entry1_, const void *entry2_)
|
|||||||
|
|
||||||
entry1 = (const struct mips_got_page_entry *) entry1_;
|
entry1 = (const struct mips_got_page_entry *) entry1_;
|
||||||
entry2 = (const struct mips_got_page_entry *) entry2_;
|
entry2 = (const struct mips_got_page_entry *) entry2_;
|
||||||
return entry1->abfd == entry2->abfd && entry1->symndx == entry2->symndx;
|
return entry1->sec == entry2->sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create and return a new mips_got_info structure. */
|
/* Create and return a new mips_got_info structure. */
|
||||||
@ -2805,9 +2855,9 @@ mips_elf_create_got_info (bfd *abfd)
|
|||||||
if (g->got_entries == NULL)
|
if (g->got_entries == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
g->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
|
g->got_page_refs = htab_try_create (1, mips_got_page_ref_hash,
|
||||||
mips_got_page_entry_eq, NULL);
|
mips_got_page_ref_eq, NULL);
|
||||||
if (g->got_page_entries == NULL)
|
if (g->got_page_refs == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
@ -2844,7 +2894,9 @@ mips_elf_replace_bfd_got (bfd *abfd, struct mips_got_info *g)
|
|||||||
/* The GOT structure itself and the hash table entries are
|
/* The GOT structure itself and the hash table entries are
|
||||||
allocated to a bfd, but the hash tables aren't. */
|
allocated to a bfd, but the hash tables aren't. */
|
||||||
htab_delete (tdata->got->got_entries);
|
htab_delete (tdata->got->got_entries);
|
||||||
htab_delete (tdata->got->got_page_entries);
|
htab_delete (tdata->got->got_page_refs);
|
||||||
|
if (tdata->got->got_page_entries)
|
||||||
|
htab_delete (tdata->got->got_page_entries);
|
||||||
}
|
}
|
||||||
tdata->got = g;
|
tdata->got = g;
|
||||||
}
|
}
|
||||||
@ -3691,30 +3743,18 @@ mips_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend,
|
|||||||
return mips_elf_record_got_entry (info, abfd, &entry);
|
return mips_elf_record_got_entry (info, abfd, &entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the maximum number of GOT page entries required for RANGE. */
|
/* Record that ABFD has a page relocation against SYMNDX + ADDEND.
|
||||||
|
H is the symbol's hash table entry, or null if SYMNDX is local
|
||||||
static bfd_vma
|
to ABFD. */
|
||||||
mips_elf_pages_for_range (const struct mips_got_page_range *range)
|
|
||||||
{
|
|
||||||
return (range->max_addend - range->min_addend + 0x1ffff) >> 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record that ABFD has a page relocation against symbol SYMNDX and
|
|
||||||
that ADDEND is the addend for that relocation.
|
|
||||||
|
|
||||||
This function creates an upper bound on the number of GOT slots
|
|
||||||
required; no attempt is made to combine references to non-overridable
|
|
||||||
global symbols across multiple input files. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
mips_elf_record_got_page_ref (struct bfd_link_info *info, bfd *abfd,
|
||||||
long symndx, bfd_signed_vma addend)
|
long symndx, struct elf_link_hash_entry *h,
|
||||||
|
bfd_signed_vma addend)
|
||||||
{
|
{
|
||||||
struct mips_elf_link_hash_table *htab;
|
struct mips_elf_link_hash_table *htab;
|
||||||
struct mips_got_info *g1, *g2;
|
struct mips_got_info *g1, *g2;
|
||||||
struct mips_got_page_entry lookup, *entry;
|
struct mips_got_page_ref lookup, *entry;
|
||||||
struct mips_got_page_range **range_ptr, *range;
|
|
||||||
bfd_vma old_pages, new_pages;
|
|
||||||
void **loc, **bfd_loc;
|
void **loc, **bfd_loc;
|
||||||
|
|
||||||
htab = mips_elf_hash_table (info);
|
htab = mips_elf_hash_table (info);
|
||||||
@ -3723,26 +3763,29 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
|||||||
g1 = htab->got_info;
|
g1 = htab->got_info;
|
||||||
BFD_ASSERT (g1 != NULL);
|
BFD_ASSERT (g1 != NULL);
|
||||||
|
|
||||||
/* Find the mips_got_page_entry hash table entry for this symbol. */
|
if (h)
|
||||||
lookup.abfd = abfd;
|
{
|
||||||
lookup.symndx = symndx;
|
lookup.symndx = -1;
|
||||||
loc = htab_find_slot (g1->got_page_entries, &lookup, INSERT);
|
lookup.u.h = (struct mips_elf_link_hash_entry *) h;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lookup.symndx = symndx;
|
||||||
|
lookup.u.abfd = abfd;
|
||||||
|
}
|
||||||
|
lookup.addend = addend;
|
||||||
|
loc = htab_find_slot (g1->got_page_refs, &lookup, INSERT);
|
||||||
if (loc == NULL)
|
if (loc == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Create a mips_got_page_entry if this is the first time we've
|
entry = (struct mips_got_page_ref *) *loc;
|
||||||
seen the symbol. */
|
|
||||||
entry = (struct mips_got_page_entry *) *loc;
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
entry = bfd_alloc (abfd, sizeof (*entry));
|
entry = bfd_alloc (abfd, sizeof (*entry));
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
entry->abfd = abfd;
|
*entry = lookup;
|
||||||
entry->symndx = symndx;
|
|
||||||
entry->ranges = NULL;
|
|
||||||
entry->num_pages = 0;
|
|
||||||
*loc = entry;
|
*loc = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3751,67 +3794,13 @@ mips_elf_record_got_page_entry (struct bfd_link_info *info, bfd *abfd,
|
|||||||
if (!g2)
|
if (!g2)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
bfd_loc = htab_find_slot (g2->got_page_entries, &lookup, INSERT);
|
bfd_loc = htab_find_slot (g2->got_page_refs, &lookup, INSERT);
|
||||||
if (!bfd_loc)
|
if (!bfd_loc)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (!*bfd_loc)
|
if (!*bfd_loc)
|
||||||
*bfd_loc = entry;
|
*bfd_loc = entry;
|
||||||
|
|
||||||
/* Skip over ranges whose maximum extent cannot share a page entry
|
|
||||||
with ADDEND. */
|
|
||||||
range_ptr = &entry->ranges;
|
|
||||||
while (*range_ptr && addend > (*range_ptr)->max_addend + 0xffff)
|
|
||||||
range_ptr = &(*range_ptr)->next;
|
|
||||||
|
|
||||||
/* If we scanned to the end of the list, or found a range whose
|
|
||||||
minimum extent cannot share a page entry with ADDEND, create
|
|
||||||
a new singleton range. */
|
|
||||||
range = *range_ptr;
|
|
||||||
if (!range || addend < range->min_addend - 0xffff)
|
|
||||||
{
|
|
||||||
range = bfd_alloc (abfd, sizeof (*range));
|
|
||||||
if (!range)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
range->next = *range_ptr;
|
|
||||||
range->min_addend = addend;
|
|
||||||
range->max_addend = addend;
|
|
||||||
|
|
||||||
*range_ptr = range;
|
|
||||||
entry->num_pages++;
|
|
||||||
g1->page_gotno++;
|
|
||||||
g2->page_gotno++;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember how many pages the old range contributed. */
|
|
||||||
old_pages = mips_elf_pages_for_range (range);
|
|
||||||
|
|
||||||
/* Update the ranges. */
|
|
||||||
if (addend < range->min_addend)
|
|
||||||
range->min_addend = addend;
|
|
||||||
else if (addend > range->max_addend)
|
|
||||||
{
|
|
||||||
if (range->next && addend >= range->next->min_addend - 0xffff)
|
|
||||||
{
|
|
||||||
old_pages += mips_elf_pages_for_range (range->next);
|
|
||||||
range->max_addend = range->next->max_addend;
|
|
||||||
range->next = range->next->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
range->max_addend = addend;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Record any change in the total estimate. */
|
|
||||||
new_pages = mips_elf_pages_for_range (range);
|
|
||||||
if (old_pages != new_pages)
|
|
||||||
{
|
|
||||||
entry->num_pages += new_pages - old_pages;
|
|
||||||
g1->page_gotno += new_pages - old_pages;
|
|
||||||
g2->page_gotno += new_pages - old_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3930,8 +3919,188 @@ mips_elf_recreate_got (void **entryp, void *data)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the maximum number of GOT page entries required for RANGE. */
|
||||||
|
|
||||||
|
static bfd_vma
|
||||||
|
mips_elf_pages_for_range (const struct mips_got_page_range *range)
|
||||||
|
{
|
||||||
|
return (range->max_addend - range->min_addend + 0x1ffff) >> 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record that G requires a page entry that can reach SEC + ADDEND. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
mips_elf_record_got_page_entry (struct mips_got_info *g,
|
||||||
|
asection *sec, bfd_signed_vma addend)
|
||||||
|
{
|
||||||
|
struct mips_got_page_entry lookup, *entry;
|
||||||
|
struct mips_got_page_range **range_ptr, *range;
|
||||||
|
bfd_vma old_pages, new_pages;
|
||||||
|
void **loc;
|
||||||
|
|
||||||
|
/* Find the mips_got_page_entry hash table entry for this section. */
|
||||||
|
lookup.sec = sec;
|
||||||
|
loc = htab_find_slot (g->got_page_entries, &lookup, INSERT);
|
||||||
|
if (loc == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Create a mips_got_page_entry if this is the first time we've
|
||||||
|
seen the section. */
|
||||||
|
entry = (struct mips_got_page_entry *) *loc;
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
entry = bfd_zalloc (sec->owner, sizeof (*entry));
|
||||||
|
if (!entry)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
entry->sec = sec;
|
||||||
|
*loc = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip over ranges whose maximum extent cannot share a page entry
|
||||||
|
with ADDEND. */
|
||||||
|
range_ptr = &entry->ranges;
|
||||||
|
while (*range_ptr && addend > (*range_ptr)->max_addend + 0xffff)
|
||||||
|
range_ptr = &(*range_ptr)->next;
|
||||||
|
|
||||||
|
/* If we scanned to the end of the list, or found a range whose
|
||||||
|
minimum extent cannot share a page entry with ADDEND, create
|
||||||
|
a new singleton range. */
|
||||||
|
range = *range_ptr;
|
||||||
|
if (!range || addend < range->min_addend - 0xffff)
|
||||||
|
{
|
||||||
|
range = bfd_zalloc (sec->owner, sizeof (*range));
|
||||||
|
if (!range)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
range->next = *range_ptr;
|
||||||
|
range->min_addend = addend;
|
||||||
|
range->max_addend = addend;
|
||||||
|
|
||||||
|
*range_ptr = range;
|
||||||
|
entry->num_pages++;
|
||||||
|
g->page_gotno++;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember how many pages the old range contributed. */
|
||||||
|
old_pages = mips_elf_pages_for_range (range);
|
||||||
|
|
||||||
|
/* Update the ranges. */
|
||||||
|
if (addend < range->min_addend)
|
||||||
|
range->min_addend = addend;
|
||||||
|
else if (addend > range->max_addend)
|
||||||
|
{
|
||||||
|
if (range->next && addend >= range->next->min_addend - 0xffff)
|
||||||
|
{
|
||||||
|
old_pages += mips_elf_pages_for_range (range->next);
|
||||||
|
range->max_addend = range->next->max_addend;
|
||||||
|
range->next = range->next->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
range->max_addend = addend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record any change in the total estimate. */
|
||||||
|
new_pages = mips_elf_pages_for_range (range);
|
||||||
|
if (old_pages != new_pages)
|
||||||
|
{
|
||||||
|
entry->num_pages += new_pages - old_pages;
|
||||||
|
g->page_gotno += new_pages - old_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A htab_traverse callback for which *REFP points to a mips_got_page_ref
|
||||||
|
and for which DATA points to a mips_elf_traverse_got_arg. Work out
|
||||||
|
whether the page reference described by *REFP needs a GOT page entry,
|
||||||
|
and record that entry in DATA->g if so. Set DATA->g to null on failure. */
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
mips_elf_resolve_got_page_ref (void **refp, void *data)
|
||||||
|
{
|
||||||
|
struct mips_got_page_ref *ref;
|
||||||
|
struct mips_elf_traverse_got_arg *arg;
|
||||||
|
struct mips_elf_link_hash_table *htab;
|
||||||
|
asection *sec;
|
||||||
|
bfd_vma addend;
|
||||||
|
|
||||||
|
ref = (struct mips_got_page_ref *) *refp;
|
||||||
|
arg = (struct mips_elf_traverse_got_arg *) data;
|
||||||
|
htab = mips_elf_hash_table (arg->info);
|
||||||
|
|
||||||
|
if (ref->symndx < 0)
|
||||||
|
{
|
||||||
|
struct mips_elf_link_hash_entry *h;
|
||||||
|
|
||||||
|
/* Global GOT_PAGEs decay to GOT_DISP and so don't need page entries. */
|
||||||
|
h = ref->u.h;
|
||||||
|
if (!SYMBOL_REFERENCES_LOCAL (arg->info, &h->root))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Ignore undefined symbols; we'll issue an error later if
|
||||||
|
appropriate. */
|
||||||
|
if (!((h->root.root.type == bfd_link_hash_defined
|
||||||
|
|| h->root.root.type == bfd_link_hash_defweak)
|
||||||
|
&& h->root.root.u.def.section))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sec = h->root.root.u.def.section;
|
||||||
|
addend = h->root.root.u.def.value + ref->addend;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Elf_Internal_Sym *isym;
|
||||||
|
|
||||||
|
/* Read in the symbol. */
|
||||||
|
isym = bfd_sym_from_r_symndx (&htab->sym_cache, ref->u.abfd,
|
||||||
|
ref->symndx);
|
||||||
|
if (isym == NULL)
|
||||||
|
{
|
||||||
|
arg->g = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the associated input section. */
|
||||||
|
sec = bfd_section_from_elf_index (ref->u.abfd, isym->st_shndx);
|
||||||
|
if (sec == NULL)
|
||||||
|
{
|
||||||
|
arg->g = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is a mergable section, work out the section and offset
|
||||||
|
of the merged data. For section symbols, the addend specifies
|
||||||
|
of the offset _of_ the first byte in the data, otherwise it
|
||||||
|
specifies the offset _from_ the first byte. */
|
||||||
|
if (sec->flags & SEC_MERGE)
|
||||||
|
{
|
||||||
|
void *secinfo;
|
||||||
|
|
||||||
|
secinfo = elf_section_data (sec)->sec_info;
|
||||||
|
if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
|
||||||
|
addend = _bfd_merged_section_offset (ref->u.abfd, &sec, secinfo,
|
||||||
|
isym->st_value + ref->addend);
|
||||||
|
else
|
||||||
|
addend = _bfd_merged_section_offset (ref->u.abfd, &sec, secinfo,
|
||||||
|
isym->st_value) + ref->addend;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addend = isym->st_value + ref->addend;
|
||||||
|
}
|
||||||
|
if (!mips_elf_record_got_page_entry (arg->g, sec, addend))
|
||||||
|
{
|
||||||
|
arg->g = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* If any entries in G->got_entries are for indirect or warning symbols,
|
/* If any entries in G->got_entries are for indirect or warning symbols,
|
||||||
replace them with entries for the target symbol. */
|
replace them with entries for the target symbol. Convert g->got_page_refs
|
||||||
|
into got_page_entry structures and estimate the number of page entries
|
||||||
|
that they require. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
|
mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
|
||||||
@ -3961,6 +4130,16 @@ mips_elf_resolve_final_got_entries (struct bfd_link_info *info,
|
|||||||
|
|
||||||
htab_delete (oldg.got_entries);
|
htab_delete (oldg.got_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g->got_page_entries = htab_try_create (1, mips_got_page_entry_hash,
|
||||||
|
mips_got_page_entry_eq, NULL);
|
||||||
|
if (g->got_page_entries == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
tga.info = info;
|
||||||
|
tga.g = g;
|
||||||
|
htab_traverse (g->got_page_refs, mips_elf_resolve_got_page_ref, &tga);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7823,21 +8002,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
|
|
||||||
case R_MIPS_GOT_PAGE:
|
case R_MIPS_GOT_PAGE:
|
||||||
case R_MICROMIPS_GOT_PAGE:
|
case R_MICROMIPS_GOT_PAGE:
|
||||||
/* If this is a global, overridable symbol, GOT_PAGE will
|
|
||||||
decay to GOT_DISP, so we'll need a GOT entry for it. */
|
|
||||||
if (h)
|
|
||||||
{
|
|
||||||
struct mips_elf_link_hash_entry *hmips =
|
|
||||||
(struct mips_elf_link_hash_entry *) h;
|
|
||||||
|
|
||||||
/* This symbol is definitely not overridable. */
|
|
||||||
if (hmips->root.def_regular
|
|
||||||
&& ! (info->shared && ! info->symbolic
|
|
||||||
&& ! hmips->root.forced_local))
|
|
||||||
h = NULL;
|
|
||||||
}
|
|
||||||
/* Fall through. */
|
|
||||||
|
|
||||||
case R_MIPS16_GOT16:
|
case R_MIPS16_GOT16:
|
||||||
case R_MIPS_GOT16:
|
case R_MIPS_GOT16:
|
||||||
case R_MIPS_GOT_HI16:
|
case R_MIPS_GOT_HI16:
|
||||||
@ -7866,10 +8030,24 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
addend = rel->r_addend;
|
addend = rel->r_addend;
|
||||||
if (!mips_elf_record_got_page_entry (info, abfd, r_symndx,
|
if (!mips_elf_record_got_page_ref (info, abfd, r_symndx,
|
||||||
addend))
|
h, addend))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
struct mips_elf_link_hash_entry *hmips =
|
||||||
|
(struct mips_elf_link_hash_entry *) h;
|
||||||
|
|
||||||
|
/* This symbol is definitely not overridable. */
|
||||||
|
if (hmips->root.def_regular
|
||||||
|
&& ! (info->shared && ! info->symbolic
|
||||||
|
&& ! hmips->root.forced_local))
|
||||||
|
h = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
/* If this is a global, overridable symbol, GOT_PAGE will
|
||||||
|
decay to GOT_DISP, so we'll need a GOT entry for it. */
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
case R_MIPS_GOT_DISP:
|
case R_MIPS_GOT_DISP:
|
||||||
@ -8602,6 +8780,9 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
|
|||||||
count the number of reloc-only GOT symbols. */
|
count the number of reloc-only GOT symbols. */
|
||||||
mips_elf_link_hash_traverse (htab, mips_elf_count_got_symbols, info);
|
mips_elf_link_hash_traverse (htab, mips_elf_count_got_symbols, info);
|
||||||
|
|
||||||
|
if (!mips_elf_resolve_final_got_entries (info, g))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Calculate the total loadable size of the output. That
|
/* Calculate the total loadable size of the output. That
|
||||||
will give us the maximum number of GOT_PAGE entries
|
will give us the maximum number of GOT_PAGE entries
|
||||||
required. */
|
required. */
|
||||||
@ -8630,18 +8811,13 @@ mips_elf_lay_out_got (bfd *output_bfd, struct bfd_link_info *info)
|
|||||||
sections. Is 5 enough? */
|
sections. Is 5 enough? */
|
||||||
page_gotno = (loadable_size >> 16) + 5;
|
page_gotno = (loadable_size >> 16) + 5;
|
||||||
|
|
||||||
/* Choose the smaller of the two estimates; both are intended to be
|
/* Choose the smaller of the two page estimates; both are intended to be
|
||||||
conservative. */
|
conservative. */
|
||||||
if (page_gotno > g->page_gotno)
|
if (page_gotno > g->page_gotno)
|
||||||
page_gotno = g->page_gotno;
|
page_gotno = g->page_gotno;
|
||||||
|
|
||||||
g->local_gotno += page_gotno;
|
g->local_gotno += page_gotno;
|
||||||
|
|
||||||
/* Replace entries for indirect and warning symbols with entries for
|
|
||||||
the target symbol. Count the number of GOT entries and TLS relocs. */
|
|
||||||
if (!mips_elf_resolve_final_got_entries (info, g))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
s->size += g->local_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
||||||
s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
s->size += g->global_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
||||||
s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
s->size += g->tls_gotno * MIPS_ELF_GOT_SIZE (output_bfd);
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
2013-02-13 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
|
* ld-mips-elf/mips16-pic-2.dd,
|
||||||
|
ld-mips-elf/mips16-pic-2.gd: Remove 3 unused local GOT entries.
|
||||||
|
* ld-mips-elf/got-page-4a.s, ld-mips-elf/got-page-4b.s,
|
||||||
|
ld-mips-elf/got-page-4a.d, ld-mips-elf/got-page-4a.got,
|
||||||
|
ld-mips-elf/got-page-4b.d, ld-mips-elf/got-page-4b.got,
|
||||||
|
ld-mips-elf/got-page-5.s, ld-mips-elf/got-page-5.d,
|
||||||
|
ld-mips-elf/got-page-5.got, ld-mips-elf/got-page-6.s,
|
||||||
|
ld-mips-elf/got-page-6.d, ld-mips-elf/got-page-6.got,
|
||||||
|
ld-mips-elf/got-page-7a.s, ld-mips-elf/got-page-7b.s,
|
||||||
|
ld-mips-elf/got-page-7c.s, ld-mips-elf/got-page-7d.s,
|
||||||
|
ld-mips-elf/got-page-7e.s, ld-mips-elf/got-page-7.d,
|
||||||
|
ld-mips-elf/got-page-7.got: New tests.
|
||||||
|
* ld-mips-elf/mips-elf.exp: Run them.
|
||||||
|
|
||||||
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
2013-02-11 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
* ld-mips-elf/tlsdyn-o32-1.d, ld-mips-elf/tlsdyn-o32-1.got,
|
* ld-mips-elf/tlsdyn-o32-1.d, ld-mips-elf/tlsdyn-o32-1.got,
|
||||||
|
35
ld/testsuite/ld-mips-elf/got-page-4a.d
Normal file
35
ld/testsuite/ld-mips-elf/got-page-4a.d
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#...
|
||||||
|
.* <foo>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,4
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,8
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,12
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,16
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,20
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,24
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,28
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,32
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,36
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,40
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,44
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,48
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,52
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,56
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,60
|
||||||
|
#pass
|
7
ld/testsuite/ld-mips-elf/got-page-4a.got
Normal file
7
ld/testsuite/ld-mips-elf/got-page-4a.got
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#...
|
||||||
|
Local entries:
|
||||||
|
Address Access Initial
|
||||||
|
00090008 -32744\(gp\) 00080000
|
||||||
|
0009000c -32740\(gp\) 00000000
|
||||||
|
|
||||||
|
#pass
|
14
ld/testsuite/ld-mips-elf/got-page-4a.s
Normal file
14
ld/testsuite/ld-mips-elf/got-page-4a.s
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.section .rodata.cst4,"aM",@progbits,4
|
||||||
|
.set x,0x01000000
|
||||||
|
.set y,0x02000000
|
||||||
|
# Add the 16 values that the next input file wants, but in such
|
||||||
|
# a way that each one lives on a separate page.
|
||||||
|
.rept 15
|
||||||
|
.word y
|
||||||
|
.set y,y+1
|
||||||
|
.rept 0x4000
|
||||||
|
.word x
|
||||||
|
.set x,x+1
|
||||||
|
.endr
|
||||||
|
.endr
|
||||||
|
.word y
|
36
ld/testsuite/ld-mips-elf/got-page-4b.d
Normal file
36
ld/testsuite/ld-mips-elf/got-page-4b.d
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#...
|
||||||
|
.* <foo>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32740\(gp\)
|
||||||
|
.* addiu a0,a0,4
|
||||||
|
.* lw a0,-32736\(gp\)
|
||||||
|
.* addiu a0,a0,8
|
||||||
|
.* lw a0,-32732\(gp\)
|
||||||
|
.* addiu a0,a0,12
|
||||||
|
.* lw a0,-32728\(gp\)
|
||||||
|
.* addiu a0,a0,16
|
||||||
|
.* lw a0,-32724\(gp\)
|
||||||
|
.* addiu a0,a0,20
|
||||||
|
.* lw a0,-32720\(gp\)
|
||||||
|
.* addiu a0,a0,24
|
||||||
|
.* lw a0,-32716\(gp\)
|
||||||
|
.* addiu a0,a0,28
|
||||||
|
.* lw a0,-32712\(gp\)
|
||||||
|
.* addiu a0,a0,32
|
||||||
|
.* lw a0,-32708\(gp\)
|
||||||
|
.* addiu a0,a0,36
|
||||||
|
.* lw a0,-32704\(gp\)
|
||||||
|
.* addiu a0,a0,40
|
||||||
|
.* lw a0,-32700\(gp\)
|
||||||
|
.* addiu a0,a0,44
|
||||||
|
.* lw a0,-32696\(gp\)
|
||||||
|
.* addiu a0,a0,48
|
||||||
|
.* lw a0,-32692\(gp\)
|
||||||
|
.* addiu a0,a0,52
|
||||||
|
.* lw a0,-32688\(gp\)
|
||||||
|
.* addiu a0,a0,56
|
||||||
|
.* lw a0,-32684\(gp\)
|
||||||
|
.* addiu a0,a0,60
|
||||||
|
|
||||||
|
#pass
|
21
ld/testsuite/ld-mips-elf/got-page-4b.got
Normal file
21
ld/testsuite/ld-mips-elf/got-page-4b.got
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#...
|
||||||
|
Local entries:
|
||||||
|
Address Access Initial
|
||||||
|
00180008 -32744\(gp\) 00080000
|
||||||
|
0018000c -32740\(gp\) 00090000
|
||||||
|
00180010 -32736\(gp\) 000a0000
|
||||||
|
00180014 -32732\(gp\) 000b0000
|
||||||
|
00180018 -32728\(gp\) 000c0000
|
||||||
|
0018001c -32724\(gp\) 000d0000
|
||||||
|
00180020 -32720\(gp\) 000e0000
|
||||||
|
00180024 -32716\(gp\) 000f0000
|
||||||
|
00180028 -32712\(gp\) 00100000
|
||||||
|
0018002c -32708\(gp\) 00110000
|
||||||
|
00180030 -32704\(gp\) 00120000
|
||||||
|
00180034 -32700\(gp\) 00130000
|
||||||
|
00180038 -32696\(gp\) 00140000
|
||||||
|
0018003c -32692\(gp\) 00150000
|
||||||
|
00180040 -32688\(gp\) 00160000
|
||||||
|
00180044 -32684\(gp\) 00170000
|
||||||
|
|
||||||
|
#pass
|
21
ld/testsuite/ld-mips-elf/got-page-4b.s
Normal file
21
ld/testsuite/ld-mips-elf/got-page-4b.s
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
.globl foo
|
||||||
|
.ent foo
|
||||||
|
foo:
|
||||||
|
# Create page references to 16 values. The layout of the values
|
||||||
|
# in this input file requires at most 2 page entries.
|
||||||
|
.set y,0x02000000
|
||||||
|
.rept 16
|
||||||
|
lw $4,%got_page(1f)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(1f)
|
||||||
|
.section .rodata.cst4,"aM",@progbits,4
|
||||||
|
1: .word y
|
||||||
|
.set y,y+1
|
||||||
|
.text
|
||||||
|
.endr
|
||||||
|
.end foo
|
||||||
|
|
||||||
|
# Make sure the loadable size of the library is large.
|
||||||
|
.section .bss
|
||||||
|
.globl g
|
||||||
|
g:
|
||||||
|
.space 0x800000
|
10
ld/testsuite/ld-mips-elf/got-page-5.d
Normal file
10
ld/testsuite/ld-mips-elf/got-page-5.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#...
|
||||||
|
.* <foo>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32740\(gp\)
|
||||||
|
.* addiu a0,a0,-32768
|
||||||
|
.* lw a0,-32740\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32736\(gp\)
|
||||||
|
.* addiu a0,a0,-32768
|
8
ld/testsuite/ld-mips-elf/got-page-5.got
Normal file
8
ld/testsuite/ld-mips-elf/got-page-5.got
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#...
|
||||||
|
Local entries:
|
||||||
|
Address Access Initial
|
||||||
|
00090008 -32744\(gp\) 00080000
|
||||||
|
0009000c -32740\(gp\) 00090000
|
||||||
|
00090010 -32736\(gp\) 000a0000
|
||||||
|
|
||||||
|
#pass
|
31
ld/testsuite/ld-mips-elf/got-page-5.s
Normal file
31
ld/testsuite/ld-mips-elf/got-page-5.s
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Create a mergeable section full of a single value,
|
||||||
|
# and page references relative to one entry called "data".
|
||||||
|
#
|
||||||
|
# The mergeable entries collapse to one, but the offsets
|
||||||
|
# from "data" must still be retained, and need 3 page entries.
|
||||||
|
#
|
||||||
|
# Technically this isn't valid, because it creates out-of-section
|
||||||
|
# page references. It's still a useful way of making sure that
|
||||||
|
# offsets in mergeable sections are handled correctly.
|
||||||
|
.globl foo
|
||||||
|
.ent foo
|
||||||
|
foo:
|
||||||
|
.set y,0
|
||||||
|
.rept 4
|
||||||
|
lw $4,%got_page(data + y)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(data + y)
|
||||||
|
.set y,y+0x8000
|
||||||
|
.endr
|
||||||
|
.end foo
|
||||||
|
|
||||||
|
.section .rodata.cst4,"aM",@progbits,4
|
||||||
|
data:
|
||||||
|
.rept 0x8000*4
|
||||||
|
.word 123456
|
||||||
|
.endr
|
||||||
|
|
||||||
|
# Make sure the loadable size of the library is large.
|
||||||
|
.section .bss
|
||||||
|
.globl g
|
||||||
|
g:
|
||||||
|
.space 0x800000
|
10
ld/testsuite/ld-mips-elf/got-page-6.d
Normal file
10
ld/testsuite/ld-mips-elf/got-page-6.d
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#...
|
||||||
|
.* <foo>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,0
|
6
ld/testsuite/ld-mips-elf/got-page-6.got
Normal file
6
ld/testsuite/ld-mips-elf/got-page-6.got
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#...
|
||||||
|
Local entries:
|
||||||
|
Address Access Initial
|
||||||
|
00090008 -32744\(gp\) 00080000
|
||||||
|
|
||||||
|
#pass
|
27
ld/testsuite/ld-mips-elf/got-page-6.s
Normal file
27
ld/testsuite/ld-mips-elf/got-page-6.s
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Create a mergeable section full of a single value.
|
||||||
|
# Create page references relative to instances of the value
|
||||||
|
# that are large distances apart.
|
||||||
|
#
|
||||||
|
# The mergeable entries collapse to one, so even with the
|
||||||
|
# large distances in the original file, we should end
|
||||||
|
# up with a single page entry.
|
||||||
|
.globl foo
|
||||||
|
.ent foo
|
||||||
|
foo:
|
||||||
|
.rept 4
|
||||||
|
lw $4,%got_page(1f)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(1f)
|
||||||
|
.section .rodata.cst4,"aM",@progbits,4
|
||||||
|
1:
|
||||||
|
.rept 0x8000
|
||||||
|
.word 123456
|
||||||
|
.endr
|
||||||
|
.text
|
||||||
|
.endr
|
||||||
|
.end foo
|
||||||
|
|
||||||
|
# Make sure the loadable size of the library is large.
|
||||||
|
.section .bss
|
||||||
|
.globl g
|
||||||
|
g:
|
||||||
|
.space 0x800000
|
17
ld/testsuite/ld-mips-elf/got-page-7.d
Normal file
17
ld/testsuite/ld-mips-elf/got-page-7.d
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#...
|
||||||
|
.* <f1>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,1024
|
||||||
|
#...
|
||||||
|
.* <f2>:
|
||||||
|
.* lw a0,-32744\(gp\)
|
||||||
|
.* addiu a0,a0,17408
|
||||||
|
#...
|
||||||
|
.* <f3>:
|
||||||
|
.* lw a0,-32740\(gp\)
|
||||||
|
.* addiu a0,a0,-31744
|
||||||
|
#...
|
||||||
|
.* <f4>:
|
||||||
|
.* lw a0,-32740\(gp\)
|
||||||
|
.* addiu a0,a0,1024
|
||||||
|
#pass
|
7
ld/testsuite/ld-mips-elf/got-page-7.got
Normal file
7
ld/testsuite/ld-mips-elf/got-page-7.got
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#...
|
||||||
|
Local entries:
|
||||||
|
Address Access Initial
|
||||||
|
00090008 -32744\(gp\) 00090000
|
||||||
|
0009000c -32740\(gp\) 000a0000
|
||||||
|
|
||||||
|
#pass
|
6
ld/testsuite/ld-mips-elf/got-page-7a.s
Normal file
6
ld/testsuite/ld-mips-elf/got-page-7a.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.globl f1
|
||||||
|
.ent f1
|
||||||
|
f1:
|
||||||
|
lw $4,%got_page(g)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(g)
|
||||||
|
.end f1
|
6
ld/testsuite/ld-mips-elf/got-page-7b.s
Normal file
6
ld/testsuite/ld-mips-elf/got-page-7b.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.globl f2
|
||||||
|
.ent f2
|
||||||
|
f2:
|
||||||
|
lw $4,%got_page(g + 0x4000)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(g + 0x4000)
|
||||||
|
.end f2
|
6
ld/testsuite/ld-mips-elf/got-page-7c.s
Normal file
6
ld/testsuite/ld-mips-elf/got-page-7c.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.globl f3
|
||||||
|
.ent f3
|
||||||
|
f3:
|
||||||
|
lw $4,%got_page(g + 0x8000)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(g + 0x8000)
|
||||||
|
.end f3
|
6
ld/testsuite/ld-mips-elf/got-page-7d.s
Normal file
6
ld/testsuite/ld-mips-elf/got-page-7d.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.globl f4
|
||||||
|
.ent f4
|
||||||
|
f4:
|
||||||
|
lw $4,%got_page(g + 0x10000)($gp)
|
||||||
|
addiu $4,$4,%got_ofst(g + 0x10000)
|
||||||
|
.end f4
|
6
ld/testsuite/ld-mips-elf/got-page-7e.s
Normal file
6
ld/testsuite/ld-mips-elf/got-page-7e.s
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Make sure the loadable size of the library is large.
|
||||||
|
.section .bss
|
||||||
|
.globl g
|
||||||
|
.hidden g
|
||||||
|
g:
|
||||||
|
.space 0x800000
|
@ -453,6 +453,46 @@ if { $linux_gnu } {
|
|||||||
run_dump_test "dyn-sec64"
|
run_dump_test "dyn-sec64"
|
||||||
}
|
}
|
||||||
run_dump_test "got-page-3"
|
run_dump_test "got-page-3"
|
||||||
|
run_ld_link_tests [subst {
|
||||||
|
{"GOT page 4 (one file)" "-shared $abi_ldflags(o32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(o32) -mips2" {got-page-4b.s}
|
||||||
|
{{objdump -dr got-page-4a.d}
|
||||||
|
{readelf -A got-page-4a.got}}
|
||||||
|
"got-page-4a.so"}
|
||||||
|
{"GOT page 4 (two files)" "-shared $abi_ldflags(o32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(o32) -mips2" {got-page-4a.s got-page-4b.s}
|
||||||
|
{{objdump -dr got-page-4b.d}
|
||||||
|
{readelf -A got-page-4b.got}}
|
||||||
|
"got-page-4b.so"}
|
||||||
|
}]
|
||||||
|
if $has_newabi {
|
||||||
|
run_ld_link_tests [subst {
|
||||||
|
{"GOT page 5" "-shared $abi_ldflags(n32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(n32)" {got-page-5.s}
|
||||||
|
{{objdump -dr got-page-5.d}
|
||||||
|
{readelf -A got-page-5.got}}
|
||||||
|
"got-page-5.so"}
|
||||||
|
{"GOT page 6" "-shared $abi_ldflags(n32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(n32)" {got-page-6.s}
|
||||||
|
{{objdump -dr got-page-6.d}
|
||||||
|
{readelf -A got-page-6.got}}
|
||||||
|
"got-page-6.so"}
|
||||||
|
{"GOT page 7 (order 1)" "-shared $abi_ldflags(n32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(n32)"
|
||||||
|
{got-page-7a.s got-page-7b.s got-page-7c.s got-page-7d.s
|
||||||
|
got-page-7e.s}
|
||||||
|
{{objdump -dr got-page-7.d}
|
||||||
|
{readelf -A got-page-7.got}}
|
||||||
|
"got-page-7a.so"}
|
||||||
|
{"GOT page 7 (order 2)" "-shared $abi_ldflags(n32) -T got-page-1.ld"
|
||||||
|
"$abi_asflags(n32)"
|
||||||
|
{got-page-7e.s got-page-7a.s got-page-7b.s got-page-7c.s
|
||||||
|
got-page-7d.s}
|
||||||
|
{{objdump -dr got-page-7.d}
|
||||||
|
{readelf -A got-page-7.got}}
|
||||||
|
"got-page-7b.so"}
|
||||||
|
}]
|
||||||
|
}
|
||||||
run_dump_test "got-dump-1"
|
run_dump_test "got-dump-1"
|
||||||
if $has_newabi {
|
if $has_newabi {
|
||||||
run_dump_test "got-dump-2"
|
run_dump_test "got-dump-2"
|
||||||
|
@ -77,7 +77,7 @@ Disassembly of section \.text:
|
|||||||
.*: [^\t]* move t9,v0
|
.*: [^\t]* move t9,v0
|
||||||
.*: [^\t]* lw v0,16\(sp\)
|
.*: [^\t]* lw v0,16\(sp\)
|
||||||
.*: [^\t]* move gp,v0
|
.*: [^\t]* move gp,v0
|
||||||
.*: [^\t]* lw v0,-32716\(v0\)
|
.*: [^\t]* lw v0,-32728\(v0\)
|
||||||
.*: [^\t]* jalr v0
|
.*: [^\t]* jalr v0
|
||||||
.*: [^\t]* move t9,v0
|
.*: [^\t]* move t9,v0
|
||||||
.*: [^\t]* lw v0,16\(sp\)
|
.*: [^\t]* lw v0,16\(sp\)
|
||||||
@ -101,7 +101,7 @@ Disassembly of section \.text:
|
|||||||
.*: [^\t]* move t9,v0
|
.*: [^\t]* move t9,v0
|
||||||
.*: [^\t]* lw v0,16\(sp\)
|
.*: [^\t]* lw v0,16\(sp\)
|
||||||
.*: [^\t]* move gp,v0
|
.*: [^\t]* move gp,v0
|
||||||
.*: [^\t]* lw v0,-32712\(v0\)
|
.*: [^\t]* lw v0,-32724\(v0\)
|
||||||
.*: [^\t]* jalr v0
|
.*: [^\t]* jalr v0
|
||||||
.*: [^\t]* move t9,v0
|
.*: [^\t]* move t9,v0
|
||||||
.*: [^\t]* lw v0,16\(sp\)
|
.*: [^\t]* lw v0,16\(sp\)
|
||||||
|
@ -13,14 +13,11 @@ Primary GOT:
|
|||||||
0005000c -32740\(gp\) 00040409
|
0005000c -32740\(gp\) 00040409
|
||||||
00050010 -32736\(gp\) 0004040d
|
00050010 -32736\(gp\) 0004040d
|
||||||
00050014 -32732\(gp\) 00000000
|
00050014 -32732\(gp\) 00000000
|
||||||
00050018 -32728\(gp\) 00000000
|
|
||||||
0005001c -32724\(gp\) 00000000
|
|
||||||
00050020 -32720\(gp\) 00000000
|
|
||||||
|
|
||||||
Global entries:
|
Global entries:
|
||||||
Address Access Initial Sym\.Val\. Type Ndx Name
|
Address Access Initial Sym\.Val\. Type Ndx Name
|
||||||
00050024 -32716\(gp\) 00040574 00040574 FUNC 6 used6
|
00050018 -32728\(gp\) 00040574 00040574 FUNC 6 used6
|
||||||
00050028 -32712\(gp\) 00040598 00040598 FUNC 6 used7
|
0005001c -32724\(gp\) 00040598 00040598 FUNC 6 used7
|
||||||
0005002c -32708\(gp\) 00040550 00040550 FUNC 6 used5
|
00050020 -32720\(gp\) 00040550 00040550 FUNC 6 used5
|
||||||
00050030 -32704\(gp\) 0004052c 0004052c FUNC 6 used4
|
00050024 -32716\(gp\) 0004052c 0004052c FUNC 6 used4
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user