* elf64-ppc.c (enum _ppc64_sec_type): New.
(struct _ppc64_elf_section_data): Move "t_symndx" into opd union, and rename fields. Add sec_type and has_14bit_branch. (struct ppc_link_hash_table): Remove has_14bit_branch. (get_opd_info, get_tls_mask, ppc64_elf_edit_opd): Adjust. (ppc64_elf_relocate_section): Likewise. (ppc64_elf_check_relocs): Likewise. Set per-section has_14bit_branch. (ppc64_elf_size_stubs): Don't set default group size here. (group_sections): Instead do so here, and group sections using their individual requirements.
This commit is contained in:
parent
b3fac117e3
commit
7c8fe5c480
|
@ -1,3 +1,16 @@
|
||||||
|
2006-11-07 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (enum _ppc64_sec_type): New.
|
||||||
|
(struct _ppc64_elf_section_data): Move "t_symndx" into opd union,
|
||||||
|
and rename fields. Add sec_type and has_14bit_branch.
|
||||||
|
(struct ppc_link_hash_table): Remove has_14bit_branch.
|
||||||
|
(get_opd_info, get_tls_mask, ppc64_elf_edit_opd): Adjust.
|
||||||
|
(ppc64_elf_relocate_section): Likewise.
|
||||||
|
(ppc64_elf_check_relocs): Likewise. Set per-section has_14bit_branch.
|
||||||
|
(ppc64_elf_size_stubs): Don't set default group size here.
|
||||||
|
(group_sections): Instead do so here, and group sections using
|
||||||
|
their individual requirements.
|
||||||
|
|
||||||
2006-11-07 Alan Modra <amodra@bigpond.net.au>
|
2006-11-07 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
* elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
|
* elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
|
||||||
|
|
117
bfd/elf64-ppc.c
117
bfd/elf64-ppc.c
|
@ -2525,6 +2525,12 @@ static const struct bfd_elf_special_section ppc64_elf_special_sections[]=
|
||||||
{ NULL, 0, 0, 0, 0 }
|
{ NULL, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum _ppc64_sec_type {
|
||||||
|
sec_normal = 0,
|
||||||
|
sec_opd = 1,
|
||||||
|
sec_toc = 2
|
||||||
|
};
|
||||||
|
|
||||||
struct _ppc64_elf_section_data
|
struct _ppc64_elf_section_data
|
||||||
{
|
{
|
||||||
struct bfd_elf_section_data elf;
|
struct bfd_elf_section_data elf;
|
||||||
|
@ -2533,14 +2539,20 @@ struct _ppc64_elf_section_data
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
/* Points to the function code section for local opd entries. */
|
/* Points to the function code section for local opd entries. */
|
||||||
asection **func_sec;
|
asection **opd_func_sec;
|
||||||
/* After editing .opd, adjust references to opd local syms. */
|
/* After editing .opd, adjust references to opd local syms. */
|
||||||
long *adjust;
|
long *opd_adjust;
|
||||||
} opd;
|
|
||||||
|
|
||||||
/* An array for toc sections, indexed by offset/8.
|
/* An array for toc sections, indexed by offset/8.
|
||||||
Specifies the relocation symbol index used at a given toc offset. */
|
Specifies the relocation symbol index used at a given toc offset. */
|
||||||
unsigned *t_symndx;
|
unsigned *t_symndx;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
enum _ppc64_sec_type sec_type:2;
|
||||||
|
|
||||||
|
/* Flag set when small branches are detected. Used to
|
||||||
|
select suitable defaults for the stub group size. */
|
||||||
|
unsigned int has_14bit_branch:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ppc64_elf_section_data(sec) \
|
#define ppc64_elf_section_data(sec) \
|
||||||
|
@ -2568,8 +2580,8 @@ get_opd_info (asection * sec)
|
||||||
{
|
{
|
||||||
if (sec != NULL
|
if (sec != NULL
|
||||||
&& ppc64_elf_section_data (sec) != NULL
|
&& ppc64_elf_section_data (sec) != NULL
|
||||||
&& ppc64_elf_section_data (sec)->opd.adjust != NULL)
|
&& ppc64_elf_section_data (sec)->sec_type == sec_opd)
|
||||||
return ppc64_elf_section_data (sec)->opd.adjust;
|
return ppc64_elf_section_data (sec)->u.opd_adjust;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3358,10 +3370,6 @@ struct ppc_link_hash_table
|
||||||
/* Set on error. */
|
/* Set on error. */
|
||||||
unsigned int stub_error:1;
|
unsigned int stub_error:1;
|
||||||
|
|
||||||
/* Flag set when small branches are detected. Used to
|
|
||||||
select suitable defaults for the stub group size. */
|
|
||||||
unsigned int has_14bit_branch:1;
|
|
||||||
|
|
||||||
/* Temp used by ppc64_elf_check_directives. */
|
/* Temp used by ppc64_elf_check_directives. */
|
||||||
unsigned int twiddled_syms:1;
|
unsigned int twiddled_syms:1;
|
||||||
|
|
||||||
|
@ -4373,7 +4381,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||||
opd_sym_map = bfd_zalloc (abfd, amt);
|
opd_sym_map = bfd_zalloc (abfd, amt);
|
||||||
if (opd_sym_map == NULL)
|
if (opd_sym_map == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ppc64_elf_section_data (sec)->opd.func_sec = opd_sym_map;
|
ppc64_elf_section_data (sec)->u.opd_func_sec = opd_sym_map;
|
||||||
|
BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
|
||||||
|
ppc64_elf_section_data (sec)->sec_type = sec_opd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->sfpr == NULL
|
if (htab->sfpr == NULL
|
||||||
|
@ -4387,6 +4397,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
enum elf_ppc64_reloc_type r_type;
|
enum elf_ppc64_reloc_type r_type;
|
||||||
int tls_type = 0;
|
int tls_type = 0;
|
||||||
|
struct _ppc64_elf_section_data *ppc64_sec;
|
||||||
|
|
||||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
|
@ -4568,7 +4579,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||||
dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
|
dest = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
|
||||||
sec, r_symndx);
|
sec, r_symndx);
|
||||||
if (dest != sec)
|
if (dest != sec)
|
||||||
htab->has_14bit_branch = 1;
|
ppc64_elf_section_data (sec)->has_14bit_branch = 1;
|
||||||
}
|
}
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
|
@ -4639,23 +4650,26 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||||
rel->r_addend, tls_type))
|
rel->r_addend, tls_type))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (ppc64_elf_section_data (sec)->t_symndx == NULL)
|
ppc64_sec = ppc64_elf_section_data (sec);
|
||||||
|
if (ppc64_sec->sec_type != sec_toc)
|
||||||
{
|
{
|
||||||
/* One extra to simplify get_tls_mask. */
|
/* One extra to simplify get_tls_mask. */
|
||||||
bfd_size_type amt = sec->size * sizeof (unsigned) / 8 + 1;
|
bfd_size_type amt = sec->size * sizeof (unsigned) / 8 + 1;
|
||||||
ppc64_elf_section_data (sec)->t_symndx = bfd_zalloc (abfd, amt);
|
ppc64_sec->u.t_symndx = bfd_zalloc (abfd, amt);
|
||||||
if (ppc64_elf_section_data (sec)->t_symndx == NULL)
|
if (ppc64_sec->u.t_symndx == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
BFD_ASSERT (ppc64_sec->sec_type == sec_normal);
|
||||||
|
ppc64_sec->sec_type = sec_toc;
|
||||||
}
|
}
|
||||||
BFD_ASSERT (rel->r_offset % 8 == 0);
|
BFD_ASSERT (rel->r_offset % 8 == 0);
|
||||||
ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8] = r_symndx;
|
ppc64_sec->u.t_symndx[rel->r_offset / 8] = r_symndx;
|
||||||
|
|
||||||
/* Mark the second slot of a GD or LD entry.
|
/* Mark the second slot of a GD or LD entry.
|
||||||
-1 to indicate GD and -2 to indicate LD. */
|
-1 to indicate GD and -2 to indicate LD. */
|
||||||
if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD))
|
if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD))
|
||||||
ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -1;
|
ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -1;
|
||||||
else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD))
|
else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD))
|
||||||
ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -2;
|
ppc64_sec->u.t_symndx[rel->r_offset / 8 + 1] = -2;
|
||||||
goto dodyn;
|
goto dodyn;
|
||||||
|
|
||||||
case R_PPC64_TPREL16:
|
case R_PPC64_TPREL16:
|
||||||
|
@ -6051,7 +6065,7 @@ get_tls_mask (char **tls_maskp, unsigned long *toc_symndx,
|
||||||
|
|
||||||
if ((*tls_maskp != NULL && **tls_maskp != 0)
|
if ((*tls_maskp != NULL && **tls_maskp != 0)
|
||||||
|| sec == NULL
|
|| sec == NULL
|
||||||
|| ppc64_elf_section_data (sec)->t_symndx == NULL)
|
|| ppc64_elf_section_data (sec)->sec_type != sec_toc)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Look inside a TOC section too. */
|
/* Look inside a TOC section too. */
|
||||||
|
@ -6064,8 +6078,8 @@ get_tls_mask (char **tls_maskp, unsigned long *toc_symndx,
|
||||||
off = sym->st_value;
|
off = sym->st_value;
|
||||||
off += rel->r_addend;
|
off += rel->r_addend;
|
||||||
BFD_ASSERT (off % 8 == 0);
|
BFD_ASSERT (off % 8 == 0);
|
||||||
r_symndx = ppc64_elf_section_data (sec)->t_symndx[off / 8];
|
r_symndx = ppc64_elf_section_data (sec)->u.t_symndx[off / 8];
|
||||||
next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1];
|
next_r = ppc64_elf_section_data (sec)->u.t_symndx[off / 8 + 1];
|
||||||
if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
|
if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd))
|
||||||
return 0;
|
return 0;
|
||||||
if (toc_symndx != NULL)
|
if (toc_symndx != NULL)
|
||||||
|
@ -6306,7 +6320,9 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info,
|
||||||
opd_adjust = bfd_alloc (obfd, amt);
|
opd_adjust = bfd_alloc (obfd, amt);
|
||||||
if (opd_adjust == NULL)
|
if (opd_adjust == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ppc64_elf_section_data (sec)->opd.adjust = opd_adjust;
|
ppc64_elf_section_data (sec)->u.opd_adjust = opd_adjust;
|
||||||
|
BFD_ASSERT (ppc64_elf_section_data (sec)->sec_type == sec_normal);
|
||||||
|
ppc64_elf_section_data (sec)->sec_type = sec_opd;
|
||||||
}
|
}
|
||||||
memset (opd_adjust, 0, amt);
|
memset (opd_adjust, 0, amt);
|
||||||
|
|
||||||
|
@ -8940,7 +8956,29 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
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 = htab->input_list + htab->top_index;
|
asection **list;
|
||||||
|
bfd_size_type stub14_group_size;
|
||||||
|
bfd_boolean suppress_size_errors;
|
||||||
|
|
||||||
|
suppress_size_errors = FALSE;
|
||||||
|
stub14_group_size = stub_group_size;
|
||||||
|
if (stub_group_size == 1)
|
||||||
|
{
|
||||||
|
/* Default values. */
|
||||||
|
if (stubs_always_before_branch)
|
||||||
|
{
|
||||||
|
stub_group_size = 0x1e00000;
|
||||||
|
stub14_group_size = 0x7800;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stub_group_size = 0x1c00000;
|
||||||
|
stub14_group_size = 0x7000;
|
||||||
|
}
|
||||||
|
suppress_size_errors = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = htab->input_list + htab->top_index;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
asection *tail = *list;
|
asection *tail = *list;
|
||||||
|
@ -8954,15 +8992,17 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
|
|
||||||
curr = tail;
|
curr = tail;
|
||||||
total = tail->size;
|
total = tail->size;
|
||||||
big_sec = total > stub_group_size;
|
big_sec = total > (ppc64_elf_section_data (tail)->has_14bit_branch
|
||||||
if (big_sec)
|
? stub14_group_size : stub_group_size);
|
||||||
|
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->stub_group[tail->id].toc_off;
|
||||||
|
|
||||||
while ((prev = PREV_SEC (curr)) != NULL
|
while ((prev = PREV_SEC (curr)) != NULL
|
||||||
&& ((total += curr->output_offset - prev->output_offset)
|
&& ((total += curr->output_offset - prev->output_offset)
|
||||||
< stub_group_size)
|
< (ppc64_elf_section_data (prev)->has_14bit_branch
|
||||||
|
? stub14_group_size : stub_group_size))
|
||||||
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
||||||
curr = prev;
|
curr = prev;
|
||||||
|
|
||||||
|
@ -8994,7 +9034,8 @@ group_sections (struct ppc_link_hash_table *htab,
|
||||||
total = 0;
|
total = 0;
|
||||||
while (prev != NULL
|
while (prev != NULL
|
||||||
&& ((total += tail->output_offset - prev->output_offset)
|
&& ((total += tail->output_offset - prev->output_offset)
|
||||||
< stub_group_size)
|
< (ppc64_elf_section_data (prev)->has_14bit_branch
|
||||||
|
? stub14_group_size : stub_group_size))
|
||||||
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
&& htab->stub_group[prev->id].toc_off == curr_toc)
|
||||||
{
|
{
|
||||||
tail = prev;
|
tail = prev;
|
||||||
|
@ -9035,22 +9076,6 @@ ppc64_elf_size_stubs (bfd *output_bfd,
|
||||||
stub_group_size = -group_size;
|
stub_group_size = -group_size;
|
||||||
else
|
else
|
||||||
stub_group_size = group_size;
|
stub_group_size = group_size;
|
||||||
if (stub_group_size == 1)
|
|
||||||
{
|
|
||||||
/* Default values. */
|
|
||||||
if (stubs_always_before_branch)
|
|
||||||
{
|
|
||||||
stub_group_size = 0x1e00000;
|
|
||||||
if (htab->has_14bit_branch)
|
|
||||||
stub_group_size = 0x7800;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stub_group_size = 0x1c00000;
|
|
||||||
if (htab->has_14bit_branch)
|
|
||||||
stub_group_size = 0x7000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group_sections (htab, stub_group_size, stubs_always_before_branch);
|
group_sections (htab, stub_group_size, stubs_always_before_branch);
|
||||||
|
|
||||||
|
@ -9721,7 +9746,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||||
TOCstart = elf_gp (output_bfd);
|
TOCstart = elf_gp (output_bfd);
|
||||||
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
|
||||||
sym_hashes = elf_sym_hashes (input_bfd);
|
sym_hashes = elf_sym_hashes (input_bfd);
|
||||||
is_opd = ppc64_elf_section_data (input_section)->opd.adjust != NULL;
|
is_opd = ppc64_elf_section_data (input_section)->sec_type == sec_opd;
|
||||||
|
|
||||||
rel = relocs;
|
rel = relocs;
|
||||||
relend = relocs + input_section->reloc_count;
|
relend = relocs + input_section->reloc_count;
|
||||||
|
|
Loading…
Reference in New Issue