Inline PLT call optimization
This patch adds the analysis part of PLT call optimization, enabling the code added with the previous patch that actually performs the optimization. Gold support is not available yet. bfd/ * elf64-ppc.c (struct _ppc64_elf_section_data): Add has_pltcall field. (struct ppc_link_hash_table): Add can_convert_all_inline_plt. (ppc64_elf_check_relocs): Set has_pltcall. (ppc64_elf_adjust_dynamic_symbol): Discard some PLT entries. (ppc64_elf_inline_plt): New function. (ppc64_elf_size_dynamic_sections): Discard some PLT entries for locals. * elf64-ppc.h (ppc64_elf_inline_plt): Declare. * elf32-ppc.c (has_pltcall): Define. (struct ppc_elf_link_hash_table): Add can_convert_all_inline_plt. (ppc_elf_check_relocs): Set has_pltcall. (ppc_elf_inline_plt): New function. (ppc_elf_adjust_dynamic_symbol): Discard some PLT entries. (ppc_elf_size_dynamic_sections): Likewise. * elf32-ppc.h (ppc_elf_inline_plt): Declare. ld/ * emultempl/ppc64elf.em (no_inline_plt): New var. (ppc_before_allocation): Call ppc64_elf_inline_plt. (enum ppc64_opt): Add OPTION_NO_INLINE_OPT. (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Handle --no-inline-optimize. * emultemps/ppc32elf.em (no_inline_opt): New var. (prelim_size_sections): New function, extracted from.. (ppc_before_allocation): ..here. Call ppc_elf_inline_plt. (enum ppc32_opt): Add OPTION_NO_INLINE_OPT. (PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS, PARSE_AND_LIST_ARGS_CASES): Handle --no-inline-optimize.
This commit is contained in:
parent
23cedd1dc9
commit
3e04d7655b
|
@ -1,3 +1,20 @@
|
|||
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (struct _ppc64_elf_section_data): Add has_pltcall field.
|
||||
(struct ppc_link_hash_table): Add can_convert_all_inline_plt.
|
||||
(ppc64_elf_check_relocs): Set has_pltcall.
|
||||
(ppc64_elf_adjust_dynamic_symbol): Discard some PLT entries.
|
||||
(ppc64_elf_inline_plt): New function.
|
||||
(ppc64_elf_size_dynamic_sections): Discard some PLT entries for locals.
|
||||
* elf64-ppc.h (ppc64_elf_inline_plt): Declare.
|
||||
* elf32-ppc.c (has_pltcall): Define.
|
||||
(struct ppc_elf_link_hash_table): Add can_convert_all_inline_plt.
|
||||
(ppc_elf_check_relocs): Set has_pltcall.
|
||||
(ppc_elf_inline_plt): New function.
|
||||
(ppc_elf_adjust_dynamic_symbol): Discard some PLT entries.
|
||||
(ppc_elf_size_dynamic_sections): Likewise.
|
||||
* elf32-ppc.h (ppc_elf_inline_plt): Declare.
|
||||
|
||||
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_howto_raw): Add PLTSEQ and PLTCALL howtos.
|
||||
|
|
156
bfd/elf32-ppc.c
156
bfd/elf32-ppc.c
|
@ -3347,6 +3347,9 @@ struct ppc_elf_link_hash_table
|
|||
/* Set if tls optimization is enabled. */
|
||||
unsigned int do_tls_opt:1;
|
||||
|
||||
/* Set if inline plt calls should be converted to direct calls. */
|
||||
unsigned int can_convert_all_inline_plt:1;
|
||||
|
||||
/* The size of PLT entries. */
|
||||
int plt_entry_size;
|
||||
/* The distance between adjacent PLT slots. */
|
||||
|
@ -3367,6 +3370,9 @@ struct ppc_elf_link_hash_table
|
|||
/* Nonzero if this section has a call to __tls_get_addr. */
|
||||
#define has_tls_get_addr_call sec_flg1
|
||||
|
||||
/* Flag set when PLTCALL relocs are detected. */
|
||||
#define has_pltcall sec_flg2
|
||||
|
||||
/* Get the PPC ELF linker hash table from a link_info structure. */
|
||||
|
||||
#define ppc_elf_hash_table(p) \
|
||||
|
@ -4351,14 +4357,18 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
if (h == NULL)
|
||||
break;
|
||||
ppc_elf_tdata (abfd)->makes_plt_call = 1;
|
||||
/* Fall through */
|
||||
goto pltentry;
|
||||
|
||||
case R_PPC_PLTCALL:
|
||||
sec->has_pltcall = 1;
|
||||
/* Fall through. */
|
||||
|
||||
case R_PPC_PLT32:
|
||||
case R_PPC_PLTREL32:
|
||||
case R_PPC_PLT16_LO:
|
||||
case R_PPC_PLT16_HI:
|
||||
case R_PPC_PLT16_HA:
|
||||
pltentry:
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Reloc requires a PLT entry\n");
|
||||
#endif
|
||||
|
@ -5236,6 +5246,141 @@ get_sym_h (struct elf_link_hash_entry **hp,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Analyze inline PLT call relocations to see whether calls to locally
|
||||
defined functions can be converted to direct calls. */
|
||||
|
||||
bfd_boolean
|
||||
ppc_elf_inline_plt (struct bfd_link_info *info)
|
||||
{
|
||||
struct ppc_elf_link_hash_table *htab;
|
||||
bfd *ibfd;
|
||||
asection *sec;
|
||||
bfd_vma low_vma, high_vma, limit;
|
||||
|
||||
htab = ppc_elf_hash_table (info);
|
||||
if (htab == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* A bl insn can reach -0x2000000 to 0x1fffffc. The limit is
|
||||
reduced somewhat to cater for possible stubs that might be added
|
||||
between the call and its destination. */
|
||||
limit = 0x1e00000;
|
||||
low_vma = -1;
|
||||
high_vma = 0;
|
||||
for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
|
||||
if ((sec->flags & (SEC_ALLOC | SEC_CODE)) == (SEC_ALLOC | SEC_CODE))
|
||||
{
|
||||
if (low_vma > sec->vma)
|
||||
low_vma = sec->vma;
|
||||
if (high_vma < sec->vma + sec->size)
|
||||
high_vma = sec->vma + sec->size;
|
||||
}
|
||||
|
||||
/* If a "bl" can reach anywhere in local code sections, then we can
|
||||
convert all inline PLT sequences to direct calls when the symbol
|
||||
is local. */
|
||||
if (high_vma - low_vma < limit)
|
||||
{
|
||||
htab->can_convert_all_inline_plt = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Otherwise, go looking through relocs for cases where a direct
|
||||
call won't reach. Mark the symbol on any such reloc to disable
|
||||
the optimization and keep the PLT entry as it seems likely that
|
||||
this will be better than creating trampolines. Note that this
|
||||
will disable the optimization for all inline PLT calls to a
|
||||
particular symbol, not just those that won't reach. The
|
||||
difficulty in doing a more precise optimization is that the
|
||||
linker needs to make a decision depending on whether a
|
||||
particular R_PPC_PLTCALL insn can be turned into a direct
|
||||
call, for each of the R_PPC_PLTSEQ and R_PPC_PLT16* insns in
|
||||
the sequence, and there is nothing that ties those relocs
|
||||
together except their symbol. */
|
||||
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
Elf_Internal_Sym *local_syms;
|
||||
|
||||
if (!is_ppc_elf (ibfd))
|
||||
continue;
|
||||
|
||||
local_syms = NULL;
|
||||
symtab_hdr = &elf_symtab_hdr (ibfd);
|
||||
|
||||
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
|
||||
if (sec->has_pltcall
|
||||
&& !bfd_is_abs_section (sec->output_section))
|
||||
{
|
||||
Elf_Internal_Rela *relstart, *rel, *relend;
|
||||
|
||||
/* Read the relocations. */
|
||||
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (relstart == NULL)
|
||||
return FALSE;
|
||||
|
||||
relend = relstart + sec->reloc_count;
|
||||
for (rel = relstart; rel < relend; )
|
||||
{
|
||||
enum elf_ppc_reloc_type r_type;
|
||||
unsigned long r_symndx;
|
||||
asection *sym_sec;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *sym;
|
||||
unsigned char *tls_maskp;
|
||||
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
if (r_type != R_PPC_PLTCALL)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (!get_sym_h (&h, &sym, &sym_sec, &tls_maskp, &local_syms,
|
||||
r_symndx, ibfd))
|
||||
{
|
||||
if (elf_section_data (sec)->relocs != relstart)
|
||||
free (relstart);
|
||||
if (local_syms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
||||
free (local_syms);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
||||
{
|
||||
bfd_vma from, to;
|
||||
if (h != NULL)
|
||||
to = h->root.u.def.value;
|
||||
else
|
||||
to = sym->st_value;
|
||||
to += (rel->r_addend
|
||||
+ sym_sec->output_offset
|
||||
+ sym_sec->output_section->vma);
|
||||
from = (rel->r_offset
|
||||
+ sec->output_offset
|
||||
+ sec->output_section->vma);
|
||||
if (to - from + limit < 2 * limit)
|
||||
*tls_maskp &= ~PLT_KEEP;
|
||||
}
|
||||
}
|
||||
if (elf_section_data (sec)->relocs != relstart)
|
||||
free (relstart);
|
||||
}
|
||||
|
||||
if (local_syms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
||||
{
|
||||
if (!info->keep_memory)
|
||||
free (local_syms);
|
||||
else
|
||||
symtab_hdr->contents = (unsigned char *) local_syms;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set plt output section type, htab->tls_get_addr, and call the
|
||||
generic ELF tls_setup function. */
|
||||
|
||||
|
@ -5716,8 +5861,9 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
if (ent == NULL
|
||||
|| (h->type != STT_GNU_IFUNC
|
||||
&& local
|
||||
&& ((ppc_elf_hash_entry (h)->tls_mask & (TLS_TLS | PLT_KEEP))
|
||||
!= PLT_KEEP)))
|
||||
&& (htab->can_convert_all_inline_plt
|
||||
|| (ppc_elf_hash_entry (h)->tls_mask
|
||||
& (TLS_TLS | PLT_KEEP)) != PLT_KEEP)))
|
||||
{
|
||||
/* A PLT entry is not required/allowed when:
|
||||
|
||||
|
@ -6216,6 +6362,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
|| (h->needs_plt
|
||||
&& h->def_regular
|
||||
&& !htab->elf.dynamic_sections_created
|
||||
&& !htab->can_convert_all_inline_plt
|
||||
&& (ppc_elf_hash_entry (h)->tls_mask
|
||||
& (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
|
||||
{
|
||||
|
@ -6570,7 +6717,8 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
{
|
||||
if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
|
||||
s = htab->elf.iplt;
|
||||
else if ((*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||
else if (htab->can_convert_all_inline_plt
|
||||
|| (*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||
{
|
||||
ent->plt.offset = (bfd_vma) -1;
|
||||
continue;
|
||||
|
|
|
@ -60,6 +60,7 @@ struct ppc_elf_params
|
|||
|
||||
void ppc_elf_link_params (struct bfd_link_info *, struct ppc_elf_params *);
|
||||
int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *);
|
||||
bfd_boolean ppc_elf_inline_plt (struct bfd_link_info *);
|
||||
asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
|
||||
bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
|
||||
void ppc_elf_maybe_strip_sdata_syms (struct bfd_link_info *);
|
||||
|
|
168
bfd/elf64-ppc.c
168
bfd/elf64-ppc.c
|
@ -3123,6 +3123,9 @@ struct _ppc64_elf_section_data
|
|||
/* Flag set when small branches are detected. Used to
|
||||
select suitable defaults for the stub group size. */
|
||||
unsigned int has_14bit_branch:1;
|
||||
|
||||
/* Flag set when PLTCALL relocs are detected. */
|
||||
unsigned int has_pltcall:1;
|
||||
};
|
||||
|
||||
#define ppc64_elf_section_data(sec) \
|
||||
|
@ -4191,6 +4194,9 @@ struct ppc_link_hash_table
|
|||
/* Set if tls optimization is enabled. */
|
||||
unsigned int do_tls_opt:1;
|
||||
|
||||
/* Set if inline plt calls should be converted to direct calls. */
|
||||
unsigned int can_convert_all_inline_plt:1;
|
||||
|
||||
/* Set on error. */
|
||||
unsigned int stub_error:1;
|
||||
|
||||
|
@ -5818,10 +5824,14 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
if (dest != sec)
|
||||
ppc64_elf_section_data (sec)->has_14bit_branch = 1;
|
||||
}
|
||||
goto rel24;
|
||||
|
||||
case R_PPC64_PLTCALL:
|
||||
ppc64_elf_section_data (sec)->has_pltcall = 1;
|
||||
/* Fall through. */
|
||||
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_PLTCALL:
|
||||
rel24:
|
||||
plt_list = ifunc;
|
||||
if (h != NULL)
|
||||
{
|
||||
|
@ -7261,8 +7271,9 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
if (ent == NULL
|
||||
|| (h->type != STT_GNU_IFUNC
|
||||
&& local
|
||||
&& (((struct ppc_link_hash_entry *) h)->tls_mask
|
||||
& (TLS_TLS | PLT_KEEP)) != PLT_KEEP))
|
||||
&& (htab->can_convert_all_inline_plt
|
||||
|| (((struct ppc_link_hash_entry *) h)->tls_mask
|
||||
& (TLS_TLS | PLT_KEEP)) != PLT_KEEP)))
|
||||
{
|
||||
h->plt.plist = NULL;
|
||||
h->needs_plt = 0;
|
||||
|
@ -8276,6 +8287,153 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Analyze inline PLT call relocations to see whether calls to locally
|
||||
defined functions can be converted to direct calls. */
|
||||
|
||||
bfd_boolean
|
||||
ppc64_elf_inline_plt (struct bfd_link_info *info)
|
||||
{
|
||||
struct ppc_link_hash_table *htab;
|
||||
bfd *ibfd;
|
||||
asection *sec;
|
||||
bfd_vma low_vma, high_vma, limit;
|
||||
|
||||
htab = ppc_hash_table (info);
|
||||
if (htab == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* A bl insn can reach -0x2000000 to 0x1fffffc. The limit is
|
||||
reduced somewhat to cater for possible stubs that might be added
|
||||
between the call and its destination. */
|
||||
if (htab->params->group_size < 0)
|
||||
{
|
||||
limit = -htab->params->group_size;
|
||||
if (limit == 1)
|
||||
limit = 0x1e00000;
|
||||
}
|
||||
else
|
||||
{
|
||||
limit = htab->params->group_size;
|
||||
if (limit == 1)
|
||||
limit = 0x1c00000;
|
||||
}
|
||||
|
||||
low_vma = -1;
|
||||
high_vma = 0;
|
||||
for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
|
||||
if ((sec->flags & (SEC_ALLOC | SEC_CODE)) == (SEC_ALLOC | SEC_CODE))
|
||||
{
|
||||
if (low_vma > sec->vma)
|
||||
low_vma = sec->vma;
|
||||
if (high_vma < sec->vma + sec->size)
|
||||
high_vma = sec->vma + sec->size;
|
||||
}
|
||||
|
||||
/* If a "bl" can reach anywhere in local code sections, then we can
|
||||
convert all inline PLT sequences to direct calls when the symbol
|
||||
is local. */
|
||||
if (high_vma - low_vma < limit)
|
||||
{
|
||||
htab->can_convert_all_inline_plt = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Otherwise, go looking through relocs for cases where a direct
|
||||
call won't reach. Mark the symbol on any such reloc to disable
|
||||
the optimization and keep the PLT entry as it seems likely that
|
||||
this will be better than creating trampolines. Note that this
|
||||
will disable the optimization for all inline PLT calls to a
|
||||
particular symbol, not just those that won't reach. The
|
||||
difficulty in doing a more precise optimization is that the
|
||||
linker needs to make a decision depending on whether a
|
||||
particular R_PPC64_PLTCALL insn can be turned into a direct
|
||||
call, for each of the R_PPC64_PLTSEQ and R_PPC64_PLT16* insns in
|
||||
the sequence, and there is nothing that ties those relocs
|
||||
together except their symbol. */
|
||||
|
||||
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
Elf_Internal_Sym *local_syms;
|
||||
|
||||
if (!is_ppc64_elf (ibfd))
|
||||
continue;
|
||||
|
||||
local_syms = NULL;
|
||||
symtab_hdr = &elf_symtab_hdr (ibfd);
|
||||
|
||||
for (sec = ibfd->sections; sec != NULL; sec = sec->next)
|
||||
if (ppc64_elf_section_data (sec)->has_pltcall
|
||||
&& !bfd_is_abs_section (sec->output_section))
|
||||
{
|
||||
Elf_Internal_Rela *relstart, *rel, *relend;
|
||||
|
||||
/* Read the relocations. */
|
||||
relstart = _bfd_elf_link_read_relocs (ibfd, sec, NULL, NULL,
|
||||
info->keep_memory);
|
||||
if (relstart == NULL)
|
||||
return FALSE;
|
||||
|
||||
relend = relstart + sec->reloc_count;
|
||||
for (rel = relstart; rel < relend; )
|
||||
{
|
||||
enum elf_ppc64_reloc_type r_type;
|
||||
unsigned long r_symndx;
|
||||
asection *sym_sec;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *sym;
|
||||
unsigned char *tls_maskp;
|
||||
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
if (r_type != R_PPC64_PLTCALL)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF64_R_SYM (rel->r_info);
|
||||
if (!get_sym_h (&h, &sym, &sym_sec, &tls_maskp, &local_syms,
|
||||
r_symndx, ibfd))
|
||||
{
|
||||
if (elf_section_data (sec)->relocs != relstart)
|
||||
free (relstart);
|
||||
if (local_syms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
||||
free (local_syms);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
||||
{
|
||||
bfd_vma from, to;
|
||||
if (h != NULL)
|
||||
to = h->root.u.def.value;
|
||||
else
|
||||
to = sym->st_value;
|
||||
to += (rel->r_addend
|
||||
+ sym_sec->output_offset
|
||||
+ sym_sec->output_section->vma);
|
||||
from = (rel->r_offset
|
||||
+ sec->output_offset
|
||||
+ sec->output_section->vma);
|
||||
if (to - from + limit < 2 * limit)
|
||||
*tls_maskp &= ~PLT_KEEP;
|
||||
}
|
||||
}
|
||||
if (elf_section_data (sec)->relocs != relstart)
|
||||
free (relstart);
|
||||
}
|
||||
|
||||
if (local_syms != NULL
|
||||
&& symtab_hdr->contents != (unsigned char *) local_syms)
|
||||
{
|
||||
if (!info->keep_memory)
|
||||
free (local_syms);
|
||||
else
|
||||
symtab_hdr->contents = (unsigned char *) local_syms;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */
|
||||
|
||||
asection *
|
||||
|
@ -9913,6 +10071,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
|| (h->needs_plt
|
||||
&& h->def_regular
|
||||
&& !htab->elf.dynamic_sections_created
|
||||
&& !htab->can_convert_all_inline_plt
|
||||
&& (((struct ppc_link_hash_entry *) h)->tls_mask
|
||||
& (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
|
||||
{
|
||||
|
@ -10241,7 +10400,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||
s->size += PLT_ENTRY_SIZE (htab);
|
||||
htab->elf.irelplt->size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
else if ((*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||
else if (htab->can_convert_all_inline_plt
|
||||
|| (*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||
ent->plt.offset = (bfd_vma) -1;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -69,6 +69,8 @@ bfd_boolean ppc64_elf_init_stub_bfd
|
|||
(struct bfd_link_info *, struct ppc64_elf_params *);
|
||||
bfd_boolean ppc64_elf_edit_opd
|
||||
(struct bfd_link_info *);
|
||||
bfd_boolean ppc64_elf_inline_plt
|
||||
(struct bfd_link_info *);
|
||||
asection *ppc64_elf_tls_setup
|
||||
(struct bfd_link_info *);
|
||||
bfd_boolean ppc64_elf_tls_optimize
|
||||
|
|
14
ld/ChangeLog
14
ld/ChangeLog
|
@ -1,3 +1,17 @@
|
|||
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* emultempl/ppc64elf.em (no_inline_plt): New var.
|
||||
(ppc_before_allocation): Call ppc64_elf_inline_plt.
|
||||
(enum ppc64_opt): Add OPTION_NO_INLINE_OPT.
|
||||
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS,
|
||||
PARSE_AND_LIST_ARGS_CASES): Handle --no-inline-optimize.
|
||||
* emultemps/ppc32elf.em (no_inline_opt): New var.
|
||||
(prelim_size_sections): New function, extracted from..
|
||||
(ppc_before_allocation): ..here. Call ppc_elf_inline_plt.
|
||||
(enum ppc32_opt): Add OPTION_NO_INLINE_OPT.
|
||||
(PARSE_AND_LIST_LONGOPTS, PARSE_AND_LIST_OPTIONS,
|
||||
PARSE_AND_LIST_ARGS_CASES): Handle --no-inline-optimize.
|
||||
|
||||
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* emulparams/elf32ppc.sh (OTHER_RELRO_SECTIONS_2): Add .branch_lt.
|
||||
|
|
|
@ -35,6 +35,9 @@ fragment <<EOF
|
|||
/* Whether to run tls optimization. */
|
||||
static int notlsopt = 0;
|
||||
|
||||
/* Whether to convert inline PLT calls to direct. */
|
||||
static int no_inline_opt = 0;
|
||||
|
||||
/* Choose the correct place for .got. */
|
||||
static int old_got = 0;
|
||||
|
||||
|
@ -115,11 +118,33 @@ ppc_after_check_relocs (void)
|
|||
EOF
|
||||
fi
|
||||
fragment <<EOF
|
||||
static void
|
||||
prelim_size_sections (void)
|
||||
{
|
||||
if (expld.phase != lang_mark_phase_enum)
|
||||
{
|
||||
expld.phase = lang_mark_phase_enum;
|
||||
expld.dataseg.phase = exp_seg_none;
|
||||
one_lang_size_sections_pass (NULL, FALSE);
|
||||
/* We must not cache anything from the preliminary sizing. */
|
||||
lang_reset_memory_regions ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ppc_before_allocation (void)
|
||||
{
|
||||
if (is_ppc_elf (link_info.output_bfd))
|
||||
{
|
||||
if (!no_inline_opt
|
||||
&& !bfd_link_relocatable (&link_info))
|
||||
{
|
||||
prelim_size_sections ();
|
||||
|
||||
if (!ppc_elf_inline_plt (&link_info))
|
||||
einfo (_("%X%P: inline PLT: %E\n"));
|
||||
}
|
||||
|
||||
if (ppc_elf_tls_setup (link_info.output_bfd, &link_info)
|
||||
&& !notlsopt)
|
||||
{
|
||||
|
@ -147,13 +172,7 @@ ppc_before_allocation (void)
|
|||
asection *o;
|
||||
|
||||
/* Run lang_size_sections (if not already done). */
|
||||
if (expld.phase != lang_mark_phase_enum)
|
||||
{
|
||||
expld.phase = lang_mark_phase_enum;
|
||||
expld.dataseg.phase = exp_seg_none;
|
||||
one_lang_size_sections_pass (NULL, FALSE);
|
||||
lang_reset_memory_regions ();
|
||||
}
|
||||
prelim_size_sections ();
|
||||
|
||||
for (o = link_info.output_bfd->sections; o != NULL; o = o->next)
|
||||
{
|
||||
|
@ -250,6 +269,7 @@ enum ppc32_opt
|
|||
OPTION_OLD_PLT,
|
||||
OPTION_PLT_ALIGN,
|
||||
OPTION_NO_PLT_ALIGN,
|
||||
OPTION_NO_INLINE_OPT,
|
||||
OPTION_OLD_GOT,
|
||||
OPTION_STUBSYMS,
|
||||
OPTION_NO_STUBSYMS,
|
||||
|
@ -271,6 +291,7 @@ if test -z "$VXWORKS_BASE_EM_FILE" ; then
|
|||
{ "bss-plt", no_argument, NULL, OPTION_OLD_PLT },
|
||||
{ "plt-align", optional_argument, NULL, OPTION_PLT_ALIGN },
|
||||
{ "no-plt-align", no_argument, NULL, OPTION_NO_PLT_ALIGN },
|
||||
{ "no-inline-optimize", no_argument, NULL, OPTION_NO_INLINE_OPT },
|
||||
{ "sdata-got", no_argument, NULL, OPTION_OLD_GOT },'
|
||||
fi
|
||||
PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
|
||||
|
@ -308,6 +329,9 @@ if test -z "$VXWORKS_BASE_EM_FILE" ; then
|
|||
--no-plt-align Dont'\''t align individual PLT call stubs\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--no-inline-optimize Don'\''t convert inline PLT to direct calls\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--sdata-got Force GOT location just before .sdata\n"
|
||||
));'
|
||||
fi
|
||||
|
@ -369,6 +393,10 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
|
|||
params.plt_stub_align = 0;
|
||||
break;
|
||||
|
||||
case OPTION_NO_INLINE_OPT:
|
||||
no_inline_opt = 1;
|
||||
break;
|
||||
|
||||
case OPTION_OLD_GOT:
|
||||
old_got = 1;
|
||||
break;
|
||||
|
|
|
@ -55,6 +55,9 @@ static int no_tls_opt = 0;
|
|||
/* Whether to run opd optimization. */
|
||||
static int no_opd_opt = 0;
|
||||
|
||||
/* Whether to convert inline PLT calls to direct. */
|
||||
static int no_inline_opt = 0;
|
||||
|
||||
/* Whether to run toc optimization. */
|
||||
static int no_toc_opt = 0;
|
||||
|
||||
|
@ -282,6 +285,15 @@ ppc_before_allocation (void)
|
|||
&& !ppc64_elf_edit_opd (&link_info))
|
||||
einfo (_("%X%P: can not edit %s: %E\n"), "opd");
|
||||
|
||||
if (!no_inline_opt
|
||||
&& !bfd_link_relocatable (&link_info))
|
||||
{
|
||||
prelim_size_sections ();
|
||||
|
||||
if (!ppc64_elf_inline_plt (&link_info))
|
||||
einfo (_("%X%P: inline PLT: %E\n"));
|
||||
}
|
||||
|
||||
if (ppc64_elf_tls_setup (&link_info)
|
||||
&& !no_tls_opt)
|
||||
{
|
||||
|
@ -706,6 +718,7 @@ enum ppc64_opt
|
|||
OPTION_TLS_GET_ADDR_OPT,
|
||||
OPTION_NO_TLS_GET_ADDR_OPT,
|
||||
OPTION_NO_OPD_OPT,
|
||||
OPTION_NO_INLINE_OPT,
|
||||
OPTION_NO_TOC_OPT,
|
||||
OPTION_NO_MULTI_TOC,
|
||||
OPTION_NO_TOC_SORT,
|
||||
|
@ -733,6 +746,7 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}'
|
|||
{ "tls-get-addr-optimize", no_argument, NULL, OPTION_TLS_GET_ADDR_OPT },
|
||||
{ "no-tls-get-addr-optimize", no_argument, NULL, OPTION_NO_TLS_GET_ADDR_OPT },
|
||||
{ "no-opd-optimize", no_argument, NULL, OPTION_NO_OPD_OPT },
|
||||
{ "no-inline-optimize", no_argument, NULL, OPTION_NO_INLINE_OPT },
|
||||
{ "no-toc-optimize", no_argument, NULL, OPTION_NO_TOC_OPT },
|
||||
{ "no-multi-toc", no_argument, NULL, OPTION_NO_MULTI_TOC },
|
||||
{ "no-toc-sort", no_argument, NULL, OPTION_NO_TOC_SORT },
|
||||
|
@ -810,6 +824,9 @@ PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}'
|
|||
--no-opd-optimize Don'\''t optimize the OPD section\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--no-inline-optimize Don'\''t convert inline PLT to direct calls\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
--no-toc-optimize Don'\''t optimize the TOC section\n"
|
||||
));
|
||||
fprintf (file, _("\
|
||||
|
@ -915,6 +932,10 @@ PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}'
|
|||
no_opd_opt = 1;
|
||||
break;
|
||||
|
||||
case OPTION_NO_INLINE_OPT:
|
||||
no_inline_opt = 1;
|
||||
break;
|
||||
|
||||
case OPTION_NO_TOC_OPT:
|
||||
no_toc_opt = 1;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue