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
4 changed files with 193 additions and 177 deletions
|
@ -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>
|
2015-08-31 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elflink.c (elf_sort_symbol): Use correctly sized type for
|
* 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);
|
asection *bfd_make_section (bfd *, const char *name);
|
||||||
|
|
||||||
|
int bfd_get_next_section_id (void);
|
||||||
|
|
||||||
bfd_boolean bfd_set_section_flags
|
bfd_boolean bfd_set_section_flags
|
||||||
(bfd *abfd, asection *sec, flagword 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
|
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 {
|
struct ppc_stub_hash_entry {
|
||||||
|
|
||||||
/* Base hash table entry structure. */
|
/* Base hash table entry structure. */
|
||||||
|
@ -3806,8 +3815,8 @@ struct ppc_stub_hash_entry {
|
||||||
|
|
||||||
enum ppc_stub_type stub_type;
|
enum ppc_stub_type stub_type;
|
||||||
|
|
||||||
/* The stub section. */
|
/* Group information. */
|
||||||
asection *stub_sec;
|
struct map_stub *group;
|
||||||
|
|
||||||
/* Offset within stub_sec of the beginning of this stub. */
|
/* Offset within stub_sec of the beginning of this stub. */
|
||||||
bfd_vma stub_offset;
|
bfd_vma stub_offset;
|
||||||
|
@ -3821,10 +3830,6 @@ struct ppc_stub_hash_entry {
|
||||||
struct ppc_link_hash_entry *h;
|
struct ppc_link_hash_entry *h;
|
||||||
struct plt_entry *plt_ent;
|
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. */
|
/* Symbol st_other. */
|
||||||
unsigned char other;
|
unsigned char other;
|
||||||
};
|
};
|
||||||
|
@ -3925,34 +3930,34 @@ struct ppc_link_hash_table
|
||||||
/* Various options and other info passed from the linker. */
|
/* Various options and other info passed from the linker. */
|
||||||
struct ppc64_elf_params *params;
|
struct ppc64_elf_params *params;
|
||||||
|
|
||||||
/* Array to keep track of which stub sections have been created, and
|
/* The size of sec_info below. */
|
||||||
information on stub grouping. */
|
unsigned int sec_info_arr_size;
|
||||||
struct map_stub {
|
|
||||||
/* This is the section to which stubs in the group will be attached. */
|
/* Per-section array of extra section info. Done this way rather
|
||||||
asection *link_sec;
|
than as part of ppc64_elf_section_data so we have the info for
|
||||||
/* The stub section. */
|
non-ppc64 sections. */
|
||||||
asection *stub_sec;
|
struct
|
||||||
/* Along with elf_gp, specifies the TOC pointer used in this group. */
|
{
|
||||||
|
/* Along with elf_gp, specifies the TOC pointer used by this section. */
|
||||||
bfd_vma toc_off;
|
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. */
|
/* Temp used when calculating TOC pointers. */
|
||||||
bfd_vma toc_curr;
|
bfd_vma toc_curr;
|
||||||
bfd *toc_bfd;
|
bfd *toc_bfd;
|
||||||
asection *toc_first_sec;
|
asection *toc_first_sec;
|
||||||
|
|
||||||
/* Highest input section id. */
|
|
||||||
unsigned int top_id;
|
|
||||||
|
|
||||||
/* Highest output section index. */
|
|
||||||
unsigned int top_index;
|
|
||||||
|
|
||||||
/* Used when adding symbols. */
|
/* Used when adding symbols. */
|
||||||
struct ppc_link_hash_entry *dot_syms;
|
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. */
|
/* Shortcuts to get to dynamic linker sections. */
|
||||||
asection *dynbss;
|
asection *dynbss;
|
||||||
asection *relbss;
|
asection *relbss;
|
||||||
|
@ -4056,13 +4061,12 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
|
||||||
/* Initialize the local fields. */
|
/* Initialize the local fields. */
|
||||||
eh = (struct ppc_stub_hash_entry *) entry;
|
eh = (struct ppc_stub_hash_entry *) entry;
|
||||||
eh->stub_type = ppc_stub_none;
|
eh->stub_type = ppc_stub_none;
|
||||||
eh->stub_sec = NULL;
|
eh->group = NULL;
|
||||||
eh->stub_offset = 0;
|
eh->stub_offset = 0;
|
||||||
eh->target_value = 0;
|
eh->target_value = 0;
|
||||||
eh->target_section = NULL;
|
eh->target_section = NULL;
|
||||||
eh->h = NULL;
|
eh->h = NULL;
|
||||||
eh->plt_ent = NULL;
|
eh->plt_ent = NULL;
|
||||||
eh->id_sec = NULL;
|
|
||||||
eh->other = 0;
|
eh->other = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4412,18 +4416,18 @@ ppc_get_stub_entry (const asection *input_section,
|
||||||
struct ppc_link_hash_table *htab)
|
struct ppc_link_hash_table *htab)
|
||||||
{
|
{
|
||||||
struct ppc_stub_hash_entry *stub_entry;
|
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
|
/* 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 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
|
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
|
more than one stub used to reach say, printf, and we need to
|
||||||
distinguish between them. */
|
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
|
if (h != NULL && h->u.stub_cache != NULL
|
||||||
&& h->u.stub_cache->h == h
|
&& 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;
|
stub_entry = h->u.stub_cache;
|
||||||
}
|
}
|
||||||
|
@ -4431,7 +4435,7 @@ ppc_get_stub_entry (const asection *input_section,
|
||||||
{
|
{
|
||||||
char *stub_name;
|
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)
|
if (stub_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -4455,35 +4459,32 @@ ppc_add_stub (const char *stub_name,
|
||||||
struct bfd_link_info *info)
|
struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||||
|
struct map_stub *group;
|
||||||
asection *link_sec;
|
asection *link_sec;
|
||||||
asection *stub_sec;
|
asection *stub_sec;
|
||||||
struct ppc_stub_hash_entry *stub_entry;
|
struct ppc_stub_hash_entry *stub_entry;
|
||||||
|
|
||||||
link_sec = htab->stub_group[section->id].link_sec;
|
group = htab->sec_info[section->id].u.group;
|
||||||
stub_sec = htab->stub_group[section->id].stub_sec;
|
link_sec = group->link_sec;
|
||||||
|
stub_sec = group->stub_sec;
|
||||||
if (stub_sec == NULL)
|
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)
|
if (stub_sec == NULL)
|
||||||
{
|
return NULL;
|
||||||
size_t namelen;
|
group->stub_sec = stub_sec;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter this entry into the linker stub hash table. */
|
/* Enter this entry into the linker stub hash table. */
|
||||||
|
@ -4496,9 +4497,8 @@ ppc_add_stub (const char *stub_name,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stub_entry->stub_sec = stub_sec;
|
stub_entry->group = group;
|
||||||
stub_entry->stub_offset = 0;
|
stub_entry->stub_offset = 0;
|
||||||
stub_entry->id_sec = link_sec;
|
|
||||||
return stub_entry;
|
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;
|
int stub_align = 1 << htab->params->plt_stub_align;
|
||||||
unsigned stub_size = plt_stub_size (htab, stub_entry, plt_off);
|
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)
|
if (((stub_off + stub_size - 1) & -stub_align) - (stub_off & -stub_align)
|
||||||
> ((stub_size - 1) & -stub_align))
|
> ((stub_size - 1) & -stub_align))
|
||||||
|
@ -10300,7 +10300,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
||||||
to = (glinkoff
|
to = (glinkoff
|
||||||
+ htab->glink->output_offset
|
+ htab->glink->output_offset
|
||||||
+ htab->glink->output_section->vma);
|
+ htab->glink->output_section->vma);
|
||||||
from = (p - stub_entry->stub_sec->contents
|
from = (p - stub_entry->group->stub_sec->contents
|
||||||
+ 4 * (ALWAYS_EMIT_R2SAVE
|
+ 4 * (ALWAYS_EMIT_R2SAVE
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||||
+ 4 * (PPC_HA (offset) != 0)
|
+ 4 * (PPC_HA (offset) != 0)
|
||||||
|
@ -10308,8 +10308,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
||||||
!= PPC_HA (offset))
|
!= PPC_HA (offset))
|
||||||
+ 4 * (plt_static_chain != 0)
|
+ 4 * (plt_static_chain != 0)
|
||||||
+ 20
|
+ 20
|
||||||
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->group->stub_sec->output_offset
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->group->stub_sec->output_section->vma);
|
||||||
cmp_branch_off = to - from;
|
cmp_branch_off = to - from;
|
||||||
use_fake_dep = cmp_branch_off + (1 << 25) >= (1 << 26);
|
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_stub_hash_entry *stub_entry)
|
||||||
{
|
{
|
||||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
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)
|
if (r2off == 0)
|
||||||
{
|
{
|
||||||
|
@ -10547,7 +10547,7 @@ get_r2off (struct bfd_link_info *info,
|
||||||
r2off = bfd_get_64 (opd->owner, buf);
|
r2off = bfd_get_64 (opd->owner, buf);
|
||||||
r2off -= elf_gp (info->output_bfd);
|
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;
|
return r2off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10574,8 +10574,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Make a note of the offset within the stubs for this entry. */
|
/* Make a note of the offset within the stubs for this entry. */
|
||||||
stub_entry->stub_offset = stub_entry->stub_sec->size;
|
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
||||||
loc = stub_entry->stub_sec->contents + stub_entry->stub_offset;
|
loc = stub_entry->group->stub_sec->contents + stub_entry->stub_offset;
|
||||||
|
|
||||||
htab->stub_count[stub_entry->stub_type - 1] += 1;
|
htab->stub_count[stub_entry->stub_type - 1] += 1;
|
||||||
switch (stub_entry->stub_type)
|
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. */
|
/* And this is where we are coming from. */
|
||||||
off -= (stub_entry->stub_offset
|
off -= (stub_entry->stub_offset
|
||||||
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->group->stub_sec->output_offset
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->group->stub_sec->output_section->vma);
|
||||||
|
|
||||||
size = 4;
|
size = 4;
|
||||||
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
|
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)
|
if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
r = get_relocs (stub_entry->stub_sec, 1);
|
r = get_relocs (stub_entry->group->stub_sec, 1);
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return FALSE;
|
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_info = ELF64_R_INFO (0, R_PPC64_REL24);
|
||||||
r->r_addend = dest;
|
r->r_addend = dest;
|
||||||
if (stub_entry->h != NULL)
|
if (stub_entry->h != NULL)
|
||||||
|
@ -10741,7 +10741,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
|
|
||||||
off = (dest
|
off = (dest
|
||||||
- elf_gp (htab->brlt->output_section->owner)
|
- 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)
|
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)
|
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)
|
if (r == NULL)
|
||||||
return FALSE;
|
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))
|
if (bfd_big_endian (info->output_bfd))
|
||||||
r[0].r_offset += 2;
|
r[0].r_offset += 2;
|
||||||
if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
|
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);
|
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
|
/* If the old-ABI "dot-symbol" is undefined make it weak so
|
||||||
we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.
|
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. */
|
|
||||||
if (fh->elf.root.type == bfd_link_hash_undefined)
|
if (fh->elf.root.type == bfd_link_hash_undefined)
|
||||||
fh->elf.root.type = bfd_link_hash_undefweak;
|
fh->elf.root.type = bfd_link_hash_undefweak;
|
||||||
/* Stop undo_symbol_twiddle changing it back to undefined. */
|
/* 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
|
off = (dest
|
||||||
- elf_gp (plt->output_section->owner)
|
- 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)
|
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);
|
unsigned pad = plt_stub_pad (htab, stub_entry, off);
|
||||||
|
|
||||||
stub_entry->stub_sec->size += pad;
|
stub_entry->group->stub_sec->size += pad;
|
||||||
stub_entry->stub_offset = stub_entry->stub_sec->size;
|
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
||||||
loc += pad;
|
loc += pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = NULL;
|
r = NULL;
|
||||||
if (info->emitrelocations)
|
if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
r = get_relocs (stub_entry->stub_sec,
|
r = get_relocs (stub_entry->group->stub_sec,
|
||||||
((PPC_HA (off) != 0)
|
((PPC_HA (off) != 0)
|
||||||
+ (htab->opd_abi
|
+ (htab->opd_abi
|
||||||
? 2 + (htab->params->plt_static_chain
|
? 2 + (htab->params->plt_static_chain
|
||||||
|
@ -10929,7 +10925,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
: 1)));
|
: 1)));
|
||||||
if (r == NULL)
|
if (r == NULL)
|
||||||
return FALSE;
|
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))
|
if (bfd_big_endian (info->output_bfd))
|
||||||
r[0].r_offset += 2;
|
r[0].r_offset += 2;
|
||||||
r[0].r_addend = dest;
|
r[0].r_addend = dest;
|
||||||
|
@ -10949,7 +10945,7 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
stub_entry->stub_sec->size += size;
|
stub_entry->group->stub_sec->size += size;
|
||||||
|
|
||||||
if (htab->params->emit_stub_syms)
|
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)
|
if (h->root.type == bfd_link_hash_new)
|
||||||
{
|
{
|
||||||
h->root.type = bfd_link_hash_defined;
|
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->root.u.def.value = stub_entry->stub_offset;
|
||||||
h->ref_regular = 1;
|
h->ref_regular = 1;
|
||||||
h->def_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
|
off += (plt->output_offset
|
||||||
+ plt->output_section->vma
|
+ plt->output_section->vma
|
||||||
- elf_gp (plt->output_section->owner)
|
- 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);
|
size = plt_stub_size (htab, stub_entry, off);
|
||||||
if (htab->params->plt_stub_align)
|
if (htab->params->plt_stub_align)
|
||||||
size += plt_stub_pad (htab, stub_entry, off);
|
size += plt_stub_pad (htab, stub_entry, off);
|
||||||
if (info->emitrelocations)
|
if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
stub_entry->stub_sec->reloc_count
|
stub_entry->group->stub_sec->reloc_count
|
||||||
+= ((PPC_HA (off) != 0)
|
+= ((PPC_HA (off) != 0)
|
||||||
+ (htab->opd_abi
|
+ (htab->opd_abi
|
||||||
? 2 + (htab->params->plt_static_chain
|
? 2 + (htab->params->plt_static_chain
|
||||||
&& PPC_HA (off + 16) == PPC_HA (off))
|
&& PPC_HA (off + 16) == PPC_HA (off))
|
||||||
: 1));
|
: 1));
|
||||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -11053,9 +11049,9 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
off = (stub_entry->target_value
|
off = (stub_entry->target_value
|
||||||
+ stub_entry->target_section->output_offset
|
+ stub_entry->target_section->output_offset
|
||||||
+ stub_entry->target_section->output_section->vma);
|
+ stub_entry->target_section->output_section->vma);
|
||||||
off -= (stub_entry->stub_sec->size
|
off -= (stub_entry->group->stub_sec->size
|
||||||
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->group->stub_sec->output_offset
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->group->stub_sec->output_section->vma);
|
||||||
|
|
||||||
/* Reset the stub type from the plt variant in case we now
|
/* Reset the stub type from the plt variant in case we now
|
||||||
can reach with a shorter stub. */
|
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_offset
|
||||||
+ htab->brlt->output_section->vma
|
+ htab->brlt->output_section->vma
|
||||||
- elf_gp (htab->brlt->output_section->owner)
|
- 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)
|
if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
stub_entry->stub_sec->reloc_count += 1 + (PPC_HA (off) != 0);
|
stub_entry->group->stub_sec->reloc_count
|
||||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
+= 1 + (PPC_HA (off) != 0);
|
||||||
|
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
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)
|
else if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
stub_entry->stub_sec->reloc_count += 1;
|
stub_entry->group->stub_sec->reloc_count += 1;
|
||||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stub_entry->stub_sec->size += size;
|
stub_entry->group->stub_sec->size += size;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11162,57 +11159,22 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||||
int
|
int
|
||||||
ppc64_elf_setup_section_lists (struct bfd_link_info *info)
|
ppc64_elf_setup_section_lists (struct bfd_link_info *info)
|
||||||
{
|
{
|
||||||
bfd *input_bfd;
|
unsigned int id;
|
||||||
unsigned int top_id, top_index, id;
|
|
||||||
asection *section;
|
|
||||||
asection **input_list;
|
|
||||||
bfd_size_type amt;
|
bfd_size_type amt;
|
||||||
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
struct ppc_link_hash_table *htab = ppc_hash_table (info);
|
||||||
|
|
||||||
if (htab == NULL)
|
if (htab == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Find the top input section id. */
|
htab->sec_info_arr_size = bfd_get_next_section_id ();
|
||||||
for (input_bfd = info->input_bfds, top_id = 3;
|
amt = sizeof (*htab->sec_info) * (htab->sec_info_arr_size);
|
||||||
input_bfd != NULL;
|
htab->sec_info = bfd_zmalloc (amt);
|
||||||
input_bfd = input_bfd->link.next)
|
if (htab->sec_info == NULL)
|
||||||
{
|
|
||||||
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)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Set toc_off for com, und, abs and ind sections. */
|
/* Set toc_off for com, und, abs and ind sections. */
|
||||||
for (id = 0; id < 3; id++)
|
for (id = 0; id < 3; id++)
|
||||||
htab->stub_group[id].toc_off = TOC_BASE_OFF;
|
htab->sec_info[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;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -11761,15 +11723,13 @@ ppc64_elf_next_input_section (struct bfd_link_info *info, asection *isec)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if ((isec->output_section->flags & SEC_CODE) != 0
|
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,
|
/* This happens to make the list in reverse order,
|
||||||
which is what we want. */
|
which is what we want. */
|
||||||
PREV_SEC (isec) = *list;
|
htab->sec_info[isec->id].u.list
|
||||||
*list = isec;
|
= htab->sec_info[isec->output_section->id].u.list;
|
||||||
|
htab->sec_info[isec->output_section->id].u.list = isec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->multi_toc_needed)
|
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->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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11815,8 +11775,8 @@ check_pasted_section (struct bfd_link_info *info, const char *name)
|
||||||
if (i->has_toc_reloc)
|
if (i->has_toc_reloc)
|
||||||
{
|
{
|
||||||
if (toc_off == 0)
|
if (toc_off == 0)
|
||||||
toc_off = htab->stub_group[i->id].toc_off;
|
toc_off = htab->sec_info[i->id].toc_off;
|
||||||
else if (toc_off != htab->stub_group[i->id].toc_off)
|
else if (toc_off != htab->sec_info[i->id].toc_off)
|
||||||
return FALSE;
|
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)
|
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
||||||
if (i->makes_toc_func_call)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the whole pasted function uses the same toc offset. */
|
/* Make sure the whole pasted function uses the same toc offset. */
|
||||||
if (toc_off != 0)
|
if (toc_off != 0)
|
||||||
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
|
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;
|
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
|
_init and _fini functions into multiple parts. Putting a stub in
|
||||||
the middle of a function is not a good idea. */
|
the middle of a function is not a good idea. */
|
||||||
|
|
||||||
static void
|
static bfd_boolean
|
||||||
group_sections (struct ppc_link_hash_table *htab,
|
group_sections (struct bfd_link_info *info,
|
||||||
bfd_size_type stub_group_size,
|
bfd_size_type stub_group_size,
|
||||||
bfd_boolean stubs_always_before_branch)
|
bfd_boolean stubs_always_before_branch)
|
||||||
{
|
{
|
||||||
asection **list;
|
struct ppc_link_hash_table *htab;
|
||||||
|
asection *osec;
|
||||||
bfd_size_type stub14_group_size;
|
bfd_size_type stub14_group_size;
|
||||||
bfd_boolean suppress_size_errors;
|
bfd_boolean suppress_size_errors;
|
||||||
|
|
||||||
|
htab = ppc_hash_table (info);
|
||||||
|
if (htab == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
suppress_size_errors = FALSE;
|
suppress_size_errors = FALSE;
|
||||||
stub14_group_size = stub_group_size >> 10;
|
stub14_group_size = stub_group_size >> 10;
|
||||||
if (stub_group_size == 1)
|
if (stub_group_size == 1)
|
||||||
|
@ -11877,10 +11842,14 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
suppress_size_errors = TRUE;
|
suppress_size_errors = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = htab->input_list + htab->top_index;
|
for (osec = info->output_bfd->sections; osec != NULL; osec = osec->next)
|
||||||
do
|
|
||||||
{
|
{
|
||||||
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)
|
while (tail != NULL)
|
||||||
{
|
{
|
||||||
asection *curr;
|
asection *curr;
|
||||||
|
@ -11888,6 +11857,7 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
bfd_size_type total;
|
bfd_size_type total;
|
||||||
bfd_boolean big_sec;
|
bfd_boolean big_sec;
|
||||||
bfd_vma curr_toc;
|
bfd_vma curr_toc;
|
||||||
|
struct map_stub *group;
|
||||||
|
|
||||||
curr = tail;
|
curr = tail;
|
||||||
total = tail->size;
|
total = tail->size;
|
||||||
|
@ -11897,14 +11867,14 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
if (big_sec && !suppress_size_errors)
|
if (big_sec && !suppress_size_errors)
|
||||||
(*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
|
(*_bfd_error_handler) (_("%B section %A exceeds stub group size"),
|
||||||
tail->owner, tail);
|
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)
|
&& ((total += curr->output_offset - prev->output_offset)
|
||||||
< (ppc64_elf_section_data (prev) != NULL
|
< (ppc64_elf_section_data (prev) != NULL
|
||||||
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
||||||
? stub14_group_size : stub_group_size))
|
? 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;
|
curr = prev;
|
||||||
|
|
||||||
/* OK, the size from the start of CURR to the end is less
|
/* 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
|
only break if stubs added make the total size more than
|
||||||
2^25, ie. for the default stub_group_size, if stubs total
|
2^25, ie. for the default stub_group_size, if stubs total
|
||||||
more than 2097152 bytes, or nearly 75000 plt call stubs. */
|
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
|
do
|
||||||
{
|
{
|
||||||
prev = PREV_SEC (tail);
|
prev = htab->sec_info[tail->id].u.list;
|
||||||
/* Set up this stub group. */
|
/* 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);
|
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) != NULL
|
||||||
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
&& ppc64_elf_section_data (prev)->has_14bit_branch
|
||||||
? stub14_group_size : stub_group_size))
|
? 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;
|
tail = prev;
|
||||||
prev = PREV_SEC (tail);
|
prev = htab->sec_info[tail->id].u.list;
|
||||||
htab->stub_group[tail->id].link_sec = curr;
|
htab->sec_info[tail->id].u.group = group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tail = prev;
|
tail = prev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (list-- != htab->input_list);
|
return TRUE;
|
||||||
free (htab->input_list);
|
|
||||||
#undef PREV_SEC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char glink_eh_frame_cie[] =
|
static const unsigned char glink_eh_frame_cie[] =
|
||||||
|
@ -12055,7 +12028,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||||
else
|
else
|
||||||
stub_group_size = htab->params->group_size;
|
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)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -12258,8 +12232,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||||
fact a call needing a TOC adjustment. */
|
fact a call needing a TOC adjustment. */
|
||||||
if (code_sec != NULL
|
if (code_sec != NULL
|
||||||
&& code_sec->output_section != NULL
|
&& code_sec->output_section != NULL
|
||||||
&& (htab->stub_group[code_sec->id].toc_off
|
&& (htab->sec_info[code_sec->id].toc_off
|
||||||
!= htab->stub_group[section->id].toc_off)
|
!= htab->sec_info[section->id].toc_off)
|
||||||
&& (code_sec->has_toc_reloc
|
&& (code_sec->has_toc_reloc
|
||||||
|| code_sec->makes_toc_func_call))
|
|| code_sec->makes_toc_func_call))
|
||||||
stub_type = ppc_stub_long_branch_r2off;
|
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;
|
stub_type = ppc_stub_plt_call_r2save;
|
||||||
|
|
||||||
/* Support for grouping stub sections. */
|
/* 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. */
|
/* Get the name of this stub. */
|
||||||
stub_name = ppc_stub_name (id_sec, sym_sec, hash, irela);
|
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)
|
if (h != NULL && &h->elf == htab->elf.hgot)
|
||||||
{
|
{
|
||||||
relocation = (TOCstart
|
relocation = TOCstart + htab->sec_info[input_section->id].toc_off;
|
||||||
+ htab->stub_group[input_section->id].toc_off);
|
|
||||||
sec = bfd_abs_section_ptr;
|
sec = bfd_abs_section_ptr;
|
||||||
unresolved_reloc = FALSE;
|
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
|
/* Munge up the value and addend so that we call the stub
|
||||||
rather than the procedure directly. */
|
rather than the procedure directly. */
|
||||||
relocation = (stub_entry->stub_offset
|
relocation = (stub_entry->stub_offset
|
||||||
+ stub_entry->stub_sec->output_offset
|
+ stub_entry->group->stub_sec->output_offset
|
||||||
+ stub_entry->stub_sec->output_section->vma);
|
+ stub_entry->group->stub_sec->output_section->vma);
|
||||||
addend = 0;
|
addend = 0;
|
||||||
reloc_dest = DEST_STUB;
|
reloc_dest = DEST_STUB;
|
||||||
|
|
||||||
|
@ -14241,7 +14214,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
relocation = got->output_section->vma + got->output_offset + off;
|
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;
|
break;
|
||||||
|
|
||||||
|
@ -14282,11 +14255,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||||
/* Relocation value is TOC base. */
|
/* Relocation value is TOC base. */
|
||||||
relocation = TOCstart;
|
relocation = TOCstart;
|
||||||
if (r_symndx == STN_UNDEF)
|
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 (unresolved_reloc)
|
||||||
;
|
;
|
||||||
else if (sec != NULL && sec->id <= htab->top_id)
|
else if (sec != NULL && sec->id < htab->sec_info_arr_size)
|
||||||
relocation += htab->stub_group[sec->id].toc_off;
|
relocation += htab->sec_info[sec->id].toc_off;
|
||||||
else
|
else
|
||||||
unresolved_reloc = TRUE;
|
unresolved_reloc = TRUE;
|
||||||
goto dodyn;
|
goto dodyn;
|
||||||
|
@ -14301,7 +14274,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||||
case R_PPC64_TOC16_DS:
|
case R_PPC64_TOC16_DS:
|
||||||
case R_PPC64_TOC16_LO_DS:
|
case R_PPC64_TOC16_LO_DS:
|
||||||
case R_PPC64_TOC16_HA:
|
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;
|
break;
|
||||||
|
|
||||||
/* Relocate against the beginning of the section. */
|
/* Relocate against the beginning of the section. */
|
||||||
|
|
|
@ -821,13 +821,13 @@ _bfd_generic_new_section_hook (bfd *abfd, asection *newsect)
|
||||||
return TRUE;
|
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. */
|
/* Initializes a new section. NEWSECT->NAME is already set. */
|
||||||
|
|
||||||
static asection *
|
static asection *
|
||||||
bfd_section_init (bfd *abfd, asection *newsect)
|
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->id = section_id;
|
||||||
newsect->index = abfd->section_count;
|
newsect->index = abfd->section_count;
|
||||||
newsect->owner = abfd;
|
newsect->owner = abfd;
|
||||||
|
@ -1273,6 +1273,23 @@ bfd_make_section (bfd *abfd, const char *name)
|
||||||
return bfd_make_section_with_flags (abfd, name, 0);
|
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
|
FUNCTION
|
||||||
bfd_set_section_flags
|
bfd_set_section_flags
|
||||||
|
|
Loading…
Reference in a new issue