ppc64 section group handling
Two organizational changes to the array of additional info kept for sections. 1) Move group info into a per-group allocated struct, in preparation for future changes that need per-group accounting. 2) Expand the array to include output sections, which simplifies sizing and removes the need for a separate output section array. * section.c (section_id): Make file scope. (bfd_get_next_section_id): New function. * elf64-ppc.c (struct map_stub): Remove toc_off field. Move decl. (struct ppc_stub_hash_entry): Delete stub_sec and id_sec. Add group. Update all uses. (struct ppc_link_hash_table): Delete top_id, top_index, and input_list. Add sec_info_arr_size. Rename stub_group to sec_info, and make group info indirect. Update stub_group refs throughout file. (ppc_add_stub): Don't look for stub_sec on link_sec stub_group entry. (ppc_build_one_stub): Delete FIXME. (ppc64_elf_setup_section_lists): Size htab->sec_info for all sections, not just input sections. Don't create htab->input_list. (ppc64_elf_next_input_section): Update to use sec_info union as list pointer. (PREV_SEC): Delete. (group_sections): Pass "info" param rather than "htab". Iterate over output sections rather than input_list. Use sec_info union as list pointers. Alloc atruct map_stub, and return fail status. * bfd-in2.h: Regenerate.
This commit is contained in:
parent
136765eab1
commit
6f20ed8a6b
|
@ -1,3 +1,27 @@
|
|||
2015-08-31 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* section.c (section_id): Make file scope.
|
||||
(bfd_get_next_section_id): New function.
|
||||
* elf64-ppc.c (struct map_stub): Remove toc_off field. Move decl.
|
||||
(struct ppc_stub_hash_entry): Delete stub_sec and id_sec. Add
|
||||
group. Update all uses.
|
||||
(struct ppc_link_hash_table): Delete top_id, top_index, and
|
||||
input_list. Add sec_info_arr_size. Rename stub_group to
|
||||
sec_info, and make group info indirect. Update stub_group refs
|
||||
throughout file.
|
||||
(ppc_add_stub): Don't look for stub_sec on link_sec stub_group
|
||||
entry.
|
||||
(ppc_build_one_stub): Delete FIXME.
|
||||
(ppc64_elf_setup_section_lists): Size htab->sec_info for all
|
||||
sections, not just input sections. Don't create htab->input_list.
|
||||
(ppc64_elf_next_input_section): Update to use sec_info union as
|
||||
list pointer.
|
||||
(PREV_SEC): Delete.
|
||||
(group_sections): Pass "info" param rather than "htab". Iterate
|
||||
over output sections rather than input_list. Use sec_info union
|
||||
as list pointers. Alloc atruct map_stub, and return fail status.
|
||||
* bfd-in2.h: Regenerate.
|
||||
|
||||
2015-08-31 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elflink.c (elf_sort_symbol): Use correctly sized type for
|
||||
|
|
|
@ -1818,6 +1818,8 @@ asection *bfd_make_section_with_flags
|
|||
|
||||
asection *bfd_make_section (bfd *, const char *name);
|
||||
|
||||
int bfd_get_next_section_id (void);
|
||||
|
||||
bfd_boolean bfd_set_section_flags
|
||||
(bfd *abfd, asection *sec, flagword flags);
|
||||
|
||||
|
|
323
bfd/elf64-ppc.c
323
bfd/elf64-ppc.c
|
@ -3799,6 +3799,15 @@ enum ppc_stub_type {
|
|||
ppc_stub_global_entry
|
||||
};
|
||||
|
||||
/* Information on stub grouping. */
|
||||
struct map_stub
|
||||
{
|
||||
/* The stub section. */
|
||||
asection *stub_sec;
|
||||
/* This is the section to which stubs in the group will be attached. */
|
||||
asection *link_sec;
|
||||
};
|
||||
|
||||
struct ppc_stub_hash_entry {
|
||||
|
||||
/* Base hash table entry structure. */
|
||||
|
@ -3806,8 +3815,8 @@ struct ppc_stub_hash_entry {
|
|||
|
||||
enum ppc_stub_type stub_type;
|
||||
|
||||
/* The stub section. */
|
||||
asection *stub_sec;
|
||||
/* Group information. */
|
||||
struct map_stub *group;
|
||||
|
||||
/* Offset within stub_sec of the beginning of this stub. */
|
||||
bfd_vma stub_offset;
|
||||
|
@ -3821,10 +3830,6 @@ struct ppc_stub_hash_entry {
|
|||
struct ppc_link_hash_entry *h;
|
||||
struct plt_entry *plt_ent;
|
||||
|
||||
/* Where this stub is being called from, or, in the case of combined
|
||||
stub sections, the first input section in the group. */
|
||||
asection *id_sec;
|
||||
|
||||
/* Symbol st_other. */
|
||||
unsigned char other;
|
||||
};
|
||||
|
@ -3925,34 +3930,34 @@ struct ppc_link_hash_table
|
|||
/* Various options and other info passed from the linker. */
|
||||
struct ppc64_elf_params *params;
|
||||
|
||||
/* Array to keep track of which stub sections have been created, and
|
||||
information on stub grouping. */
|
||||
struct map_stub {
|
||||
/* This is the section to which stubs in the group will be attached. */
|
||||
asection *link_sec;
|
||||
/* The stub section. */
|
||||
asection *stub_sec;
|
||||
/* Along with elf_gp, specifies the TOC pointer used in this group. */
|
||||
/* The size of sec_info below. */
|
||||
unsigned int sec_info_arr_size;
|
||||
|
||||
/* Per-section array of extra section info. Done this way rather
|
||||
than as part of ppc64_elf_section_data so we have the info for
|
||||
non-ppc64 sections. */
|
||||
struct
|
||||
{
|
||||
/* Along with elf_gp, specifies the TOC pointer used by this section. */
|
||||
bfd_vma toc_off;
|
||||
} *stub_group;
|
||||
|
||||
union
|
||||
{
|
||||
/* The section group that this section belongs to. */
|
||||
struct map_stub *group;
|
||||
/* A temp section list pointer. */
|
||||
asection *list;
|
||||
} u;
|
||||
} *sec_info;
|
||||
|
||||
/* Temp used when calculating TOC pointers. */
|
||||
bfd_vma toc_curr;
|
||||
bfd *toc_bfd;
|
||||
asection *toc_first_sec;
|
||||
|
||||
/* Highest input section id. */
|
||||
unsigned int top_id;
|
||||
|
||||
/* Highest output section index. */
|
||||
unsigned int top_index;
|
||||
|
||||
/* Used when adding symbols. */
|
||||
struct ppc_link_hash_entry *dot_syms;
|
||||
|
||||
/* List of input sections for each output section. */
|
||||
asection **input_list;
|
||||
|
||||
/* Shortcuts to get to dynamic linker sections. */
|
||||
asection *dynbss;
|
||||
asection *relbss;
|
||||
|
@ -4056,13 +4061,12 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
|||
/* Initialize the local fields. */
|
||||
eh = (struct ppc_stub_hash_entry *) entry;
|
||||
eh->stub_type = ppc_stub_none;
|
||||
eh->stub_sec = NULL;
|
||||
eh->group = NULL;
|
||||
eh->stub_offset = 0;
|
||||
eh->target_value = 0;
|
||||
eh->target_section = NULL;
|
||||
eh->h = NULL;
|
||||
eh->plt_ent = NULL;
|
||||
eh->id_sec = NULL;
|
||||
eh->other = 0;
|
||||
}
|
||||
|
||||
|
@ -4412,18 +4416,18 @@ ppc_get_stub_entry (const asection *input_section,
|
|||
struct ppc_link_hash_table *htab)
|
||||
{
|
||||
struct ppc_stub_hash_entry *stub_entry;
|
||||
const asection *id_sec;
|
||||
struct map_stub *group;
|
||||
|
||||
/* If this input section is part of a group of sections sharing one
|
||||
stub section, then use the id of the first section in the group.
|
||||
Stub names need to include a section id, as there may well be
|
||||
more than one stub used to reach say, printf, and we need to
|
||||
distinguish between them. */
|
||||
id_sec = htab->stub_group[input_section->id].link_sec;
|
||||
group = htab->sec_info[input_section->id].u.group;
|
||||
|
||||
if (h != NULL && h->u.stub_cache != NULL
|
||||
&& h->u.stub_cache->h == h
|
||||
&& h->u.stub_cache->id_sec == id_sec)
|
||||
&& h->u.stub_cache->group == group)
|
||||
{
|
||||
stub_entry = h->u.stub_cache;
|
||||
}
|
||||
|
@ -4431,7 +4435,7 @@ ppc_get_stub_entry (const asection *input_section,
|
|||
{
|
||||
char *stub_name;
|
||||
|
||||
stub_name = ppc_stub_name (id_sec, sym_sec, h, rel);
|
||||
stub_name = ppc_stub_name (group->link_sec, sym_sec, h, rel);
|
||||
if (stub_name == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -4455,35 +4459,32 @@ ppc_add_stub (const char *stub_name,
|
|||
struct bfd_link_info *info)
|
||||
{
|
||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
struct map_stub *group;
|
||||
asection *link_sec;
|
||||
asection *stub_sec;
|
||||
struct ppc_stub_hash_entry *stub_entry;
|
||||
|
||||
link_sec = htab->stub_group[section->id].link_sec;
|
||||
stub_sec = htab->stub_group[section->id].stub_sec;
|
||||
group = htab->sec_info[section->id].u.group;
|
||||
link_sec = group->link_sec;
|
||||
stub_sec = group->stub_sec;
|
||||
if (stub_sec == NULL)
|
||||
{
|
||||
stub_sec = htab->stub_group[link_sec->id].stub_sec;
|
||||
size_t namelen;
|
||||
bfd_size_type len;
|
||||
char *s_name;
|
||||
|
||||
namelen = strlen (link_sec->name);
|
||||
len = namelen + sizeof (STUB_SUFFIX);
|
||||
s_name = bfd_alloc (htab->params->stub_bfd, len);
|
||||
if (s_name == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (s_name, link_sec->name, namelen);
|
||||
memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
|
||||
stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
|
||||
if (stub_sec == NULL)
|
||||
{
|
||||
size_t namelen;
|
||||
bfd_size_type len;
|
||||
char *s_name;
|
||||
|
||||
namelen = strlen (link_sec->name);
|
||||
len = namelen + sizeof (STUB_SUFFIX);
|
||||
s_name = bfd_alloc (htab->params->stub_bfd, len);
|
||||
if (s_name == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (s_name, link_sec->name, namelen);
|
||||
memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
|
||||
stub_sec = (*htab->params->add_stub_section) (s_name, link_sec);
|
||||
if (stub_sec == NULL)
|
||||
return NULL;
|
||||
htab->stub_group[link_sec->id].stub_sec = stub_sec;
|
||||
}
|
||||
htab->stub_group[section->id].stub_sec = stub_sec;
|
||||
return NULL;
|
||||
group->stub_sec = stub_sec;
|
||||
}
|
||||
|
||||
/* Enter this entry into the linker stub hash table. */
|
||||
|
@ -4496,9 +4497,8 @@ ppc_add_stub (const char *stub_name,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
stub_entry->stub_sec = stub_sec;
|
||||
stub_entry->group = group;
|
||||
stub_entry->stub_offset = 0;
|
||||
stub_entry->id_sec = link_sec;
|
||||
return stub_entry;
|
||||
}
|
||||
|
||||
|
@ -10257,7 +10257,7 @@ plt_stub_pad (struct ppc_link_hash_table *htab,
|
|||
{
|
||||
int stub_align = 1 << htab->params->plt_stub_align;
|
||||
unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
|
||||
bfd_vma stub_off = stub_entry->stub_sec->size;
|
||||
bfd_vma stub_off = stub_entry->group->stub_sec->size;
|
||||
|
||||
if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
|
||||
> ((stub_size - 1) & -stub_align))
|
||||
|
@ -10300,7 +10300,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||
to = (glinkoff
|
||||
+ htab->glink->output_offset
|
||||
+ htab->glink->output_section->vma);
|
||||
from = (p - stub_entry->stub_sec->contents
|
||||
from = (p - stub_entry->group->stub_sec->contents
|
||||
+ 4 * (ALWAYS_EMIT_R2SAVE
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
+ 4 * (PPC_HA (offset) != 0)
|
||||
|
@ -10308,8 +10308,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||
!= PPC_HA (offset))
|
||||
+ 4 * (plt_static_chain != 0)
|
||||
+ 20
|
||||
+ stub_entry->stub_sec->output_offset
|
||||
+ stub_entry->stub_sec->output_section->vma);
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
cmp_branch_off = to - from;
|
||||
use_fake_dep = cmp_branch_off + (1 << 25) >= (1 << 26);
|
||||
}
|
||||
|
@ -10522,7 +10522,7 @@ get_r2off (struct bfd_link_info *info,
|
|||
struct ppc_stub_hash_entry *stub_entry)
|
||||
{
|
||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
bfd_vma r2off = htab->stub_group[stub_entry->target_section->id].toc_off;
|
||||
bfd_vma r2off = htab->sec_info[stub_entry->target_section->id].toc_off;
|
||||
|
||||
if (r2off == 0)
|
||||
{
|
||||
|
@ -10547,7 +10547,7 @@ get_r2off (struct bfd_link_info *info,
|
|||
r2off = bfd_get_64 (opd->owner, buf);
|
||||
r2off -= elf_gp (info->output_bfd);
|
||||
}
|
||||
r2off -= htab->stub_group[stub_entry->id_sec->id].toc_off;
|
||||
r2off -= htab->sec_info[stub_entry->group->link_sec->id].toc_off;
|
||||
return r2off;
|
||||
}
|
||||
|
||||
|
@ -10574,8 +10574,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
return FALSE;
|
||||
|
||||
/* Make a note of the offset within the stubs for this entry. */
|
||||
stub_entry->stub_offset = stub_entry->stub_sec->size;
|
||||
loc = stub_entry->stub_sec->contents + stub_entry->stub_offset;
|
||||
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
||||
loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
|
||||
|
||||
htab->stub_count[stub_entry->stub_type - 1] += 1;
|
||||
switch (stub_entry->stub_type)
|
||||
|
@ -10591,8 +10591,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
|
||||
/* And this is where we are coming from. */
|
||||
off -= (stub_entry->stub_offset
|
||||
+ stub_entry->stub_sec->output_offset
|
||||
+ stub_entry->stub_sec->output_section->vma);
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
|
||||
size = 4;
|
||||
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
|
||||
|
@ -10631,10 +10631,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
|
||||
if (info->emitrelocations)
|
||||
{
|
||||
r = get_relocs (stub_entry->stub_sec, 1);
|
||||
r = get_relocs (stub_entry->group->stub_sec, 1);
|
||||
if (r == NULL)
|
||||
return FALSE;
|
||||
r->r_offset = loc - stub_entry->stub_sec->contents;
|
||||
r->r_offset = loc - stub_entry->group->stub_sec->contents;
|
||||
r->r_info = ELF64_R_INFO (0, R_PPC64_REL24);
|
||||
r->r_addend = dest;
|
||||
if (stub_entry->h != NULL)
|
||||
|
@ -10741,7 +10741,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
|
||||
off = (dest
|
||||
- elf_gp (htab->brlt->output_section->owner)
|
||||
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
||||
- htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
|
||||
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
||||
{
|
||||
|
@ -10755,10 +10755,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
|
||||
if (info->emitrelocations)
|
||||
{
|
||||
r = get_relocs (stub_entry->stub_sec, 1 + (PPC_HA (off) != 0));
|
||||
r = get_relocs (stub_entry->group->stub_sec, 1 + (PPC_HA (off) != 0));
|
||||
if (r == NULL)
|
||||
return FALSE;
|
||||
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
||||
r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
|
||||
if (bfd_big_endian (info->output_bfd))
|
||||
r[0].r_offset += 2;
|
||||
if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
|
||||
|
@ -10847,11 +10847,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
struct ppc_link_hash_entry *fh = ppc_follow_link (stub_entry->h->oh);
|
||||
|
||||
/* If the old-ABI "dot-symbol" is undefined make it weak so
|
||||
we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.
|
||||
FIXME: We used to define the symbol on one of the call
|
||||
stubs instead, which is why we test symbol section id
|
||||
against htab->top_id in various places. Likely all
|
||||
these checks could now disappear. */
|
||||
we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL. */
|
||||
if (fh->elf.root.type == bfd_link_hash_undefined)
|
||||
fh->elf.root.type = bfd_link_hash_undefweak;
|
||||
/* Stop undo_symbol_twiddle changing it back to undefined. */
|
||||
|
@ -10895,7 +10891,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
|
||||
off = (dest
|
||||
- elf_gp (plt->output_section->owner)
|
||||
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
||||
- htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
|
||||
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
|
||||
{
|
||||
|
@ -10913,15 +10909,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
{
|
||||
unsigned pad = plt_stub_pad (htab, stub_entry, off);
|
||||
|
||||
stub_entry->stub_sec->size += pad;
|
||||
stub_entry->stub_offset = stub_entry->stub_sec->size;
|
||||
stub_entry->group->stub_sec->size += pad;
|
||||
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
||||
loc += pad;
|
||||
}
|
||||
|
||||
r = NULL;
|
||||
if (info->emitrelocations)
|
||||
{
|
||||
r = get_relocs (stub_entry->stub_sec,
|
||||
r = get_relocs (stub_entry->group->stub_sec,
|
||||
((PPC_HA (off) != 0)
|
||||
+ (htab->opd_abi
|
||||
? 2 + (htab->params->plt_static_chain
|
||||
|
@ -10929,7 +10925,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
: 1)));
|
||||
if (r == NULL)
|
||||
return FALSE;
|
||||
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
||||
r[0].r_offset = loc - stub_entry->group->stub_sec->contents;
|
||||
if (bfd_big_endian (info->output_bfd))
|
||||
r[0].r_offset += 2;
|
||||
r[0].r_addend = dest;
|
||||
|
@ -10949,7 +10945,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
stub_entry->stub_sec->size += size;
|
||||
stub_entry->group->stub_sec->size += size;
|
||||
|
||||
if (htab->params->emit_stub_syms)
|
||||
{
|
||||
|
@ -10977,7 +10973,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
if (h->root.type == bfd_link_hash_new)
|
||||
{
|
||||
h->root.type = bfd_link_hash_defined;
|
||||
h->root.u.def.section = stub_entry->stub_sec;
|
||||
h->root.u.def.section = stub_entry->group->stub_sec;
|
||||
h->root.u.def.value = stub_entry->stub_offset;
|
||||
h->ref_regular = 1;
|
||||
h->def_regular = 1;
|
||||
|
@ -11027,20 +11023,20 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
off += (plt->output_offset
|
||||
+ plt->output_section->vma
|
||||
- elf_gp (plt->output_section->owner)
|
||||
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
||||
- htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
|
||||
size = plt_stub_size (htab, stub_entry, off);
|
||||
if (htab->params->plt_stub_align)
|
||||
size += plt_stub_pad (htab, stub_entry, off);
|
||||
if (info->emitrelocations)
|
||||
{
|
||||
stub_entry->stub_sec->reloc_count
|
||||
stub_entry->group->stub_sec->reloc_count
|
||||
+= ((PPC_HA (off) != 0)
|
||||
+ (htab->opd_abi
|
||||
? 2 + (htab->params->plt_static_chain
|
||||
&& PPC_HA (off + 16) == PPC_HA (off))
|
||||
: 1));
|
||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -11053,9 +11049,9 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
off = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
off -= (stub_entry->stub_sec->size
|
||||
+ stub_entry->stub_sec->output_offset
|
||||
+ stub_entry->stub_sec->output_section->vma);
|
||||
off -= (stub_entry->group->stub_sec->size
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
|
||||
/* Reset the stub type from the plt variant in case we now
|
||||
can reach with a shorter stub. */
|
||||
|
@ -11118,12 +11114,13 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
+ htab->brlt->output_offset
|
||||
+ htab->brlt->output_section->vma
|
||||
- elf_gp (htab->brlt->output_section->owner)
|
||||
- htab->stub_group[stub_entry->id_sec->id].toc_off);
|
||||
- htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
|
||||
if (info->emitrelocations)
|
||||
{
|
||||
stub_entry->stub_sec->reloc_count += 1 + (PPC_HA (off) != 0);
|
||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
||||
stub_entry->group->stub_sec->reloc_count
|
||||
+= 1 + (PPC_HA (off) != 0);
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
|
||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
||||
|
@ -11146,12 +11143,12 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
}
|
||||
else if (info->emitrelocations)
|
||||
{
|
||||
stub_entry->stub_sec->reloc_count += 1;
|
||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
||||
stub_entry->group->stub_sec->reloc_count += 1;
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
}
|
||||
|
||||
stub_entry->stub_sec->size += size;
|
||||
stub_entry->group->stub_sec->size += size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -11162,57 +11159,22 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
int
|
||||
ppc64_elf_setup_section_lists (struct bfd_link_info *info)
|
||||
{
|
||||
bfd *input_bfd;
|
||||
unsigned int top_id, top_index, id;
|
||||
asection *section;
|
||||
asection **input_list;
|
||||
unsigned int id;
|
||||
bfd_size_type amt;
|
||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||
|
||||
if (htab == NULL)
|
||||
return -1;
|
||||
|
||||
/* Find the top input section id. */
|
||||
for (input_bfd = info->input_bfds, top_id = 3;
|
||||
input_bfd != NULL;
|
||||
input_bfd = input_bfd->link.next)
|
||||
{
|
||||
for (section = input_bfd->sections;
|
||||
section != NULL;
|
||||
section = section->next)
|
||||
{
|
||||
if (top_id < section->id)
|
||||
top_id = section->id;
|
||||
}
|
||||
}
|
||||
|
||||
htab->top_id = top_id;
|
||||
amt = sizeof (struct map_stub) * (top_id + 1);
|
||||
htab->stub_group = bfd_zmalloc (amt);
|
||||
if (htab->stub_group == NULL)
|
||||
htab->sec_info_arr_size = bfd_get_next_section_id ();
|
||||
amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
|
||||
htab->sec_info = bfd_zmalloc (amt);
|
||||
if (htab->sec_info == NULL)
|
||||
return -1;
|
||||
|
||||
/* Set toc_off for com, und, abs and ind sections. */
|
||||
for (id = 0; id < 3; id++)
|
||||
htab->stub_group[id].toc_off = TOC_BASE_OFF;
|
||||
|
||||
/* We can't use output_bfd->section_count here to find the top output
|
||||
section index as some sections may have been removed, and
|
||||
strip_excluded_output_sections doesn't renumber the indices. */
|
||||
for (section = info->output_bfd->sections, top_index = 0;
|
||||
section != NULL;
|
||||
section = section->next)
|
||||
{
|
||||
if (top_index < section->index)
|
||||
top_index = section->index;
|
||||
}
|
||||
|
||||
htab->top_index = top_index;
|
||||
amt = sizeof (asection *) * (top_index + 1);
|
||||
input_list = bfd_zmalloc (amt);
|
||||
htab->input_list = input_list;
|
||||
if (input_list == NULL)
|
||||
return -1;
|
||||
htab->sec_info[id].toc_off = TOC_BASE_OFF;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -11761,15 +11723,13 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
|
|||
return FALSE;
|
||||
|
||||
if ((isec->output_section->flags & SEC_CODE) != 0
|
||||
&& isec->output_section->index <= htab->top_index)
|
||||
&& isec->output_section->id < htab->sec_info_arr_size)
|
||||
{
|
||||
asection **list = htab->input_list + isec->output_section->index;
|
||||
/* Steal the link_sec pointer for our list. */
|
||||
#define PREV_SEC(sec) (htab->stub_group[(sec)->id].link_sec)
|
||||
/* This happens to make the list in reverse order,
|
||||
which is what we want. */
|
||||
PREV_SEC (isec) = *list;
|
||||
*list = isec;
|
||||
htab->sec_info[isec->id].u.list
|
||||
= htab->sec_info[isec->output_section->id].u.list;
|
||||
htab->sec_info[isec->output_section->id].u.list = isec;
|
||||
}
|
||||
|
||||
if (htab->multi_toc_needed)
|
||||
|
@ -11793,7 +11753,7 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
|
|||
htab->toc_curr = elf_gp (isec->owner);
|
||||
}
|
||||
|
||||
htab->stub_group[isec->id].toc_off = htab->toc_curr;
|
||||
htab->sec_info[isec->id].toc_off = htab->toc_curr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -11815,8 +11775,8 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
|
|||
if (i->has_toc_reloc)
|
||||
{
|
||||
if (toc_off == 0)
|
||||
toc_off = htab->stub_group[i->id].toc_off;
|
||||
else if (toc_off != htab->stub_group[i->id].toc_off)
|
||||
toc_off = htab->sec_info[i->id].toc_off;
|
||||
else if (toc_off != htab->sec_info[i->id].toc_off)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -11824,14 +11784,14 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
|
|||
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||
if (i->makes_toc_func_call)
|
||||
{
|
||||
toc_off = htab->stub_group[i->id].toc_off;
|
||||
toc_off = htab->sec_info[i->id].toc_off;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the whole pasted function uses the same toc offset. */
|
||||
if (toc_off != 0)
|
||||
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||
htab->stub_group[i->id].toc_off = toc_off;
|
||||
htab->sec_info[i->id].toc_off = toc_off;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -11850,15 +11810,20 @@ ppc64_elf_check_init_fini (struct bfd_link_info *info)
|
|||
_init and _fini functions into multiple parts. Putting a stub in
|
||||
the middle of a function is not a good idea. */
|
||||
|
||||
static void
|
||||
group_sections (struct ppc_link_hash_table *htab,
|
||||
static bfd_boolean
|
||||
group_sections (struct bfd_link_info *info,
|
||||
bfd_size_type stub_group_size,
|
||||
bfd_boolean stubs_always_before_branch)
|
||||
{
|
||||
asection **list;
|
||||
struct ppc_link_hash_table *htab;
|
||||
asection *osec;
|
||||
bfd_size_type stub14_group_size;
|
||||
bfd_boolean suppress_size_errors;
|
||||
|
||||
htab = ppc_hash_table (info);
|
||||
if (htab == NULL)
|
||||
return FALSE;
|
||||
|
||||
suppress_size_errors = FALSE;
|
||||
stub14_group_size = stub_group_size >> 10;
|
||||
if (stub_group_size == 1)
|
||||
|
@ -11877,10 +11842,14 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
suppress_size_errors = TRUE;
|
||||
}
|
||||
|
||||
list = htab->input_list + htab->top_index;
|
||||
do
|
||||
for (osec = info->output_bfd->sections; osec != NULL; osec = osec->next)
|
||||
{
|
||||
asection *tail = *list;
|
||||
asection *tail;
|
||||
|
||||
if (osec->id >= htab->sec_info_arr_size)
|
||||
continue;
|
||||
|
||||
tail = htab->sec_info[osec->id].u.list;
|
||||
while (tail != NULL)
|
||||
{
|
||||
asection *curr;
|
||||
|
@ -11888,6 +11857,7 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
bfd_size_type total;
|
||||
bfd_boolean big_sec;
|
||||
bfd_vma curr_toc;
|
||||
struct map_stub *group;
|
||||
|
||||
curr = tail;
|
||||
total = tail->size;
|
||||
|
@ -11897,14 +11867,14 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
if (big_sec && !suppress_size_errors)
|
||||
(*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
|
||||
tail->owner, tail);
|
||||
curr_toc = htab->stub_group[tail->id].toc_off;
|
||||
curr_toc = htab->sec_info[tail->id].toc_off;
|
||||
|
||||
while ((prev = PREV_SEC (curr)) != NULL
|
||||
while ((prev = htab->sec_info[curr->id].u.list) != NULL
|
||||
&& ((total += curr->output_offset - prev->output_offset)
|
||||
< (ppc64_elf_section_data (prev) != NULL
|
||||
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
||||
? stub14_group_size : stub_group_size))
|
||||
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
||||
&& htab->sec_info[prev->id].toc_off == curr_toc)
|
||||
curr = prev;
|
||||
|
||||
/* OK, the size from the start of CURR to the end is less
|
||||
|
@ -11917,11 +11887,16 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
only break if stubs added make the total size more than
|
||||
2^25, ie. for the default stub_group_size, if stubs total
|
||||
more than 2097152 bytes, or nearly 75000 plt call stubs. */
|
||||
group = bfd_alloc (curr->owner, sizeof (*group));
|
||||
if (group == NULL)
|
||||
return FALSE;
|
||||
group->link_sec = curr;
|
||||
group->stub_sec = NULL;
|
||||
do
|
||||
{
|
||||
prev = PREV_SEC (tail);
|
||||
prev = htab->sec_info[tail->id].u.list;
|
||||
/* Set up this stub group. */
|
||||
htab->stub_group[tail->id].link_sec = curr;
|
||||
htab->sec_info[tail->id].u.group = group;
|
||||
}
|
||||
while (tail != curr && (tail = prev) != NULL);
|
||||
|
||||
|
@ -11938,19 +11913,17 @@ group_sections (struct ppc_link_hash_table *htab,
|
|||
< (ppc64_elf_section_data (prev) != NULL
|
||||
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
||||
? stub14_group_size : stub_group_size))
|
||||
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
||||
&& htab->sec_info[prev->id].toc_off == curr_toc)
|
||||
{
|
||||
tail = prev;
|
||||
prev = PREV_SEC (tail);
|
||||
htab->stub_group[tail->id].link_sec = curr;
|
||||
prev = htab->sec_info[tail->id].u.list;
|
||||
htab->sec_info[tail->id].u.group = group;
|
||||
}
|
||||
}
|
||||
tail = prev;
|
||||
}
|
||||
}
|
||||
while (list-- != htab->input_list);
|
||||
free (htab->input_list);
|
||||
#undef PREV_SEC
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const unsigned char glink_eh_frame_cie[] =
|
||||
|
@ -12055,7 +12028,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||
else
|
||||
stub_group_size = htab->params->group_size;
|
||||
|
||||
group_sections (htab, stub_group_size, stubs_always_before_branch);
|
||||
if (!group_sections (info, stub_group_size, stubs_always_before_branch))
|
||||
return FALSE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
@ -12258,8 +12232,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||
fact a call needing a TOC adjustment. */
|
||||
if (code_sec != NULL
|
||||
&& code_sec->output_section != NULL
|
||||
&& (htab->stub_group[code_sec->id].toc_off
|
||||
!= htab->stub_group[section->id].toc_off)
|
||||
&& (htab->sec_info[code_sec->id].toc_off
|
||||
!= htab->sec_info[section->id].toc_off)
|
||||
&& (code_sec->has_toc_reloc
|
||||
|| code_sec->makes_toc_func_call))
|
||||
stub_type = ppc_stub_long_branch_r2off;
|
||||
|
@ -12299,7 +12273,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||
stub_type = ppc_stub_plt_call_r2save;
|
||||
|
||||
/* Support for grouping stub sections. */
|
||||
id_sec = htab->stub_group[section->id].link_sec;
|
||||
id_sec = htab->sec_info[section->id].u.group->link_sec;
|
||||
|
||||
/* Get the name of this stub. */
|
||||
stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela);
|
||||
|
@ -13234,8 +13208,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
|
||||
if (h != NULL && &h->elf == htab->elf.hgot)
|
||||
{
|
||||
relocation = (TOCstart
|
||||
+ htab->stub_group[input_section->id].toc_off);
|
||||
relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
|
||||
sec = bfd_abs_section_ptr;
|
||||
unresolved_reloc = FALSE;
|
||||
}
|
||||
|
@ -13943,8 +13916,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
/* Munge up the value and addend so that we call the stub
|
||||
rather than the procedure directly. */
|
||||
relocation = (stub_entry->stub_offset
|
||||
+ stub_entry->stub_sec->output_offset
|
||||
+ stub_entry->stub_sec->output_section->vma);
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
addend = 0;
|
||||
reloc_dest = DEST_STUB;
|
||||
|
||||
|
@ -14241,7 +14214,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
abort ();
|
||||
|
||||
relocation = got->output_section->vma + got->output_offset + off;
|
||||
addend = -(TOCstart + htab->stub_group[input_section->id].toc_off);
|
||||
addend = -(TOCstart + htab->sec_info[input_section->id].toc_off);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -14282,11 +14255,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
/* Relocation value is TOC base. */
|
||||
relocation = TOCstart;
|
||||
if (r_symndx == STN_UNDEF)
|
||||
relocation += htab->stub_group[input_section->id].toc_off;
|
||||
relocation += htab->sec_info[input_section->id].toc_off;
|
||||
else if (unresolved_reloc)
|
||||
;
|
||||
else if (sec != NULL && sec->id <= htab->top_id)
|
||||
relocation += htab->stub_group[sec->id].toc_off;
|
||||
else if (sec != NULL && sec->id < htab->sec_info_arr_size)
|
||||
relocation += htab->sec_info[sec->id].toc_off;
|
||||
else
|
||||
unresolved_reloc = TRUE;
|
||||
goto dodyn;
|
||||
|
@ -14301,7 +14274,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
case R_PPC64_TOC16_DS:
|
||||
case R_PPC64_TOC16_LO_DS:
|
||||
case R_PPC64_TOC16_HA:
|
||||
addend -= TOCstart + htab->stub_group[input_section->id].toc_off;
|
||||
addend -= TOCstart + htab->sec_info[input_section->id].toc_off;
|
||||
break;
|
||||
|
||||
/* Relocate against the beginning of the section. */
|
||||
|
|
|
@ -821,13 +821,13 @@ _bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static unsigned int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
|
||||
|
||||
/* Initializes a new section. NEWSECT->NAME is already set. */
|
||||
|
||||
static asection *
|
||||
bfd_section_init (bfd *abfd, asection *newsect)
|
||||
{
|
||||
static unsigned int section_id = 0x10; /* id 0 to 3 used by STD_SECTION. */
|
||||
|
||||
newsect->id = section_id;
|
||||
newsect->index = abfd->section_count;
|
||||
newsect->owner = abfd;
|
||||
|
@ -1273,6 +1273,23 @@ bfd_make_section (bfd *abfd, const char *name)
|
|||
return bfd_make_section_with_flags (abfd, name, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
bfd_get_next_section_id
|
||||
|
||||
SYNOPSIS
|
||||
int bfd_get_next_section_id (void);
|
||||
|
||||
DESCRIPTION
|
||||
Returns the id that the next section created will have.
|
||||
*/
|
||||
|
||||
int
|
||||
bfd_get_next_section_id (void)
|
||||
{
|
||||
return section_id;
|
||||
}
|
||||
|
||||
/*
|
||||
FUNCTION
|
||||
bfd_set_section_flags
|
||||
|
|
Loading…
Reference in New Issue