mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
Merge some FRV FDPIC changes into the Blackfin code.
* elf32-bfin.c (struct bfinfdpic_elf_link_hash_table): Add pointer to summary reloc information. (bfinfdpic_dynamic_got_plt_info): New. (_bfin_create_got_section): Create the PLT section here. (elf32_bfinfdpic_create_dynamic_sections): Not here. (_bfinfdpic_count_nontls_entries): Move out of... (_bfinfdpic_count_got_plt_entries): ... here. (_bfinfdpic_count_relocs_fixups): Likewise. (_bfinfdpic_reset_got_plt_entries): New. (_bfinfdpic_size_got_plt): Move out of... (elf32_bfinfdpic_size_dynamic_sections): ... here. (bfinfdpic_relocate_section): Be careful not to call _bfinfdpic_add_rofixup or _bfinfdpic_add_dyn_reloc for deleted relocs. (bfinfdpic_check_discarded_relocs, bfinfdpic_elf_discard_info): New functions. (elf_backend_discard_info): Define for FD-PIC.
This commit is contained in:
parent
ba7e13e478
commit
6a9adeca2c
@ -1,3 +1,23 @@
|
||||
2009-08-11 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
Merge some FRV FDPIC changes into the Blackfin code.
|
||||
* elf32-bfin.c (struct bfinfdpic_elf_link_hash_table): Add pointer to
|
||||
summary reloc information.
|
||||
(bfinfdpic_dynamic_got_plt_info): New.
|
||||
(_bfin_create_got_section): Create the PLT section here.
|
||||
(elf32_bfinfdpic_create_dynamic_sections): Not here.
|
||||
(_bfinfdpic_count_nontls_entries): Move out of...
|
||||
(_bfinfdpic_count_got_plt_entries): ... here.
|
||||
(_bfinfdpic_count_relocs_fixups): Likewise.
|
||||
(_bfinfdpic_reset_got_plt_entries): New.
|
||||
(_bfinfdpic_size_got_plt): Move out of...
|
||||
(elf32_bfinfdpic_size_dynamic_sections): ... here.
|
||||
(bfinfdpic_relocate_section): Be careful not to call
|
||||
_bfinfdpic_add_rofixup or _bfinfdpic_add_dyn_reloc for deleted relocs.
|
||||
(bfinfdpic_check_discarded_relocs, bfinfdpic_elf_discard_info):
|
||||
New functions.
|
||||
(elf_backend_discard_info): Define for FD-PIC.
|
||||
|
||||
2009-08-11 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elflink.c: Add FIXMEs for some places that require octets_per_byte
|
||||
@ -69,7 +89,7 @@
|
||||
(ppc_elf_size_dynamic_sections): Likewise.
|
||||
(ppc_elf_relocate_section): Likewise.
|
||||
|
||||
2006-08-09 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
2009-08-09 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
From Mike Frysinger <michael.frysinger@analog.com>
|
||||
* elf32-bfin.c (bfin_howto_table, bfin_reloc_map, bfin_check_relocs,
|
||||
|
649
bfd/elf32-bfin.c
649
bfd/elf32-bfin.c
@ -1740,6 +1740,9 @@ struct bfinfdpic_elf_link_hash_table
|
||||
/* A hash table holding information about which symbols were
|
||||
referenced with which PIC-related relocations. */
|
||||
struct htab *relocs_info;
|
||||
/* Summary reloc information collected by
|
||||
_bfinfdpic_count_got_plt_entries. */
|
||||
struct _bfinfdpic_dynamic_got_info *g;
|
||||
};
|
||||
|
||||
/* Get the Blackfin ELF linker hash table from a link_info structure. */
|
||||
@ -1763,6 +1766,8 @@ struct bfinfdpic_elf_link_hash_table
|
||||
(bfinfdpic_hash_table (info)->got0)
|
||||
#define bfinfdpic_plt_initial_offset(info) \
|
||||
(bfinfdpic_hash_table (info)->plt0)
|
||||
#define bfinfdpic_dynamic_got_plt_info(info) \
|
||||
(bfinfdpic_hash_table (info)->g)
|
||||
|
||||
/* The name of the dynamic interpreter. This is put in the .interp
|
||||
section. */
|
||||
@ -2149,7 +2154,8 @@ _bfinfdpic_emit_got_relocs_plt_entries (struct bfinfdpic_relocs_info *entry,
|
||||
dynindx = entry->d.h->dynindx;
|
||||
else
|
||||
{
|
||||
if (sec->output_section
|
||||
if (sec
|
||||
&& sec->output_section
|
||||
&& ! bfd_is_abs_section (sec->output_section)
|
||||
&& ! bfd_is_und_section (sec->output_section))
|
||||
dynindx = elf_section_data (sec->output_section)->dynindx;
|
||||
@ -2417,8 +2423,9 @@ _bfinfdpic_emit_got_relocs_plt_entries (struct bfinfdpic_relocs_info *entry,
|
||||
of the section. For a non-local function, it's
|
||||
disregarded. */
|
||||
lowword = ad;
|
||||
if (entry->symndx == -1 && entry->d.h->dynindx != -1
|
||||
&& entry->d.h->dynindx == idx)
|
||||
if (sec == NULL
|
||||
|| (entry->symndx == -1 && entry->d.h->dynindx != -1
|
||||
&& entry->d.h->dynindx == idx))
|
||||
highword = 0;
|
||||
else
|
||||
highword = _bfinfdpic_osec_to_segment
|
||||
@ -2843,6 +2850,8 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
if (info->executable && !info->pie
|
||||
&& (!h || BFINFDPIC_FUNCDESC_LOCAL (info, h)))
|
||||
{
|
||||
bfd_vma offset;
|
||||
|
||||
addend += bfinfdpic_got_section (info)->output_section->vma;
|
||||
if ((bfd_get_section_flags (output_bfd,
|
||||
input_section->output_section)
|
||||
@ -2858,16 +2867,19 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
_bfinfdpic_add_rofixup (output_bfd,
|
||||
bfinfdpic_gotfixup_section
|
||||
(info),
|
||||
_bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
input_section, rel->r_offset)
|
||||
+ input_section
|
||||
->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
|
||||
offset = _bfd_elf_section_offset
|
||||
(output_bfd, info,
|
||||
input_section, rel->r_offset);
|
||||
|
||||
if (offset != (bfd_vma)-1)
|
||||
_bfinfdpic_add_rofixup (output_bfd,
|
||||
bfinfdpic_gotfixup_section
|
||||
(info),
|
||||
offset + input_section
|
||||
->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
}
|
||||
}
|
||||
else if ((bfd_get_section_flags (output_bfd,
|
||||
@ -2888,14 +2900,8 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
}
|
||||
offset = _bfd_elf_section_offset (output_bfd, info,
|
||||
input_section, rel->r_offset);
|
||||
/* Only output a reloc for a not deleted entry. */
|
||||
if (offset >= (bfd_vma) -2)
|
||||
_bfinfdpic_add_dyn_reloc (output_bfd,
|
||||
bfinfdpic_gotrel_section (info),
|
||||
0,
|
||||
R_BFIN_UNUSED0,
|
||||
dynindx, addend, picrel);
|
||||
else
|
||||
|
||||
if (offset != (bfd_vma)-1)
|
||||
_bfinfdpic_add_dyn_reloc (output_bfd,
|
||||
bfinfdpic_gotrel_section (info),
|
||||
offset + input_section
|
||||
@ -2986,28 +2992,17 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
}
|
||||
if (!h || h->root.type != bfd_link_hash_undefweak)
|
||||
{
|
||||
/* Only output a reloc for a not deleted entry. */
|
||||
if (offset >= (bfd_vma)-2)
|
||||
_bfinfdpic_add_rofixup (output_bfd,
|
||||
bfinfdpic_gotfixup_section
|
||||
(info), -1, picrel);
|
||||
else
|
||||
_bfinfdpic_add_rofixup (output_bfd,
|
||||
bfinfdpic_gotfixup_section
|
||||
(info),
|
||||
offset + input_section
|
||||
->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
|
||||
if (r_type == R_BFIN_FUNCDESC_VALUE)
|
||||
if (offset != (bfd_vma)-1)
|
||||
{
|
||||
if (offset >= (bfd_vma)-2)
|
||||
_bfinfdpic_add_rofixup
|
||||
(output_bfd,
|
||||
bfinfdpic_gotfixup_section (info),
|
||||
-1, picrel);
|
||||
else
|
||||
_bfinfdpic_add_rofixup (output_bfd,
|
||||
bfinfdpic_gotfixup_section
|
||||
(info),
|
||||
offset + input_section
|
||||
->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
picrel);
|
||||
|
||||
if (r_type == R_BFIN_FUNCDESC_VALUE)
|
||||
_bfinfdpic_add_rofixup
|
||||
(output_bfd,
|
||||
bfinfdpic_gotfixup_section (info),
|
||||
@ -3033,17 +3028,12 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
name, input_bfd, input_section, rel->r_offset);
|
||||
return FALSE;
|
||||
}
|
||||
/* Only output a reloc for a not deleted entry. */
|
||||
if (offset >= (bfd_vma)-2)
|
||||
_bfinfdpic_add_dyn_reloc (output_bfd,
|
||||
bfinfdpic_gotrel_section (info),
|
||||
0, R_BFIN_UNUSED0, dynindx, addend, picrel);
|
||||
else
|
||||
|
||||
if (offset != (bfd_vma)-1)
|
||||
_bfinfdpic_add_dyn_reloc (output_bfd,
|
||||
bfinfdpic_gotrel_section (info),
|
||||
offset
|
||||
+ input_section
|
||||
->output_section->vma
|
||||
+ input_section->output_section->vma
|
||||
+ input_section->output_offset,
|
||||
r_type, dynindx, addend, picrel);
|
||||
}
|
||||
@ -3055,7 +3045,7 @@ bfinfdpic_relocate_section (bfd * output_bfd,
|
||||
relocation = addend - rel->r_addend;
|
||||
}
|
||||
|
||||
if (r_type == R_BFIN_FUNCDESC_VALUE && offset < (bfd_vma)-2)
|
||||
if (r_type == R_BFIN_FUNCDESC_VALUE)
|
||||
{
|
||||
/* If we've omitted the dynamic relocation, just emit
|
||||
the fixed addresses of the symbol and of the local
|
||||
@ -3469,28 +3459,7 @@ _bfin_create_got_section (bfd *abfd, struct bfd_link_info *info)
|
||||
flags = BSF_GLOBAL | BSF_WEAK;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Make sure the got and plt sections exist, and that our pointers in
|
||||
the link hash table point to them. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
/* This is mostly copied from
|
||||
elflink.c:_bfd_elf_create_dynamic_sections(). */
|
||||
flagword flags, pltflags;
|
||||
asection *s;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
|
||||
/* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
|
||||
.rel[a].bss sections. */
|
||||
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED);
|
||||
|
||||
pltflags = flags;
|
||||
flags = pltflags;
|
||||
pltflags |= SEC_CODE;
|
||||
if (bed->plt_not_loaded)
|
||||
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
|
||||
@ -3532,6 +3501,27 @@ elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
/* Blackfin-specific: remember it. */
|
||||
bfinfdpic_pltrel_section (info) = s;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Make sure the got and plt sections exist, and that our pointers in
|
||||
the link hash table point to them. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
{
|
||||
/* This is mostly copied from
|
||||
elflink.c:_bfd_elf_create_dynamic_sections(). */
|
||||
flagword flags;
|
||||
asection *s;
|
||||
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
|
||||
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
|
||||
| SEC_LINKER_CREATED);
|
||||
|
||||
/* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
|
||||
.rel[a].bss sections. */
|
||||
|
||||
/* Blackfin-specific: we want to create the GOT in the Blackfin way. */
|
||||
if (! _bfin_create_got_section (abfd, info))
|
||||
return FALSE;
|
||||
@ -3586,13 +3576,10 @@ elf32_bfinfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
||||
the symbol, an entry pointing to its function descriptor, and a
|
||||
private function descriptors taking two words. */
|
||||
|
||||
static int
|
||||
_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
|
||||
static void
|
||||
_bfinfdpic_count_nontls_entries (struct bfinfdpic_relocs_info *entry,
|
||||
struct _bfinfdpic_dynamic_got_info *dinfo)
|
||||
{
|
||||
struct bfinfdpic_relocs_info *entry = *entryp;
|
||||
struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
|
||||
unsigned relocs = 0, fixups = 0;
|
||||
|
||||
/* Allocate space for a GOT entry pointing to the symbol. */
|
||||
if (entry->got17m4)
|
||||
dinfo->got17m4 += 4;
|
||||
@ -3640,6 +3627,18 @@ _bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
|
||||
|
||||
if (entry->lazyplt)
|
||||
dinfo->lzplt += LZPLT_NORMAL_SIZE;
|
||||
}
|
||||
|
||||
/* Compute the number of dynamic relocations and fixups that a symbol
|
||||
requires, and add (or subtract) from the grand and per-symbol
|
||||
totals. */
|
||||
|
||||
static void
|
||||
_bfinfdpic_count_relocs_fixups (struct bfinfdpic_relocs_info *entry,
|
||||
struct _bfinfdpic_dynamic_got_info *dinfo,
|
||||
bfd_boolean subtract)
|
||||
{
|
||||
bfd_vma relocs = 0, fixups = 0;
|
||||
|
||||
if (!dinfo->info->executable || dinfo->info->pie)
|
||||
relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
|
||||
@ -3665,10 +3664,32 @@ _bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
|
||||
relocs += entry->relocsfd;
|
||||
}
|
||||
|
||||
if (subtract)
|
||||
{
|
||||
relocs = - relocs;
|
||||
fixups = - fixups;
|
||||
}
|
||||
|
||||
entry->dynrelocs += relocs;
|
||||
entry->fixups += fixups;
|
||||
dinfo->relocs += relocs;
|
||||
dinfo->fixups += fixups;
|
||||
}
|
||||
|
||||
/* Compute the total GOT and PLT size required by each symbol in each range. *
|
||||
Symbols may require up to 4 words in the GOT: an entry pointing to
|
||||
the symbol, an entry pointing to its function descriptor, and a
|
||||
private function descriptors taking two words. */
|
||||
|
||||
static int
|
||||
_bfinfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
|
||||
{
|
||||
struct bfinfdpic_relocs_info *entry = *entryp;
|
||||
struct _bfinfdpic_dynamic_got_info *dinfo = dinfo_;
|
||||
|
||||
_bfinfdpic_count_nontls_entries (entry, dinfo);
|
||||
|
||||
_bfinfdpic_count_relocs_fixups (entry, dinfo, FALSE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -3964,6 +3985,23 @@ _bfinfdpic_assign_plt_entries (void **entryp, void *info_)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Cancel out any effects of calling _bfinfdpic_assign_got_entries and
|
||||
_bfinfdpic_assign_plt_entries. */
|
||||
|
||||
static int
|
||||
_bfinfdpic_reset_got_plt_entries (void **entryp, void *ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct bfinfdpic_relocs_info *entry = *entryp;
|
||||
|
||||
entry->got_entry = 0;
|
||||
entry->fdgot_entry = 0;
|
||||
entry->fd_entry = 0;
|
||||
entry->plt_entry = (bfd_vma)-1;
|
||||
entry->lzplt_entry = (bfd_vma)-1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Follow indirect and warning hash entries so that each got entry
|
||||
points to the final symbol definition. P must point to a pointer
|
||||
to the hash table we're traversing. Since this traversal may
|
||||
@ -4020,22 +4058,193 @@ _bfinfdpic_resolve_final_relocs_info (void **entryp, void *p)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Compute the total size of the GOT, the PLT, the dynamic relocations
|
||||
section and the rofixup section. Assign locations for GOT and PLT
|
||||
entries. */
|
||||
|
||||
static bfd_boolean
|
||||
_bfinfdpic_size_got_plt (bfd *output_bfd,
|
||||
struct _bfinfdpic_dynamic_got_plt_info *gpinfop)
|
||||
{
|
||||
bfd_signed_vma odd;
|
||||
bfd_vma limit;
|
||||
struct bfd_link_info *info = gpinfop->g.info;
|
||||
bfd *dynobj = elf_hash_table (info)->dynobj;
|
||||
|
||||
memcpy (bfinfdpic_dynamic_got_plt_info (info), &gpinfop->g,
|
||||
sizeof (gpinfop->g));
|
||||
|
||||
odd = 12;
|
||||
/* Compute the total size taken by entries in the 18-bit range,
|
||||
to tell how many PLT function descriptors we can bring into it
|
||||
without causing it to overflow. */
|
||||
limit = odd + gpinfop->g.got17m4 + gpinfop->g.fd17m4;
|
||||
if (limit < (bfd_vma)1 << 18)
|
||||
limit = ((bfd_vma)1 << 18) - limit;
|
||||
else
|
||||
limit = 0;
|
||||
if (gpinfop->g.fdplt < limit)
|
||||
limit = gpinfop->g.fdplt;
|
||||
|
||||
/* Determine the ranges of GOT offsets that we can use for each
|
||||
range of addressing modes. */
|
||||
odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->got17m4,
|
||||
0,
|
||||
odd,
|
||||
16,
|
||||
gpinfop->g.got17m4,
|
||||
gpinfop->g.fd17m4,
|
||||
limit,
|
||||
(bfd_vma)1 << (18-1));
|
||||
odd = _bfinfdpic_compute_got_alloc_data (&gpinfop->gothilo,
|
||||
gpinfop->got17m4.min,
|
||||
odd,
|
||||
gpinfop->got17m4.max,
|
||||
gpinfop->g.gothilo,
|
||||
gpinfop->g.fdhilo,
|
||||
gpinfop->g.fdplt - gpinfop->got17m4.fdplt,
|
||||
(bfd_vma)1 << (32-1));
|
||||
|
||||
/* Now assign (most) GOT offsets. */
|
||||
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
|
||||
gpinfop);
|
||||
|
||||
bfinfdpic_got_section (info)->size = gpinfop->gothilo.max
|
||||
- gpinfop->gothilo.min
|
||||
/* If an odd word is the last word of the GOT, we don't need this
|
||||
word to be part of the GOT. */
|
||||
- (odd + 4 == gpinfop->gothilo.max ? 4 : 0);
|
||||
if (bfinfdpic_got_section (info)->size == 0)
|
||||
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
|
||||
else if (bfinfdpic_got_section (info)->size == 12
|
||||
&& ! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
|
||||
bfinfdpic_got_section (info)->size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfinfdpic_got_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_got_section (info)->size);
|
||||
if (bfinfdpic_got_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
/* Subtract the number of lzplt entries, since those will generate
|
||||
relocations in the pltrel section. */
|
||||
bfinfdpic_gotrel_section (info)->size =
|
||||
(gpinfop->g.relocs - gpinfop->g.lzplt / LZPLT_NORMAL_SIZE)
|
||||
* get_elf_backend_data (output_bfd)->s->sizeof_rel;
|
||||
else
|
||||
BFD_ASSERT (gpinfop->g.relocs == 0);
|
||||
if (bfinfdpic_gotrel_section (info)->size == 0)
|
||||
bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_gotrel_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_gotrel_section (info)->size);
|
||||
if (bfinfdpic_gotrel_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bfinfdpic_gotfixup_section (info)->size = (gpinfop->g.fixups + 1) * 4;
|
||||
if (bfinfdpic_gotfixup_section (info)->size == 0)
|
||||
bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_gotfixup_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_gotfixup_section (info)->size);
|
||||
if (bfinfdpic_gotfixup_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_pltrel_section (info)->size =
|
||||
gpinfop->g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
|
||||
if (bfinfdpic_pltrel_section (info)->size == 0)
|
||||
bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_pltrel_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_pltrel_section (info)->size);
|
||||
if (bfinfdpic_pltrel_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add 4 bytes for every block of at most 65535 lazy PLT entries,
|
||||
such that there's room for the additional instruction needed to
|
||||
call the resolver. Since _bfinfdpic_assign_got_entries didn't
|
||||
account for them, our block size is 4 bytes smaller than the real
|
||||
block size. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_plt_section (info)->size = gpinfop->g.lzplt
|
||||
+ ((gpinfop->g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
|
||||
/ (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
|
||||
}
|
||||
|
||||
/* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
|
||||
actually assign lazy PLT entries addresses. */
|
||||
gpinfop->g.lzplt = 0;
|
||||
|
||||
/* Save information that we're going to need to generate GOT and PLT
|
||||
entries. */
|
||||
bfinfdpic_got_initial_offset (info) = -gpinfop->gothilo.min;
|
||||
|
||||
if (get_elf_backend_data (output_bfd)->want_got_sym)
|
||||
elf_hash_table (info)->hgot->root.u.def.value
|
||||
= bfinfdpic_got_initial_offset (info);
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
bfinfdpic_plt_initial_offset (info) =
|
||||
bfinfdpic_plt_section (info)->size;
|
||||
|
||||
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
|
||||
gpinfop);
|
||||
|
||||
/* Allocate the PLT section contents only after
|
||||
_bfinfdpic_assign_plt_entries has a chance to add the size of the
|
||||
non-lazy PLT entries. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (bfinfdpic_plt_section (info)->size == 0)
|
||||
bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_plt_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_plt_section (info)->size);
|
||||
if (bfinfdpic_plt_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set the sizes of the dynamic sections. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
|
||||
struct bfd_link_info *info)
|
||||
{
|
||||
struct elf_link_hash_table *htab;
|
||||
bfd *dynobj;
|
||||
asection *s;
|
||||
struct _bfinfdpic_dynamic_got_plt_info gpinfo;
|
||||
bfd_signed_vma odd;
|
||||
bfd_vma limit;
|
||||
|
||||
dynobj = elf_hash_table (info)->dynobj;
|
||||
htab = elf_hash_table (info);
|
||||
dynobj = htab->dynobj;
|
||||
BFD_ASSERT (dynobj != NULL);
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
if (htab->dynamic_sections_created)
|
||||
{
|
||||
/* Set the contents of the .interp section to the interpreter. */
|
||||
if (info->executable)
|
||||
@ -4063,157 +4272,12 @@ elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
|
||||
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
|
||||
&gpinfo.g);
|
||||
|
||||
odd = 12;
|
||||
/* Compute the total size taken by entries in the 18-bit range,
|
||||
to tell how many PLT function descriptors we can bring into it
|
||||
without causing it to overflow. */
|
||||
limit = odd + gpinfo.g.got17m4 + gpinfo.g.fd17m4;
|
||||
if (limit < (bfd_vma)1 << 18)
|
||||
limit = ((bfd_vma)1 << 18) - limit;
|
||||
else
|
||||
limit = 0;
|
||||
if (gpinfo.g.fdplt < limit)
|
||||
limit = gpinfo.g.fdplt;
|
||||
/* Allocate space to save the summary information, we're going to
|
||||
use it if we're doing relaxations. */
|
||||
bfinfdpic_dynamic_got_plt_info (info) = bfd_alloc (dynobj, sizeof (gpinfo.g));
|
||||
|
||||
/* Determine the ranges of GOT offsets that we can use for each
|
||||
range of addressing modes. */
|
||||
odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.got17m4,
|
||||
0,
|
||||
odd,
|
||||
16,
|
||||
gpinfo.g.got17m4,
|
||||
gpinfo.g.fd17m4,
|
||||
limit,
|
||||
(bfd_vma)1 << (18-1));
|
||||
odd = _bfinfdpic_compute_got_alloc_data (&gpinfo.gothilo,
|
||||
gpinfo.got17m4.min,
|
||||
odd,
|
||||
gpinfo.got17m4.max,
|
||||
gpinfo.g.gothilo,
|
||||
gpinfo.g.fdhilo,
|
||||
gpinfo.g.fdplt - gpinfo.got17m4.fdplt,
|
||||
(bfd_vma)1 << (32-1));
|
||||
|
||||
/* Now assign (most) GOT offsets. */
|
||||
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_got_entries,
|
||||
&gpinfo);
|
||||
|
||||
bfinfdpic_got_section (info)->size = gpinfo.gothilo.max
|
||||
- gpinfo.gothilo.min
|
||||
/* If an odd word is the last word of the GOT, we don't need this
|
||||
word to be part of the GOT. */
|
||||
- (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
|
||||
if (bfinfdpic_got_section (info)->size == 0)
|
||||
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
|
||||
else if (bfinfdpic_got_section (info)->size == 12
|
||||
&& ! elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_got_section (info)->flags |= SEC_EXCLUDE;
|
||||
bfinfdpic_got_section (info)->size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfinfdpic_got_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_got_section (info)->size);
|
||||
if (bfinfdpic_got_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
/* Subtract the number of lzplt entries, since those will generate
|
||||
relocations in the pltrel section. */
|
||||
bfinfdpic_gotrel_section (info)->size =
|
||||
(gpinfo.g.relocs - gpinfo.g.lzplt / LZPLT_NORMAL_SIZE)
|
||||
* get_elf_backend_data (output_bfd)->s->sizeof_rel;
|
||||
else
|
||||
BFD_ASSERT (gpinfo.g.relocs == 0);
|
||||
if (bfinfdpic_gotrel_section (info)->size == 0)
|
||||
bfinfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_gotrel_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_gotrel_section (info)->size);
|
||||
if (bfinfdpic_gotrel_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bfinfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
|
||||
if (bfinfdpic_gotfixup_section (info)->size == 0)
|
||||
bfinfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_gotfixup_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_gotfixup_section (info)->size);
|
||||
if (bfinfdpic_gotfixup_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_pltrel_section (info)->size =
|
||||
gpinfo.g.lzplt / LZPLT_NORMAL_SIZE * get_elf_backend_data (output_bfd)->s->sizeof_rel;
|
||||
if (bfinfdpic_pltrel_section (info)->size == 0)
|
||||
bfinfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_pltrel_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_pltrel_section (info)->size);
|
||||
if (bfinfdpic_pltrel_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add 4 bytes for every block of at most 65535 lazy PLT entries,
|
||||
such that there's room for the additional instruction needed to
|
||||
call the resolver. Since _bfinfdpic_assign_got_entries didn't
|
||||
account for them, our block size is 4 bytes smaller than the real
|
||||
block size. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
bfinfdpic_plt_section (info)->size = gpinfo.g.lzplt
|
||||
+ ((gpinfo.g.lzplt + (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) - LZPLT_NORMAL_SIZE)
|
||||
/ (BFINFDPIC_LZPLT_BLOCK_SIZE - 4) * LZPLT_RESOLVER_EXTRA);
|
||||
}
|
||||
|
||||
/* Reset it, such that _bfinfdpic_assign_plt_entries() can use it to
|
||||
actually assign lazy PLT entries addresses. */
|
||||
gpinfo.g.lzplt = 0;
|
||||
|
||||
/* Save information that we're going to need to generate GOT and PLT
|
||||
entries. */
|
||||
bfinfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
|
||||
|
||||
if (get_elf_backend_data (output_bfd)->want_got_sym)
|
||||
elf_hash_table (info)->hgot->root.u.def.value
|
||||
+= bfinfdpic_got_initial_offset (info);
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
bfinfdpic_plt_initial_offset (info) =
|
||||
bfinfdpic_plt_section (info)->size;
|
||||
|
||||
htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_assign_plt_entries,
|
||||
&gpinfo);
|
||||
|
||||
/* Allocate the PLT section contents only after
|
||||
_bfinfdpic_assign_plt_entries has a chance to add the size of the
|
||||
non-lazy PLT entries. */
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
if (bfinfdpic_plt_section (info)->size == 0)
|
||||
bfinfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
|
||||
else
|
||||
{
|
||||
bfinfdpic_plt_section (info)->contents =
|
||||
(bfd_byte *) bfd_zalloc (dynobj,
|
||||
bfinfdpic_plt_section (info)->size);
|
||||
if (bfinfdpic_plt_section (info)->contents == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (!_bfinfdpic_size_got_plt (output_bfd, &gpinfo))
|
||||
return FALSE;
|
||||
|
||||
if (elf_hash_table (info)->dynamic_sections_created)
|
||||
{
|
||||
@ -4275,6 +4339,122 @@ elf32_bfinfdpic_always_size_sections (bfd *output_bfd,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check whether any of the relocations was optimized away, and
|
||||
subtract it from the relocation or fixup count. */
|
||||
static bfd_boolean
|
||||
_bfinfdpic_check_discarded_relocs (bfd *abfd, asection *sec,
|
||||
struct bfd_link_info *info,
|
||||
|
||||
bfd_boolean *changed)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
|
||||
Elf_Internal_Rela *rel, *erel;
|
||||
|
||||
if ((sec->flags & SEC_RELOC) == 0
|
||||
|| sec->reloc_count == 0)
|
||||
return TRUE;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
|
||||
if (!elf_bad_symtab (abfd))
|
||||
sym_hashes_end -= symtab_hdr->sh_info;
|
||||
|
||||
rel = elf_section_data (sec)->relocs;
|
||||
|
||||
/* Now examine each relocation. */
|
||||
for (erel = rel + sec->reloc_count; rel < erel; rel++)
|
||||
{
|
||||
struct elf_link_hash_entry *h;
|
||||
unsigned long r_symndx;
|
||||
struct bfinfdpic_relocs_info *picrel;
|
||||
struct _bfinfdpic_dynamic_got_info *dinfo;
|
||||
|
||||
if (ELF32_R_TYPE (rel->r_info) != R_BFIN_BYTE4_DATA
|
||||
&& ELF32_R_TYPE (rel->r_info) != R_BFIN_FUNCDESC)
|
||||
continue;
|
||||
|
||||
if (_bfd_elf_section_offset (sec->output_section->owner,
|
||||
info, sec, rel->r_offset)
|
||||
!= (bfd_vma)-1)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = NULL;
|
||||
else
|
||||
{
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *)h->root.u.i.link;
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
picrel = bfinfdpic_relocs_info_for_global (bfinfdpic_relocs_info (info),
|
||||
abfd, h,
|
||||
rel->r_addend, NO_INSERT);
|
||||
else
|
||||
picrel = bfinfdpic_relocs_info_for_local (bfinfdpic_relocs_info (info),
|
||||
abfd, r_symndx,
|
||||
rel->r_addend, NO_INSERT);
|
||||
|
||||
if (! picrel)
|
||||
return FALSE;
|
||||
|
||||
*changed = TRUE;
|
||||
dinfo = bfinfdpic_dynamic_got_plt_info (info);
|
||||
|
||||
_bfinfdpic_count_relocs_fixups (picrel, dinfo, TRUE);
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_BFIN_BYTE4_DATA)
|
||||
picrel->relocs32--;
|
||||
else /* we know (ELF32_R_TYPE (rel->r_info) == R_BFIN_FUNCDESC) */
|
||||
picrel->relocsfd--;
|
||||
_bfinfdpic_count_relocs_fixups (picrel, dinfo, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
bfinfdpic_elf_discard_info (bfd *ibfd,
|
||||
struct elf_reloc_cookie *cookie ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info)
|
||||
{
|
||||
bfd_boolean changed = FALSE;
|
||||
asection *s;
|
||||
bfd *obfd = NULL;
|
||||
|
||||
/* Account for relaxation of .eh_frame section. */
|
||||
for (s = ibfd->sections; s; s = s->next)
|
||||
if (s->sec_info_type == ELF_INFO_TYPE_EH_FRAME)
|
||||
{
|
||||
if (!_bfinfdpic_check_discarded_relocs (ibfd, s, info, &changed))
|
||||
return FALSE;
|
||||
obfd = s->output_section->owner;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
struct _bfinfdpic_dynamic_got_plt_info gpinfo;
|
||||
|
||||
memset (&gpinfo, 0, sizeof (gpinfo));
|
||||
memcpy (&gpinfo.g, bfinfdpic_dynamic_got_plt_info (info),
|
||||
sizeof (gpinfo.g));
|
||||
|
||||
/* Clear GOT and PLT assignments. */
|
||||
htab_traverse (bfinfdpic_relocs_info (info),
|
||||
_bfinfdpic_reset_got_plt_entries,
|
||||
NULL);
|
||||
|
||||
if (!_bfinfdpic_size_got_plt (obfd, &gpinfo))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
elf32_bfinfdpic_modify_program_headers (bfd *output_bfd,
|
||||
struct bfd_link_info *info)
|
||||
@ -5678,6 +5858,9 @@ struct bfd_elf_special_section const elf32_bfin_special_sections[] =
|
||||
#define elf_backend_finish_dynamic_sections \
|
||||
elf32_bfinfdpic_finish_dynamic_sections
|
||||
|
||||
#undef elf_backend_discard_info
|
||||
#define elf_backend_discard_info \
|
||||
bfinfdpic_elf_discard_info
|
||||
#undef elf_backend_can_make_relative_eh_frame
|
||||
#define elf_backend_can_make_relative_eh_frame \
|
||||
bfinfdpic_elf_use_relative_eh_frame
|
||||
|
Loading…
Reference in New Issue
Block a user