The Linux kernel builds modules using ld -r. These might need the
ppc476 workaround, so enable it for ld -r if sections have sufficient
alignment to tell location within a page.
bfd/
* elf32-ppc.c (ppc_elf_relax_section): Enable ppc476 workaround
for ld -r, when code sections are sufficiently aligned.
* elf32-ppc.h (struct ppc_elf_params): Delete pagesize. Add
pagesize_p2.
ld/
* emultempl/ppc32elf.em (pagesize): New static var.
(ppc_after_open_output): Set params.pagesize_p2 from pagesize.
(PARSE_AND_LIST_ARGS_CASES): Adjust to use pagesize.
This implements a work-around for an icache bug on 476 that can cause
execution of stale instructions when control falls through from one
page to the next. The idea is to prevent such fall-through by
replacing the last instruction on a page with a branch to a patch
area containing the instruction, then branch to the next page.
The patch also fixes a number of bugs in the existing support for long
branch trampolines.
bfd/
* elf32-ppc.c (struct ppc_elf_link_hash_table): Add params.
Delete emit_stub_syms, no_tls_get_addr_opt. Update all uses.
(ppc_elf_link_params): New function.
(ppc_elf_create_glink): Align .glink to 64 bytes for ppc476
workaround.
(ppc_elf_select_plt_layout): Remove plt_style and emit_stub_syms
parameters. Use htab->params instead.
(ppc_elf_tls_setup): Remove no_tls_get_addr_opt parameter.
(ppc_elf_size_dynamic_sections): Align __glink_PLTresolve to
64 bytes for ppc476 workaround.
(struct ppc_elf_relax_info): New.
(ppc_elf_relax_section): Exclude linker created sections and
those too small to hold one instruction. Don't add another
branch around trampolines on later relax passes. Don't
generate trampolines for undefined symbols when !relocatable,
nor for plugin symbols. Allocate space for ppc476 workaround
patch area. Free fixups on error return path.
(ppc_elf_relocate_section): Handle ppc476 workaround patching.
* elf32-ppc.h (struct ppc_elf_params): New.
(ppc_elf_select_plt_layout, ppc_elf_tls_setup): Update prototype.
(ppc_elf_link_params): Declare.
* section.c (SEC_INFO_TYPE_TARGET): Define.
* bfd-in2.h: Regenerate.
ld/
* emultempl/ppc32elf.em (no_tls_get_addr_opt, emit_stub_syms)
plt_style): Delete. Adjust all refs to instead use..
(params): ..this. New variable.
(ppc_after_open_output): New function. Tweak params and pass to
ppc_elf_link_params.
(ppc_after_open): Adjust ppc_elf_select_plt_layout call.
(ppc_before_allocation): Adjust ppc_elf_tls_setup call. Enable
relaxation for ppc476 workaround.
(PARSE_AND_LIST_*): Add --{no-,}ppc476-workaround support.
(LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS): Define.
(BFD_RELOC_HI16_S_PCREL, BFD_RELOC_LO16_PCREL): Define.
* elf32-ppc.c (GLINK_PLTRESOLVE, GLINK_ENTRY_SIZE): Define.
(CROR_151515, CROR_313131): Delete.
(ADDIS_11_11, ADDI_11_11, SUB_11_11_30, ADD_0_11_11, ADD_11_0_11,
LWZ_0_4_30, MTCTR_0, LWZ_12_8_30, BCTR, ADDIS_11_30,
LWZU_0_X_11): Define.
(ppc_elf_howto_raw): Add R_PPC_REL16, R_PPC_REL16_LO, R_PPC_REL16_HI
and R_PPC_REL16_HA entries.
(ppc_elf_reloc_type_lookup): Convert new bfd reloc types.
(ppc_elf_addr16_ha_reloc): Also handle R_PPC_REL16_HA.
(struct ppc_elf_link_hash_table): Add glink, glink_pltresolve,
new_plt, and old_plt.
(ppc_elf_create_dynamic_sections): Create .glink section.
(ppc_elf_check_relocs): Set new_plt and old_plt.
(ppc_elf_select_plt_layout): New function.
(ppc_elf_tls_setup): Set plt output section elf type and flags.
(allocate_got): Handle differences between old and new got layout.
(allocate_dynrelocs): Likewise for plt.
(ppc_elf_size_dynamic_sections): Likewise. Allocate memory for
.glink. Don't allocate memory for old bss .plt. Emit DT_PPC_GLINK.
(ppc_elf_relax_section): Rename ppc_info to htab. Handle .glink
destination of R_PPC_PLTREL24 relocs.
(ppc_elf_relocate_section): Handle new relocs and changed destination
of R_PPC_PLTREL24.
(ppc_elf_finish_dynamic_symbol): Init new style plt and handle
differences in layout.
(ppc_elf_finish_dynamic_sections): Set DT_PPC_GLINK value. Don't
put a blrl in new got. Write glink contents.
* elf32-ppc.h (ppc_elf_select_plt_layout): Declare.
* libbfd.h: Regenerate.
* bfd-in2.h: Regenerate.
* elf32-ppc.c (struct elf_linker_section): Remove sym_hash and
sym_offset. Add name, bss_name, sym_name, sym_val.
(struct ppc_elf_link_hash_table): Remove sdata and sdata2 pointers.
Add sdata array of elf_linker_section_t.
(ppc_elf_link_hash_table_create): Set name, sym_name, and bss_name.
(enum elf_linker_section_enum): Delete.
(ppc_elf_create_linker_section): Rewrite. Don't create syms here.
(ppc_elf_check_relocs): Delay ppc_elf_create_linker_section until
the special sections are needed. Adjust htab->sdata refs.
Ensure dynobj is set in sreloc code.
(ppc_elf_size_dynamic_sections): Strip sdata sections.
(ppc_elf_set_sdata_syms): New function.
(elf_finish_pointer_linker_section): Use 0x8000 for sym_offset.
(ppc_elf_relocate_section): Adjust references to htab->sdata. Use
sym_val instead of sym_hash.
* elf32-ppc.h (ppc_elf_set_sdata_syms): Declare.
ld/
* emultempl/ppc32elf.em (gld${EMULATION_NAME}_after_allocation): New
function.
(LDEMUL_AFTER_ALLOCATION): Define.
* elf32-ppc.c: Include elf32-ppc.h.
(NOP, CROR_151515, CROR_313131, TP_OFFSET, DTP_OFFSET): Define.
(struct ppc_elf_link_hash_entry): Rename "root" to "elf". Adjust uses.
Add "tls_mask" field.
(TLS_GD, TLS_LD, TLS_TPREL, TLS_DTPREL, TLS_TLS, TLS_TPRELGD): Define.
(struct ppc_elf_link_hash_table): Rename "root" to "elf". Adjust uses.
Add got, relgot, plt, relplt, dynbss, relbss, dynsbss, relsbss,
sdata, sdata2, tls_sec, tls_get_addr, tlsld_got fields.
Make use of htab shortcuts throughout file.
(ppc_elf_link_hash_newfunc): Init tls_mask field.
(ppc_elf_link_hash_table_create): Init new fields.
(ppc_elf_copy_indirect_symbol): Copy tls_mask.
(ppc_elf_howto_raw): Add tls relocs.
(ppc_elf_reloc_type_lookup): Handle them.
(ppc_elf_unhandled_reloc): New function.
(ppc_elf_create_got): Stash got section pointer in hash table,
return status. Make .rela.got too.
(ppc_elf_create_dynamic_sections): Stash section pointers in htab.
(ppc_elf_adjust_dynamic_symbol): Only set up copy relocs when
NON_GOT_REF set. Don't allocate space in .plt here..
(allocate_dynrelocs): ..do so here instead, properly ref-counting and
not allocating plt entries unnecessarily. Allocate got entries here.
(WILL_CALL_FINISH_DYNAMIC_SYMBOL): Define.
(ppc_elf_size_dynamic_sections): Allocate local got entries. Pass
"info" during allocate_dynrelocs hash traversal. Use htab section
shortcuts rather than searching for named sections. Get rid of
"plt" and "strip" booleans.
(update_local_sym_info, bad_shared_reloc): New functions.
(ppc_elf_check_relocs): Handle TLS relocs. Move .rela.got creation to
ppc_elf_create_got. Don't mark got or plt reloc syms dynamic, do so
in allocate_dynreloc. Use update_local_sym_info and bad_shared_reloc.
Disallow R_PPC_EMB_RELSDA, R_PPC_EMB_NADDR32, R_PPC_EMB_NADDR16,
R_PPC_EMB_NADDR16_LO, R_PPC_EMB_NADDR16_HI and R_PPC_EMB_NADDR16_HA
in shared libs. R_PPC_PLTREL32 is a plt reloc too. Refcount all
relocs that might use a plt entry. Set NON_GOT_REF too.
Enumerate all do-nothing relocs.
(ppc_elf_gc_sweep_hook): Simplify removal of dynrelocs. Handle
tls relocs and all plt relocs.
(ppc_elf_tls_setup, ppc_elf_tls_optimize): New functions.
(ppc_elf_finish_dynamic_symbol): Don't build got entries here.
(ppc_elf_finish_dynamic_sections): Rewrite tag code using htab
shortcuts.
(ppc_elf_relocate_section): Tidy. Handle TLS relocs. Use
bfd_elf_local_sym_name. Simplify unresolved reloc code. Build got
entries and got relocs here. Warn on non-zero got reloc addend.
Split out branch taken/not taken reloc code into a separate switch
and correct offset calculation. Allow BRTAKEN/BRNTAKEN dynamic relocs.
Split out HA reloc adjustments to separate switch statement. Don't
warn on reloc overflow if we've already warned about undefined.
Don't rebuild sym name when reporting errors. Report all possible
errors from _bfd_final_link_relocate.
(bfd_elf32_bfd_final_link): Don't define.