This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Blackfin: BFD fixes for deleted relocs
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: binutils at sources dot redhat dot com
- Date: Tue, 11 Aug 2009 13:40:21 +0100
- Subject: Blackfin: BFD fixes for deleted relocs
Over time, the Blackfin and FRV FD-PIC implementations have slightly
diverged. We've had our own fixes for dealing with deleted relocs in
eh-frame sections, and these have worked in the 2.17 tree we're using
locally. However, with CVS binutils there are lots of assertion
failures when trying to link C++ programs.
This patch just copies over the FRV version of these fixes. To do that,
I've also had to bring in a few structural changes - the FRV code got a
bit rearranged with the introduction of TLS.
Bernd
--
This footer brought to you by insane German lawmakers.
Analog Devices GmbH Wilhelm-Wagenfeld-Str. 6 80807 Muenchen
Sitz der Gesellschaft Muenchen, Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, William A. Martin, Margaret Seif
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.4735
diff -c -p -r1.4735 ChangeLog
*** ChangeLog 11 Aug 2009 02:21:34 -0000 1.4735
--- ChangeLog 11 Aug 2009 11:40:02 -0000
***************
*** 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,75 ****
(ppc_elf_size_dynamic_sections): Likewise.
(ppc_elf_relocate_section): Likewise.
! 2006-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,
--- 89,95 ----
(ppc_elf_size_dynamic_sections): Likewise.
(ppc_elf_relocate_section): Likewise.
! 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,
Index: elf32-bfin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-bfin.c,v
retrieving revision 1.39
diff -c -p -r1.39 elf32-bfin.c
*** elf32-bfin.c 9 Aug 2009 16:45:04 -0000 1.39
--- elf32-bfin.c 11 Aug 2009 11:40:03 -0000
*************** struct bfinfdpic_elf_link_hash_table
*** 1740,1745 ****
--- 1740,1748 ----
/* 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. */
*************** struct bfinfdpic_elf_link_hash_table
*** 1763,1768 ****
--- 1766,1773 ----
(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. */
*************** _bfinfdpic_emit_got_relocs_plt_entries (
*** 2149,2155 ****
dynindx = entry->d.h->dynindx;
else
{
! if (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;
--- 2154,2161 ----
dynindx = entry->d.h->dynindx;
else
{
! 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;
*************** _bfinfdpic_emit_got_relocs_plt_entries (
*** 2417,2424 ****
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)
highword = 0;
else
highword = _bfinfdpic_osec_to_segment
--- 2423,2431 ----
of the section. For a non-local function, it's
disregarded. */
lowword = ad;
! if (sec == NULL
! || (entry->symndx == -1 && entry->d.h->dynindx != -1
! && entry->d.h->dynindx == idx))
highword = 0;
else
highword = _bfinfdpic_osec_to_segment
*************** bfinfdpic_relocate_section (bfd * output
*** 2843,2848 ****
--- 2850,2857 ----
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)
*************** bfinfdpic_relocate_section (bfd * output
*** 2858,2873 ****
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);
}
}
else if ((bfd_get_section_flags (output_bfd,
--- 2867,2885 ----
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
!
! 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,
*************** bfinfdpic_relocate_section (bfd * output
*** 2888,2901 ****
}
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
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset + input_section
--- 2900,2907 ----
}
offset = _bfd_elf_section_offset (output_bfd, info,
input_section, rel->r_offset);
!
! if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset + input_section
*************** bfinfdpic_relocate_section (bfd * output
*** 2986,3013 ****
}
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)-2)
! _bfinfdpic_add_rofixup
! (output_bfd,
! bfinfdpic_gotfixup_section (info),
! -1, picrel);
! else
_bfinfdpic_add_rofixup
(output_bfd,
bfinfdpic_gotfixup_section (info),
--- 2992,3008 ----
}
if (!h || h->root.type != bfd_link_hash_undefweak)
{
! 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);
!
! if (r_type == R_BFIN_FUNCDESC_VALUE)
_bfinfdpic_add_rofixup
(output_bfd,
bfinfdpic_gotfixup_section (info),
*************** bfinfdpic_relocate_section (bfd * output
*** 3033,3049 ****
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
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset
! + input_section
! ->output_section->vma
+ input_section->output_offset,
r_type, dynindx, addend, picrel);
}
--- 3028,3039 ----
name, input_bfd, input_section, rel->r_offset);
return FALSE;
}
!
! if (offset != (bfd_vma)-1)
_bfinfdpic_add_dyn_reloc (output_bfd,
bfinfdpic_gotrel_section (info),
offset
! + input_section->output_section->vma
+ input_section->output_offset,
r_type, dynindx, addend, picrel);
}
*************** bfinfdpic_relocate_section (bfd * output
*** 3055,3061 ****
relocation = addend - rel->r_addend;
}
! if (r_type == R_BFIN_FUNCDESC_VALUE && offset < (bfd_vma)-2)
{
/* If we've omitted the dynamic relocation, just emit
the fixed addresses of the symbol and of the local
--- 3045,3051 ----
relocation = addend - rel->r_addend;
}
! 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
*************** _bfin_create_got_section (bfd *abfd, str
*** 3469,3496 ****
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;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
--- 3459,3465 ----
flags = BSF_GLOBAL | BSF_WEAK;
}
! flags = pltflags;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
*************** elf32_bfinfdpic_create_dynamic_sections
*** 3532,3537 ****
--- 3501,3527 ----
/* 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;
*************** elf32_bfinfdpic_create_dynamic_sections
*** 3586,3598 ****
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_;
- unsigned relocs = 0, fixups = 0;
-
/* Allocate space for a GOT entry pointing to the symbol. */
if (entry->got17m4)
dinfo->got17m4 += 4;
--- 3576,3585 ----
the symbol, an entry pointing to its function descriptor, and a
private function descriptors taking two words. */
! static void
! _bfinfdpic_count_nontls_entries (struct bfinfdpic_relocs_info *entry,
! struct _bfinfdpic_dynamic_got_info *dinfo)
{
/* Allocate space for a GOT entry pointing to the symbol. */
if (entry->got17m4)
dinfo->got17m4 += 4;
*************** _bfinfdpic_count_got_plt_entries (void *
*** 3640,3645 ****
--- 3627,3644 ----
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;
*************** _bfinfdpic_count_got_plt_entries (void *
*** 3665,3674 ****
--- 3664,3695 ----
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;
}
*************** _bfinfdpic_assign_plt_entries (void **en
*** 3964,3969 ****
--- 3985,4007 ----
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
*************** _bfinfdpic_resolve_final_relocs_info (vo
*** 4020,4108 ****
return 1;
}
! /* Set the sizes of the dynamic sections. */
static bfd_boolean
! elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
! struct bfd_link_info *info)
{
- bfd *dynobj;
- asection *s;
- struct _bfinfdpic_dynamic_got_plt_info gpinfo;
bfd_signed_vma odd;
bfd_vma limit;
! dynobj = elf_hash_table (info)->dynobj;
! BFD_ASSERT (dynobj != NULL);
!
! if (elf_hash_table (info)->dynamic_sections_created)
! {
! /* Set the contents of the .interp section to the interpreter. */
! if (info->executable)
! {
! s = bfd_get_section_by_name (dynobj, ".interp");
! BFD_ASSERT (s != NULL);
! s->size = sizeof ELF_DYNAMIC_INTERPRETER;
! s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
! }
! }
!
! memset (&gpinfo, 0, sizeof (gpinfo));
! gpinfo.g.info = info;
!
! for (;;)
! {
! htab_t relocs = bfinfdpic_relocs_info (info);
!
! htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
!
! if (relocs == bfinfdpic_relocs_info (info))
! break;
! }
!
! 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;
/* 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
--- 4058,4119 ----
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
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4124,4133 ****
/* 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
--- 4135,4144 ----
/* 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
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4139,4145 ****
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
--- 4150,4156 ----
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
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4154,4160 ****
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
--- 4165,4171 ----
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
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4174,4202 ****
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
--- 4185,4213 ----
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
*************** elf32_bfinfdpic_size_dynamic_sections (b
*** 4215,4220 ****
--- 4226,4284 ----
}
}
+ 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;
+
+ htab = elf_hash_table (info);
+ dynobj = htab->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (htab->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ gpinfo.g.info = info;
+
+ for (;;)
+ {
+ htab_t relocs = bfinfdpic_relocs_info (info);
+
+ htab_traverse (relocs, _bfinfdpic_resolve_final_relocs_info, &relocs);
+
+ if (relocs == bfinfdpic_relocs_info (info))
+ break;
+ }
+
+ htab_traverse (bfinfdpic_relocs_info (info), _bfinfdpic_count_got_plt_entries,
+ &gpinfo.g);
+
+ /* 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));
+
+ if (!_bfinfdpic_size_got_plt (output_bfd, &gpinfo))
+ return FALSE;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
if (bfinfdpic_got_section (info)->size)
*************** elf32_bfinfdpic_always_size_sections (bf
*** 4275,4280 ****
--- 4339,4460 ----
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)
*************** struct bfd_elf_special_section const elf
*** 5678,5683 ****
--- 5858,5866 ----
#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