* elf32-frv.c (struct frv_pic_relocs_info): Added fixups and
dynrelocs. (_frv_count_got_plt_entries): Initialize them. (frv_pic_relocs_info_find): Add insert argument. Adjust all callers. (frv_pic_relocs_info_for_global): Likewise. (frv_pic_relocs_info_for_local): Likewise. (frv_pic_merge_early_relocs_info): New. (_frv_resolve_final_relocs_info): Use it in case one entry maps to another. (_frv_add_dyn_reloc): Add entry argument. Adjust all callers. Check that we don't exceed the allocated count for entry. (_frv_add_rofixup): Likewise. (_frv_emit_got_relocs_plt_entries): Adjust for coding standards. (elf32_frv_finish_dynamic_sections): Improve error message in case we emit too few rofixup entries.
This commit is contained in:
parent
abc523ed9f
commit
3b712a1afc
2 changed files with 159 additions and 37 deletions
|
@ -1,3 +1,22 @@
|
|||
2004-03-02 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
* elf32-frv.c (struct frv_pic_relocs_info): Added fixups and
|
||||
dynrelocs.
|
||||
(_frv_count_got_plt_entries): Initialize them.
|
||||
(frv_pic_relocs_info_find): Add insert argument. Adjust all
|
||||
callers.
|
||||
(frv_pic_relocs_info_for_global): Likewise.
|
||||
(frv_pic_relocs_info_for_local): Likewise.
|
||||
(frv_pic_merge_early_relocs_info): New.
|
||||
(_frv_resolve_final_relocs_info): Use it in case one entry maps to
|
||||
another.
|
||||
(_frv_add_dyn_reloc): Add entry argument. Adjust all callers.
|
||||
Check that we don't exceed the allocated count for entry.
|
||||
(_frv_add_rofixup): Likewise.
|
||||
(_frv_emit_got_relocs_plt_entries): Adjust for coding standards.
|
||||
(elf32_frv_finish_dynamic_sections): Improve error message in case
|
||||
we emit too few rofixup entries.
|
||||
|
||||
2004-03-01 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* archures.c (bfd_mach_fr450): New.
|
||||
|
|
177
bfd/elf32-frv.c
177
bfd/elf32-frv.c
|
@ -748,6 +748,10 @@ struct frv_pic_relocs_info
|
|||
relocations referencing the symbol. */
|
||||
unsigned relocs32, relocsfd, relocsfdv;
|
||||
|
||||
/* The number of .rofixups entries and dynamic relocations allocated
|
||||
for this symbol, minus any that might have already been used. */
|
||||
unsigned fixups, dynrelocs;
|
||||
|
||||
/* The offsets of the GOT entries assigned to symbol+addend, to the
|
||||
function descriptor's address, and to a function descriptor,
|
||||
respectively. Should be zero if unassigned. The offsets are
|
||||
|
@ -789,10 +793,14 @@ frv_pic_relocs_info_eq (const void *entry1, const void *entry2)
|
|||
static struct frv_pic_relocs_info *
|
||||
frv_pic_relocs_info_find (struct htab *ht,
|
||||
bfd *abfd,
|
||||
const struct frv_pic_relocs_info *entry)
|
||||
const struct frv_pic_relocs_info *entry,
|
||||
enum insert_option insert)
|
||||
{
|
||||
struct frv_pic_relocs_info **loc =
|
||||
(struct frv_pic_relocs_info **) htab_find_slot (ht, entry, INSERT);
|
||||
(struct frv_pic_relocs_info **) htab_find_slot (ht, entry, insert);
|
||||
|
||||
if (! loc)
|
||||
return NULL;
|
||||
|
||||
if (*loc)
|
||||
return *loc;
|
||||
|
@ -818,7 +826,8 @@ inline static struct frv_pic_relocs_info *
|
|||
frv_pic_relocs_info_for_global (struct htab *ht,
|
||||
bfd *abfd,
|
||||
struct elf_link_hash_entry *h,
|
||||
bfd_vma addend)
|
||||
bfd_vma addend,
|
||||
enum insert_option insert)
|
||||
{
|
||||
struct frv_pic_relocs_info entry;
|
||||
|
||||
|
@ -826,7 +835,7 @@ frv_pic_relocs_info_for_global (struct htab *ht,
|
|||
entry.d.h = h;
|
||||
entry.addend = addend;
|
||||
|
||||
return frv_pic_relocs_info_find (ht, abfd, &entry);
|
||||
return frv_pic_relocs_info_find (ht, abfd, &entry, insert);
|
||||
}
|
||||
|
||||
/* Obtain the address of the entry in HT associated with the SYMNDXth
|
||||
|
@ -836,7 +845,8 @@ inline static struct frv_pic_relocs_info *
|
|||
frv_pic_relocs_info_for_local (struct htab *ht,
|
||||
bfd *abfd,
|
||||
long symndx,
|
||||
bfd_vma addend)
|
||||
bfd_vma addend,
|
||||
enum insert_option insert)
|
||||
{
|
||||
struct frv_pic_relocs_info entry;
|
||||
|
||||
|
@ -844,7 +854,59 @@ frv_pic_relocs_info_for_local (struct htab *ht,
|
|||
entry.d.abfd = abfd;
|
||||
entry.addend = addend;
|
||||
|
||||
return frv_pic_relocs_info_find (ht, abfd, &entry);
|
||||
return frv_pic_relocs_info_find (ht, abfd, &entry, insert);
|
||||
}
|
||||
|
||||
/* Merge fields set by check_relocs() of two entries that end up being
|
||||
mapped to the same (presumably global) symbol. */
|
||||
|
||||
inline static void
|
||||
frv_pic_merge_early_relocs_info (struct frv_pic_relocs_info *e2,
|
||||
struct frv_pic_relocs_info const *e1)
|
||||
{
|
||||
e2->got12 |= e1->got12;
|
||||
e2->gotlos |= e1->gotlos;
|
||||
e2->gothilo |= e1->gothilo;
|
||||
e2->fd |= e1->fd;
|
||||
e2->fdgot12 |= e1->fdgot12;
|
||||
e2->fdgotlos |= e1->fdgotlos;
|
||||
e2->fdgothilo |= e1->fdgothilo;
|
||||
e2->fdgoff12 |= e1->fdgoff12;
|
||||
e2->fdgofflos |= e1->fdgofflos;
|
||||
e2->fdgoffhilo |= e1->fdgoffhilo;
|
||||
e2->gotoff |= e1->gotoff;
|
||||
e2->call |= e1->call;
|
||||
e2->sym |= e1->sym;
|
||||
|
||||
#if 0
|
||||
/* These are set in _frv_count_got_plt_entries() or later, and this
|
||||
function is only called in _frv_resolve_final_relocs_info(), that
|
||||
runs just before it, so we don't have to worry about the fields
|
||||
below. */
|
||||
|
||||
e2->plt |= e1->plt;
|
||||
e2->privfd |= e1->privfd;
|
||||
e2->lazyplt |= e1->lazyplt;
|
||||
e2->done |= e1->done;
|
||||
|
||||
e2->relocs32 += e1->relocs32;
|
||||
e2->relocsfd += e1->relocsfd;
|
||||
e2->relocsfdv += e1->relocsfdv;
|
||||
e2->fixups += e1->fixups;
|
||||
e2->dynrelocs += e1->dynrelocs;
|
||||
|
||||
if (abs (e1->got_entry) < abs (e2->got_entry))
|
||||
e2->got_entry = e1->got_entry;
|
||||
if (abs (e1->fdgot_entry) < abs (e2->fdgot_entry))
|
||||
e2->fdgot_entry = e1->fdgot_entry;
|
||||
if (abs (e1->fd_entry) < abs (e2->fd_entry))
|
||||
e2->fd_entry = e1->fd_entry;
|
||||
|
||||
if (e1->plt_entry < e2->plt_entry)
|
||||
e2->plt_entry = e1->plt_entry;
|
||||
if (e1->lzplt_entry < e2->lzplt_entry)
|
||||
e2->lzplt_entry = e1->lzplt_entry;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Every block of 65535 lazy PLT entries shares a single call to the
|
||||
|
@ -859,7 +921,8 @@ frv_pic_relocs_info_for_local (struct htab *ht,
|
|||
|
||||
inline static bfd_vma
|
||||
_frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
|
||||
int reloc_type, long dynindx, bfd_vma addend)
|
||||
int reloc_type, long dynindx, bfd_vma addend,
|
||||
struct frv_pic_relocs_info *entry)
|
||||
{
|
||||
Elf_Internal_Rela outrel;
|
||||
bfd_vma reloc_offset;
|
||||
|
@ -874,13 +937,17 @@ _frv_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset,
|
|||
sreloc->contents + reloc_offset);
|
||||
sreloc->reloc_count++;
|
||||
|
||||
BFD_ASSERT (entry->dynrelocs > 0);
|
||||
entry->dynrelocs--;
|
||||
|
||||
return reloc_offset;
|
||||
}
|
||||
|
||||
/* Add a fixup to the ROFIXUP section. */
|
||||
|
||||
static bfd_vma
|
||||
_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
|
||||
_frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset,
|
||||
struct frv_pic_relocs_info *entry)
|
||||
{
|
||||
bfd_vma fixup_offset;
|
||||
|
||||
|
@ -894,7 +961,13 @@ _frv_add_rofixup (bfd *output_bfd, asection *rofixup, bfd_vma offset)
|
|||
bfd_put_32 (output_bfd, offset, rofixup->contents + fixup_offset);
|
||||
}
|
||||
rofixup->reloc_count++;
|
||||
|
||||
|
||||
if (entry)
|
||||
{
|
||||
BFD_ASSERT (entry->fixups > 0);
|
||||
entry->fixups--;
|
||||
}
|
||||
|
||||
return fixup_offset;
|
||||
}
|
||||
|
||||
|
@ -999,13 +1072,13 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
{
|
||||
if (sec)
|
||||
ad += sec->output_section->vma;
|
||||
if (entry->symndx != -1 ||
|
||||
entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
if (entry->symndx != -1
|
||||
|| entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
|
||||
frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ entry->got_entry);
|
||||
+ entry->got_entry, entry);
|
||||
}
|
||||
else
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
|
@ -1016,7 +1089,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
+ entry->got_entry)
|
||||
+ frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset,
|
||||
R_FRV_32, idx, ad);
|
||||
R_FRV_32, idx, ad, entry);
|
||||
|
||||
bfd_put_32 (output_bfd, ad,
|
||||
frv_got_section (info)->contents
|
||||
|
@ -1089,7 +1162,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ entry->fdgot_entry);
|
||||
+ entry->fdgot_entry, entry);
|
||||
}
|
||||
else
|
||||
_frv_add_dyn_reloc (output_bfd, frv_gotrel_section (info),
|
||||
|
@ -1100,7 +1173,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
+ entry->fdgot_entry)
|
||||
+ frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset,
|
||||
reloc, idx, ad);
|
||||
reloc, idx, ad, entry);
|
||||
}
|
||||
|
||||
bfd_put_32 (output_bfd, ad,
|
||||
|
@ -1142,19 +1215,19 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
if (sec)
|
||||
ad += sec->output_section->vma;
|
||||
ofst = 0;
|
||||
if (entry->symndx != -1 ||
|
||||
entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
if (entry->symndx != -1
|
||||
|| entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
{
|
||||
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
|
||||
frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ entry->fd_entry);
|
||||
+ entry->fd_entry, entry);
|
||||
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
|
||||
frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset
|
||||
+ frv_got_initial_offset (info)
|
||||
+ entry->fd_entry + 4);
|
||||
+ entry->fd_entry + 4, entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1170,7 +1243,7 @@ _frv_emit_got_relocs_plt_entries (struct frv_pic_relocs_info *entry,
|
|||
+ entry->fd_entry)
|
||||
+ frv_got_section (info)->output_section->vma
|
||||
+ frv_got_section (info)->output_offset,
|
||||
R_FRV_FUNCDESC_VALUE, idx, ad);
|
||||
R_FRV_FUNCDESC_VALUE, idx, ad, entry);
|
||||
}
|
||||
|
||||
/* If we've omitted the dynamic relocation, just emit the fixed
|
||||
|
@ -1922,14 +1995,14 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
if (h != NULL)
|
||||
picrel = frv_pic_relocs_info_for_global (frv_relocs_info (info),
|
||||
input_bfd, h,
|
||||
orig_addend);
|
||||
orig_addend, INSERT);
|
||||
else
|
||||
/* In order to find the entry we created before, we must
|
||||
use the original addend, not the one that may have been
|
||||
modified by _bfd_elf_rela_local_sym(). */
|
||||
picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
|
||||
input_bfd, r_symndx,
|
||||
orig_addend);
|
||||
orig_addend, INSERT);
|
||||
if (! picrel)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2092,7 +2165,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset);
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
}
|
||||
}
|
||||
else if ((bfd_get_section_flags (output_bfd,
|
||||
|
@ -2114,7 +2188,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
r_type, dynindx, addend);
|
||||
r_type, dynindx, addend, picrel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2192,7 +2266,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset);
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
if (r_type == R_FRV_FUNCDESC_VALUE)
|
||||
_frv_add_rofixup
|
||||
(output_bfd,
|
||||
|
@ -2201,7 +2276,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset + 4);
|
||||
+ input_section->output_offset + 4, picrel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2226,7 +2301,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||
input_section, rel->r_offset)
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
r_type, dynindx, addend);
|
||||
r_type, dynindx, addend, picrel);
|
||||
}
|
||||
/* We want the addend in-place because dynamic
|
||||
relocations are REL. Setting relocation to it
|
||||
|
@ -2806,6 +2881,7 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
|
|||
{
|
||||
struct frv_pic_relocs_info *entry = *entryp;
|
||||
struct _frv_dynamic_got_info *dinfo = dinfo_;
|
||||
unsigned relocs = 0, fixups = 0;
|
||||
|
||||
/* Allocate space for a GOT entry pointing to the symbol. */
|
||||
if (entry->got12)
|
||||
|
@ -2862,27 +2938,33 @@ _frv_count_got_plt_entries (void **entryp, void *dinfo_)
|
|||
dinfo->lzplt += 8;
|
||||
|
||||
if (!dinfo->info->executable || dinfo->info->pie)
|
||||
dinfo->relocs += entry->relocs32 + entry->relocsfd + entry->relocsfdv;
|
||||
relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
|
||||
else
|
||||
{
|
||||
if (entry->symndx != -1 || FRV_SYM_LOCAL (dinfo->info, entry->d.h))
|
||||
{
|
||||
if (entry->symndx != -1
|
||||
|| entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
dinfo->fixups += entry->relocs32 + 2 * entry->relocsfdv;
|
||||
|| entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
fixups += entry->relocs32 + 2 * entry->relocsfdv;
|
||||
}
|
||||
else
|
||||
dinfo->relocs += entry->relocs32 + entry->relocsfdv;
|
||||
relocs += entry->relocs32 + entry->relocsfdv;
|
||||
|
||||
if (entry->symndx != -1 || FRV_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
|
||||
{
|
||||
if (entry->symndx != -1
|
||||
|| entry->d.h->root.type != bfd_link_hash_undefweak)
|
||||
dinfo->fixups += entry->relocsfd;
|
||||
fixups += entry->relocsfd;
|
||||
}
|
||||
else
|
||||
dinfo->relocs += entry->relocsfd;
|
||||
relocs += entry->relocsfd;
|
||||
}
|
||||
|
||||
entry->dynrelocs += relocs;
|
||||
entry->fixups += fixups;
|
||||
dinfo->relocs += relocs;
|
||||
dinfo->fixups += fixups;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3210,6 +3292,7 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
|
|||
if (entry->symndx == -1)
|
||||
{
|
||||
struct elf_link_hash_entry *h = entry->d.h;
|
||||
struct frv_pic_relocs_info *oentry;
|
||||
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
|
@ -3218,6 +3301,17 @@ _frv_resolve_final_relocs_info (void **entryp, void *p)
|
|||
if (entry->d.h == h)
|
||||
return 1;
|
||||
|
||||
oentry = frv_pic_relocs_info_for_global (*htab, 0, h, entry->addend,
|
||||
NO_INSERT);
|
||||
|
||||
if (oentry)
|
||||
{
|
||||
/* Merge the two entries. */
|
||||
frv_pic_merge_early_relocs_info (oentry, entry);
|
||||
htab_clear_slot (*htab, entryp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
entry->d.h = h;
|
||||
|
||||
/* If we can't find this entry with the new bfd hash, re-insert
|
||||
|
@ -3581,13 +3675,22 @@ elf32_frv_finish_dynamic_sections (bfd *output_bfd,
|
|||
+ hgot->root.u.def.section->output_offset;
|
||||
|
||||
_frv_add_rofixup (output_bfd, frv_gotfixup_section (info),
|
||||
got_value);
|
||||
got_value, 0);
|
||||
}
|
||||
|
||||
if (frv_gotfixup_section (info)->_raw_size
|
||||
!= (frv_gotfixup_section (info)->reloc_count * 4))
|
||||
{
|
||||
if (!elf_hash_table (info)->dynamic_sections_created)
|
||||
if (frv_gotfixup_section (info)->_raw_size
|
||||
< frv_gotfixup_section (info)->reloc_count * 4)
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info, "LINKER BUG: .rofixup section size mismatch",
|
||||
".rofixup", NULL, NULL, 0);
|
||||
abort ();
|
||||
return FALSE;
|
||||
}
|
||||
else if (!elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
info->callbacks->warning
|
||||
(info, "no dynamic sections, missing -melf32frvfd?",
|
||||
|
@ -3931,12 +4034,12 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
|
|||
picrel
|
||||
= frv_pic_relocs_info_for_global (frv_relocs_info (info),
|
||||
abfd, h,
|
||||
rel->r_addend);
|
||||
rel->r_addend, INSERT);
|
||||
}
|
||||
else
|
||||
picrel = frv_pic_relocs_info_for_local (frv_relocs_info (info),
|
||||
abfd, r_symndx,
|
||||
rel->r_addend);
|
||||
rel->r_addend, INSERT);
|
||||
if (! picrel)
|
||||
return FALSE;
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue