diff options
author | nobody <> | 2003-03-03 20:50:21 +0000 |
---|---|---|
committer | nobody <> | 2003-03-03 20:50:21 +0000 |
commit | 900958cda09af0ca2839cc7e2a7c46355b051c83 (patch) | |
tree | 45e564da9eaed919ca56fc52f793cb0578b02a8b /bfd | |
parent | cddd45abf62af6ed70c8c67601a9f09da0a939b0 (diff) | |
download | fsf-binutils-gdb-900958cda09af0ca2839cc7e2a7c46355b051c83.zip fsf-binutils-gdb-900958cda09af0ca2839cc7e2a7c46355b051c83.tar.gz fsf-binutils-gdb-900958cda09af0ca2839cc7e2a7c46355b051c83.tar.bz2 |
This commit was manufactured by cvs2svn to create branchcagney_offbyone-20030303-branchpoint
'cagney_offbyone-20030303-branch'.
Sprout from interps-20030202-branch 2003-02-02 23:00:07 UTC nobody 'This commit was manufactured by cvs2svn to create branch'
Cherrypick from master 2003-03-03 20:50:20 UTC Andrew Cagney <cagney@redhat.com> '2003-03-03 Andrew Cagney <cagney@redhat.com>':
ChangeLog
Makefile.def
Makefile.in
Makefile.tpl
bfd/ChangeLog
bfd/Makefile.am
bfd/Makefile.in
bfd/archures.c
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/bfd.c
bfd/coff-h8300.c
bfd/coff-ppc.c
bfd/coffcode.h
bfd/config.bfd
bfd/cpu-arm.c
bfd/doc/ChangeLog
bfd/doc/bfd.texinfo
bfd/doc/fdl.texi
bfd/ecoff.c
bfd/elf-bfd.h
bfd/elf-eh-frame.c
bfd/elf.c
bfd/elf32-arm.h
bfd/elf32-cris.c
bfd/elf32-hppa.c
bfd/elf32-i386.c
bfd/elf32-m68k.c
bfd/elf32-mips.c
bfd/elf32-ppc.c
bfd/elf32-ppc.h
bfd/elf32-s390.c
bfd/elf32-sh.c
bfd/elf32-sparc.c
bfd/elf32-vax.c
bfd/elf64-alpha.c
bfd/elf64-hppa.c
bfd/elf64-mips.c
bfd/elf64-mmix.c
bfd/elf64-ppc.c
bfd/elf64-ppc.h
bfd/elf64-s390.c
bfd/elf64-sparc.c
bfd/elf64-x86-64.c
bfd/elfcore.h
bfd/elflink.c
bfd/elflink.h
bfd/elfn32-mips.c
bfd/elfxx-ia64.c
bfd/elfxx-mips.c
bfd/format.c
bfd/ieee.c
bfd/libbfd.h
bfd/libcoff.h
bfd/mmo.c
bfd/oasys.c
bfd/po/da.po
bfd/reloc.c
bfd/section.c
bfd/syms.c
bfd/targets.c
bfd/version.h
config.guess
config.sub
configure
configure.in
gdb/ChangeLog
gdb/MAINTAINERS
gdb/Makefile.in
gdb/NEWS
gdb/PROBLEMS
gdb/TODO
gdb/acinclude.m4
gdb/aclocal.m4
gdb/ada-exp.y
gdb/ada-lang.c
gdb/ada-lang.h
gdb/ada-typeprint.c
gdb/alpha-tdep.c
gdb/arch-utils.c
gdb/arm-linux-tdep.c
gdb/arm-tdep.c
gdb/avr-tdep.c
gdb/ax-gdb.c
gdb/block.c
gdb/block.h
gdb/blockframe.c
gdb/breakpoint.c
gdb/breakpoint.h
gdb/buildsym.c
gdb/buildsym.h
gdb/c-exp.y
gdb/c-valprint.c
gdb/cli-out.c
gdb/cli-out.h
gdb/cli/cli-cmds.c
gdb/cli/cli-decode.c
gdb/cli/cli-dump.c
gdb/cli/cli-interp.c
gdb/cli/cli-script.c
gdb/cli/cli-setshow.c
gdb/coff-pe-read.c
gdb/coff-pe-read.h
gdb/coffread.c
gdb/config.in
gdb/config/djgpp/fnchange.lst
gdb/config/h8500/h8500.mt
gdb/config/h8500/tm-h8500.h
gdb/config/i386/nm-i386.h
gdb/config/i386/nm-i386sco5.h
gdb/config/i386/nm-i386sol2.h
gdb/config/i386/tm-ptx.h
gdb/config/ia64/tm-ia64.h
gdb/config/m32r/m32r.mt
gdb/config/m32r/tm-m32r.h
gdb/config/mn10200/mn10200.mt
gdb/config/mn10200/tm-mn10200.h
gdb/config/pa/tm-hppa.h
gdb/config/pa/tm-hppa64.h
gdb/config/s390/nm-linux.h
gdb/config/sparc/nm-sun4sol2.h
gdb/config/sparc/tm-sp64.h
gdb/config/sparc/tm-sparc.h
gdb/config/z8k/tm-z8k.h
gdb/config/z8k/z8k.mt
gdb/configure
gdb/configure.host
gdb/configure.in
gdb/configure.tgt
gdb/cp-valprint.c
gdb/cris-tdep.c
gdb/d10v-tdep.c
gdb/dbxread.c
gdb/defs.h
gdb/disasm.c
gdb/doc/ChangeLog
gdb/doc/Makefile.in
gdb/doc/gdb.texinfo
gdb/doc/gdbint.texinfo
gdb/doublest.c
gdb/dwarf2cfi.c
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2loc.h
gdb/dwarf2read.c
gdb/dwarfread.c
gdb/elfread.c
gdb/event-top.c
gdb/event-top.h
gdb/expprint.c
gdb/f-exp.y
gdb/f-lang.c
gdb/f-valprint.c
gdb/findvar.c
gdb/frame.c
gdb/frame.h
gdb/frv-tdep.c
gdb/gdb.c
gdb/gdb_mbuild.sh
gdb/gdb_thread_db.h
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/gnu-v2-abi.c
gdb/h8300-tdep.c
gdb/h8500-tdep.c
gdb/hppa-tdep.c
gdb/hpread.c
gdb/hpux-thread.c
gdb/i386-interix-tdep.c
gdb/i386-linux-tdep.c
gdb/i386-tdep.c
gdb/i386bsd-tdep.c
gdb/ia64-linux-nat.c
gdb/ia64-tdep.c
gdb/infcmd.c
gdb/inflow.c
gdb/inflow.h
gdb/infptrace.c
gdb/infrun.c
gdb/inftarg.c
gdb/infttrace.c
gdb/interps.c
gdb/interps.h
gdb/jv-exp.y
gdb/jv-lang.c
gdb/jv-typeprint.c
gdb/jv-valprint.c
gdb/linespec.c
gdb/linux-proc.c
gdb/lynx-nat.c
gdb/m2-exp.y
gdb/m32r-rom.c
gdb/m32r-stub.c
gdb/m32r-tdep.c
gdb/m68hc11-tdep.c
gdb/m68k-tdep.c
gdb/main.c
gdb/main.h
gdb/maint.c
gdb/mcore-tdep.c
gdb/mdebugread.c
gdb/mi/ChangeLog
gdb/mi/gdbmi.texinfo
gdb/mi/mi-cmd-env.c
gdb/mi/mi-cmd-stack.c
gdb/mi/mi-cmds.c
gdb/mi/mi-cmds.h
gdb/mi/mi-console.c
gdb/mi/mi-console.h
gdb/mi/mi-interp.c
gdb/mi/mi-main.c
gdb/mi/mi-main.h
gdb/minsyms.c
gdb/mips-tdep.c
gdb/mipsread.c
gdb/mn10200-tdep.c
gdb/mn10300-tdep.c
gdb/monitor.c
gdb/nlmread.c
gdb/ns32k-tdep.c
gdb/objc-exp.y
gdb/objc-lang.c
gdb/objc-lang.h
gdb/objfiles.c
gdb/objfiles.h
gdb/observer.c
gdb/observer.h
gdb/osabi.c
gdb/p-exp.y
gdb/p-valprint.c
gdb/parse.c
gdb/parser-defs.h
gdb/ppc-linux-nat.c
gdb/ppc-linux-tdep.c
gdb/printcmd.c
gdb/proc-api.c
gdb/procfs.c
gdb/rdi-share/ardi.c
gdb/regcache.c
gdb/regcache.h
gdb/remote-e7000.c
gdb/remote-sim.c
gdb/remote.c
gdb/rs6000-tdep.c
gdb/s390-tdep.c
gdb/sh-tdep.c
gdb/sol-thread.c
gdb/solib-sunos.c
gdb/solib.c
gdb/solist.h
gdb/somread.c
gdb/somsolib.c
gdb/sparc-nat.c
gdb/sparc-tdep.c
gdb/stabsread.c
gdb/stack.c
gdb/symfile.c
gdb/symfile.h
gdb/symm-nat.c
gdb/symmisc.c
gdb/symtab.c
gdb/symtab.h
gdb/target.c
gdb/target.h
gdb/testsuite/ChangeLog
gdb/testsuite/Makefile.in
gdb/testsuite/configure.in
gdb/testsuite/gdb.base/advance.c
gdb/testsuite/gdb.base/advance.exp
gdb/testsuite/gdb.base/dump.exp
gdb/testsuite/gdb.base/exprs.exp
gdb/testsuite/gdb.base/funcargs.exp
gdb/testsuite/gdb.base/list.exp
gdb/testsuite/gdb.base/maint.exp
gdb/testsuite/gdb.base/ptype.exp
gdb/testsuite/gdb.base/restore.c
gdb/testsuite/gdb.base/until.exp
gdb/testsuite/gdb.base/watchpoint.exp
gdb/testsuite/gdb.c++/anon-union.exp
gdb/testsuite/gdb.c++/classes.exp
gdb/testsuite/gdb.c++/cplusfuncs.exp
gdb/testsuite/gdb.c++/inherit.exp
gdb/testsuite/gdb.c++/local.cc
gdb/testsuite/gdb.c++/local.exp
gdb/testsuite/gdb.c++/overload.cc
gdb/testsuite/gdb.c++/overload.exp
gdb/testsuite/gdb.c++/ovldbreak.exp
gdb/testsuite/gdb.c++/pr-1023.cc
gdb/testsuite/gdb.c++/pr-1023.exp
gdb/testsuite/gdb.c++/templates.exp
gdb/testsuite/gdb.c++/virtfunc.exp
gdb/testsuite/gdb.disasm/Makefile.in
gdb/testsuite/gdb.disasm/mn10200.exp
gdb/testsuite/gdb.mi/ChangeLog
gdb/testsuite/gdb.mi/mi-cli.exp
gdb/testsuite/gdb.mi/mi-syn-frame.c
gdb/testsuite/gdb.mi/mi-syn-frame.exp
gdb/testsuite/gdb.trace/Makefile.in
gdb/testsuite/lib/gdb.exp
gdb/thread.c
gdb/top.c
gdb/tracepoint.c
gdb/tui/ChangeLog
gdb/tui/tui-hooks.c
gdb/tui/tui-interp.c
gdb/tui/tui.c
gdb/tui/tuiData.h
gdb/tui/tuiIO.c
gdb/typeprint.c
gdb/ui-out.c
gdb/ui-out.h
gdb/utils.c
gdb/v850-tdep.c
gdb/valops.c
gdb/value.h
gdb/values.c
gdb/vax-tdep.c
gdb/version.in
gdb/win32-nat.c
gdb/wrapper.h
gdb/x86-64-linux-nat.c
gdb/x86-64-tdep.c
gdb/xcoffread.c
gdb/xstormy16-tdep.c
gdb/z8k-tdep.c
include/ChangeLog
include/elf/ChangeLog
include/elf/arm.h
include/elf/ia64.h
include/elf/ppc.h
include/elf/ppc64.h
include/gdb/ChangeLog
include/gdb/remote-sim.h
include/libiberty.h
include/opcode/ChangeLog
include/opcode/h8300.h
libiberty/ChangeLog
libiberty/Makefile.in
libiberty/acconfig.h
libiberty/aclocal.m4
libiberty/config.in
libiberty/configure
libiberty/configure.in
libiberty/cplus-dem.c
libiberty/functions.texi
libiberty/libiberty.texi
libiberty/lrealpath.c
libiberty/make-relative-prefix.c
libiberty/physmem.c
libtool.m4
ltcf-cxx.sh
ltcf-gcj.sh
ltconfig
opcodes/ChangeLog
opcodes/fr30-desc.c
opcodes/hppa-dis.c
opcodes/i386-dis.c
opcodes/mips-dis.c
readline/ChangeLog.gdb
readline/Makefile.in
readline/aclocal.m4
readline/config.h.in
readline/configure
readline/rlmbutil.h
readline/shlib/Makefile.in
sim/ChangeLog
sim/arm/ChangeLog
sim/arm/armos.c
sim/arm/wrapper.c
sim/common/ChangeLog
sim/common/Make-common.in
sim/common/nrun.c
sim/common/sim-base.h
sim/common/sim-engine.c
sim/common/sim-engine.h
sim/common/sim-hload.c
sim/common/sim-module.c
sim/common/sim-utils.h
sim/d10v/ChangeLog
sim/d10v/interp.c
sim/erc32/ChangeLog
sim/erc32/interf.c
sim/h8300/ChangeLog
sim/h8300/compile.c
sim/h8500/ChangeLog
sim/h8500/compile.c
sim/i960/ChangeLog
sim/i960/sim-if.c
sim/m32r/ChangeLog
sim/m32r/sim-if.c
sim/m68hc11/ChangeLog
sim/m68hc11/Makefile.in
sim/m68hc11/interp.c
sim/mcore/ChangeLog
sim/mcore/interp.c
sim/mips/ChangeLog
sim/mips/interp.c
sim/mn10200/ChangeLog
sim/mn10200/interp.c
sim/mn10300/ChangeLog
sim/mn10300/am33.igen
sim/mn10300/dv-mn103tim.c
sim/mn10300/interp.c
sim/ppc/ChangeLog
sim/ppc/sim_calls.c
sim/sh/ChangeLog
sim/sh/gencode.c
sim/sh/interp.c
sim/v850/ChangeLog
sim/v850/interp.c
sim/z8k/ChangeLog
sim/z8k/iface.c
Delete:
gdb/config/i386/gdbserve.mt
gdb/config/i386/i386sco5.mt
gdb/config/i386/i386v4.mt
gdb/config/i386/i386v42mp.mt
gdb/config/m68k/nm-apollo68b.h
gdb/config/m68k/nm-hp300bsd.h
gdb/config/m68k/tm-apollo68b.h
gdb/config/m68k/tm-es1800.h
gdb/config/m68k/tm-hp300bsd.h
gdb/config/m68k/tm-mac.h
gdb/config/m68k/xm-apollo68b.h
gdb/config/pa/hpux1020.mt
gdb/config/pa/hpux11.mt
gdb/config/pa/hpux11w.mt
gdb/config/powerpc/gdbserve.mt
gdb/config/powerpc/ppcle-eabi.mt
gdb/config/powerpc/ppcle-sim.mt
gdb/config/powerpc/tm-ppc-sim.h
gdb/config/sparc/sp64sim.mt
gdb/config/sparc/tm-sp64sim.h
sim/common/sim-break.c
sim/common/sim-break.h
Diffstat (limited to 'bfd')
58 files changed, 9009 insertions, 4605 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ef1e407..393ab0f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,513 @@ +2003-03-03 Nick Clifton <nickc@redhat.com> + + * po/da.po: Installed latest translation. + +2003-03-02 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de> + + * elf32-mips.c (elf_mips_howto_table_rel): Change definition of + R_MIPS_PC16 to rightshift 2. + (elf_reloc_map mips_reloc_map): Map to rightshifted BFD reloc. + (bfd_elf32_bfd_reloc_type_lookup): Support + BFD_RELOC_MIPSEMB_16_PCREL_S2. + * elf64-mips.c (mips_elf64_howto_table_rel): Change definition of + R_MIPS_PC16 to rightshift 2. + (mips_elf64_howto_table_rela): Likewise. + (mips_reloc_map): Map to rightshifted BFD reloc. + * elfn32-mips.c: The same as in elf64-mips.c. + * elfxx-mips.c (mips_elf_got_for_ibfd): Typo in comment. + (mips_elf_calculate_relocation): Handle rightshifted addends for + R_MIPS_PC16. + * reloc.c (BFD_RELOC_MIPSEMB_16_PCREL_S2): New BFD relocation for + MIPS Embedded PIC. Remove superfluous empty COMMENT. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + +2003-02-28 Richard Henderson <rth@redhat.com> + + * elfxx-ia64.c (elfNN_ia64_relax_section): Correct bounds + for ltoff22x relaxation. + +2003-03-01 Alan Modra <amodra@bigpond.net.au> + + * bfd-in.h (_bfd): Don't define. + * bfd.c: Rename occurrences of "struct _bfd" to "struct bfd". + * syms.c: Likewise. + * bfd-in2.h: Regenerate. + +2003-02-27 Richard Henderson <rth@redhat.com> + + * elfxx-ia64.c (struct elfNN_ia64_dyn_sym_info): Add want_gotx; + (elfNN_ia64_check_relocs): Set it. + (allocate_global_data_got): Check it. + (allocate_local_got): Likewise. + (allocate_dynrel_entries): Likewise. + (elfNN_ia64_relax_ldxmov): New. + (elfNN_ia64_relax_section): Handle LTOFF22X, LDXMOV. + (elfNN_ia64_choose_gp): Split out from ... + (elfNN_ia64_final_link): ... here. + +2003-02-27 Andrew Cagney <cagney@redhat.com> + + * bfd.c (struct bfd): Rename "struct _bfd". + * bfd-in.h: Update copyright. + (struct bfd): Rename "struct _bfd". + (_bfd): Define for backward compatibility. + * bfd-in2.h: Regenerate. + +2003-02-25 Alan Modra <amodra@bigpond.net.au> + + * elflink.h (elf_bfd_final_link): Apportion reloc counts to rel_hdr + and rel_hdr2 when initially counting input relocs rather than after + creating output reloc sections. + (elf_link_read_relocs_from_section): Don't abort with wrong reloc + sizes. + + * Makefile.am: Run "make dep-am". + * Makefile.in: Regenerate. + +2003-02-24 Kris Warkentin <kewarken@qnx.com> + + * elf.c (elfcore_read_notes): Add check for QNX style core file. + (elfcore_grog_nto_note): New function. + (elfcore_grog_nto_gregs): New function. + (elfcore_grog_nto_status): New function. + +2003-02-24 Alan Modra <amodra@bigpond.net.au> + + * elflink.c (_bfd_elf_create_got_section): Check existing .got + section flags before concluding that we've already been called. + Don't use register keyword. + (_bfd_elf_create_dynamic_sections): Don't use register keyword. + (_bfd_elf_create_linker_section): Formatting. + +2003-02-20 jmc <jmc@prioris.mini.pw.edu.pl> + + * coff-h8300.c: Fix typo: intial -> initial. + * coff-ppc.c: Likewise. + +2003-02-20 Alan Modra <amodra@bigpond.net.au> + + * elf32-ppc.c: Formatting. + (allocate_dynrelocs): LD and GD relocs against the same sym need + separate GOT entries. + (ppc_elf_relocate_section): Correct GOT handling for multiple GOT + entries per symbol. + +2003-02-19 Alan Modra <amodra@bigpond.net.au> + + * elf32-hppa.c (elf32_hppa_gc_sweep_hook): Simplify dynamic reloc + removal. Localize vars. Remove unnecessary dynobj test. + * elf32-i386 (WILL_CALL_FINISH_DYNAMIC_SYMBOL): Pass SHARED instead + of INFO. + (allocate_dynrelocs): Adjust WILL_CALL_FINISH_DYNAMIC_SYMBOL uses, + and optimize. + (elf_i386_relocate_section): Likewise. + (elf_i386_gc_sweep_hook): Simplify dyn reloc removal. Localize vars. + * elf32-s390.c (elf_s390_gc_sweep_hook): Likewise. + * elf32-sh.c (sh_elf_gc_sweep_hook): Likewise. + * elf64-s390.c (elf_s390_gc_sweep_hook): Likewise. + * elf64-x86-64.c (elf64_x86_64_gc_sweep_hook): Likewise. + * elf32-sparc.c (elf32_sparc_gc_sweep_hook): Likewise. Remove + local_dynrel for section too. Don't touch HIPLT22, LOPLT10, PCPLT32 + or PCPLT10 relocs. Don't subtract twice on PLT32 relocs. + Formatting. + + * elf64-ppc.c (ELIMINATE_COPY_RELOCS): Define. + (ppc64_elf_check_relocs): Use it. Correct comment. Move SEC_ALLOC + test. + (ppc64_elf_adjust_dynamic_symbol): Use ELIMINATE_COPY_RELOCS. + (WILL_CALL_FINISH_DYNAMIC_SYMBOL): Pass SHARED instead of INFO. + (allocate_dynrelocs): Adjust WILL_CALL_FINISH_DYNAMIC_SYMBOL uses, + and optimize. Use ELIMINATE_COPY_RELOCS. + (ppc64_elf_relocate_section): Likewise. + + * elf32-ppc.c (struct ppc_elf_dyn_relocs): Add pc_count field. + (ppc_elf_copy_indirect_symbol): Copy pc_count field. + (ELIMINATE_COPY_RELOCS): Define. + (ppc_elf_adjust_dynamic_symbol): Convert copy relocs to dynamic. + (WILL_CALL_FINISH_DYNAMIC_SYMBOL): Pass SHARED instead of INFO. + (MUST_BE_DYN_RELOC): Define. + (allocate_dynrelocs): Adjust WILL_CALL_FINISH_DYNAMIC_SYMBOL uses, + and optimize. Trim dyn_relocs. + (ppc_elf_check_relocs): Don't generate dyn_relocs when we know they'll + not be used. Do generate dyn_relocs for copy reloc avoidance. Keep + track of pc_rel dyn relocs. + (ppc_elf_relocate_section): Remove "will_become_local". Adjust + WILL_CALL_FINISH_DYNAMIC_SYMBOL use. Trim dyn relocs as per + allocate_dynrelocs. Don't recalculate "sec". + +2003-02-18 Alan Modra <amodra@bigpond.net.au> + + * elf32-ppc.c (ppc_elf_relocate_section): Remove unnecessary test. + * elf64-ppc.c (ppc64_elf_tls_optimize): Decrement tlsld_got.refcount + on invalid LD relocs. + (allocate_dynrelocs): Invalid LD relocs don't use tlsld_got entry. + (ppc64_elf_relocate_section): Unify new handling of LD relocs and + tlsld_got entry. Use IS_PPC64_TLS_RELOC. + + * elf32-ppc.h: New file. + * 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. + +2003-02-18 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (ppc64_elf_relocate_section): Don't init "r". Don't + rebuild sym name when reporting errors. + +2003-02-17 Nick Clifton <nickc@redhat.com> + + * elflink.h (elf_link_output_extsym): Only check + allow_shlib_undefined for shared libraries. + * elf32-i386.c (elf_i386_relocate_section): Remove bogus check + of allow_shlib_undefined. + * elf32-cris.c (cris_elf_relocate_section): Likewise. + * elf32-hppa.c (elf32_hppa_relocate_section): Likewise. + * elf32-m68k.c (elf_m68k_relocate_section): Likewise. + * elf32-ppc.c (ppc_elf_relocate_section): Likewise. + * elf32-s390.c (elf_s390_relocate_section): Likewise. + * elf32-sh.c (sh_elf_relocate_section): Likewise. + * elf32-sparc.c (elf32_sparc_relocate_section): Likewise. + * elf32-vax.c (elf_vax_relocate_section): Likewise. + * elf64-alpha.c (elf64_alpha_relocate_section): Likewise. + * elf64-hppa.c (elf64_hppa_relocate_section): Likewise. + * elf64-ppc.c (ppc64_elf_relocate_section): Likewise. + * elf64-s390.c (elf_s390_relocate_section): Likewise. + * elf64-sparc.c (sparc64_elf_relocate_section): Likewise. + * elf64-x86-64.c (elf64_x86_64_relocate_section): Likewise. + * elfxx-ia64.c (elfNN_ia64_relocate_section): Likewise. + * elfxx-mips.c (_bfd_mips_elf_relocate_section): Likewise. + +2003-02-17 Nick Clifton <nickc@redhat.com> + + * elf.c (SEGMENT_AFTER_SEGMENT): Add third parameter - the + address field to use in the comparison. + (SEGMENT_OVERLAPS): Check that LMAs overlap as well. + +2003-02-14 Bob Wilson <bob.wilson@acm.org> + + * elfcore.h (elf_core_file_p): Compare alternate machine codes for ELF + backends when checking if the generic ELF target should be used. + + * syms.c (_bfd_stab_section_find_nearest_line): For line number stabs + outside of functions, treat values as absolute addresses. + + * bfd.c: Change embedded documentation to use consistent indentation + and to split up long lines. Change informal style of description + for functions lacking real documentation. + * coffcode.h: Break up long lines in embedded documentation. + * format.c: Likewise. + * targets.c: Likewise. + * libcoff.h: Regenerate. + * bfd-in2.h: Regenerate. + +2003-02-14 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (ppc64_elf_link_hash_table_create): Init tls_get_addr. + (ppc64_elf_copy_indirect_symbol): Merge tls_mask too. + (ppc64_elf_gc_sweep_hook): Simplify removal of dyn_relocs. + (allocate_dynrelocs): Don't treat undefined and undefweak specially. + (ppc_size_one_stub): Fix warning, and tighten plt entry check. + (group_sections): Don't share a stub section if stubs are for a large + section. Adjust comment. + (ppc64_elf_size_stubs): Roughly double the size left for stubs if + !stubs_always_before_branch. + (ppc64_elf_relocate_section): Initialize tlsld GOT entry once. Don't + treat undefined and undefweak specially when processing dyn relocs. + +2003-02-13 Jakub Jelinek <jakub@redhat.com> + + * elflink.h (elf_link_add_object_symbols): Handle .symver x, x@FOO. + +2003-02-13 Nick Clifton <nickc@redhat.com> + + * elf32-arm.h (elf32_thumb_to_arm_stub): Include section VMAs + in computation of offset to insert into BL instruction. + +2003-02-11 Uwe Stieber <uwe@wwws.de> + + * config.bfd: Add support for kaOS as cross build target system. + +2003-02-11 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (ppc64_elf_check_relocs): Match versioned + .__tls_get_addr too. + (ppc64_elf_tls_setup): Ensure cached tls_get_addr is not indirect. + +2003-02-10 Kaz kojima <kkojima@rr.iij4u.or.jp> + + * elf32-sh.c (elf_sh_dyn_relocs): Add tls_tpoff32 field. + (elf_sh_link_hash_entry): Remove tls_tpoff32 field. + (sh_elf_link_hash_newfunc): Remove the initialization of + tls_tpoff32 field. + (allocate_dynrelocs): Keep dyn_relocs if it includes the entry + for which tls_tpoff32 flag is set. + (sh_elf_relocate_section): Covert to LE only if the dyn_relocs + of the symbol includes the entry matched with the input_section + and having tls_tpoff32 flag on. When linking statically, set + symbol index of R_SH_TLS_TPOFF32 relocation to zero if the symbol + is defined in this executable. + (sh_elf_check_relocs): Set tls_tpoff32 flag appropriately. + +2003-02-10 Jakub Jelinek <jakub@redhat.com> + + * elf32-s390.c (elf_s390_size_dynamic_sections): Set relocs to TRUE + even if there is just non-empty .rela.plt. + +2003-02-10 Nick Clifton <nickc@redhat.com> + + * archures.c (bfd_mach_arm_ep9312): Define. + * bfd-in2.h: Regenerate. + * cpu-arm.c (processors[]): Add ep9312. + (bfd_arm_arch): Add ep9312. + * elf32-arm.h (elf32_arm_merge_private_data): Update error + messages and add test for Maverick floating point support. + (elf32_arm_print_private_bfd_data): Handle + EF_ARM_MAVERICK_FLOAT flag. + (elf32_arm_object_p): New function. + (elf_backend_object_p): Define. + +2003-02-10 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c: Rename assorted occurrences of tls_type and similar + variables, structure fields or function params to tls_mask or + similar to better reflect usage. + (struct got_entry): Comment. + (struct ppc_link_hash_entry): Expand comment, and renumber TLS_*. + (get_tls_mask): Rename from get_tls_type. + +2003-02-09 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (TLS_GD_LD): Don't define.. + (TLS_GD): ..define this instead and update all uses. + (TLS_TPRELGD): Define. + (ppc64_elf_link_hash_table_create): Tweak initialization of + init_refcount and init_offset. + (ppc64_elf_check_relocs): Add one extra element to t_symndx array. + Mark second slot of GD or LD toc entries. + (get_tls_type): Return an int. Distinguish toc GD and LD entries + from other tls types. + (ppc64_elf_tls_setup): New function, split out from.. + (ppc64_elf_tls_optimize): ..here. Don't optimize when symbols are + defined in a dynamic object. Fix LD optimization. Don't set TLS_TPREL + on GD->IE optimization, use TLS_TPRELGD instead. Use get_tls_type + return value to properly decide whether toc GD and LD entries can + optimize away __tls_get_addr call. Check next reloc after DTPMOD64 + to determine GD or LD rather than looking at TLS_LD flag. Don't + attempt to adjust got entry tls_type here.. + (allocate_dynrelocs): ..instead, adjust got entry tls_type here, and + look for possible merges. + (ppc64_elf_size_dynamic_sections): Adjust local got entries for + optimization. + (ppc64_elf_size_stubs): Tweak __tls_get_addr fudge. + (ppc64_elf_relocate_section): Rename some vars to better reflect usage. + Make use of return value from get_tls_type to properly detect GD and + LD optimizations. Split tlsld/gd hi/ha from lo/ds case. Don't + handle tls_get_addr removal when looking at REL24 relocs, do it when + looking at the previous reloc. Check reloc after DTPMOD64 to determine + GD or LD. + * elf64-ppc.h (ppc64_elf_tls_setup): Declare. + +2003-02-08 Alan Modra <amodra@bigpond.net.au> + + * elf32-hppa.c (group_sections): Don't share a stub section if + stubs are for a large section. + + * elf32-hppa.c (elf32_hppa_size_stubs): Double the size left for + stubs if !stubs_always_before_branch. + +2003-02-07 Nick Clifton <nickc@redhat.com> + + * elf.c (swap_out_syms): Generate an error message if an + equivalent output section cannot be found for a symbol. + +2003-02-07 Jakub Jelinek <jakub@redhat.com> + + * elf64-alpha.c (elf64_alpha_relax_section): Don't crash if + local_got_entries is NULL. + +2003-02-06 Andreas Schwab <schwab@suse.de> + + * elf-eh-frame.c (get_DW_EH_PE_signed): Define. + (read_value): Add parameter is_signed, use signed extraction if + the value is signed. + (_bfd_elf_write_section_eh_frame): Pass signed flag of the + encoding to read_value. + +2003-02-06 Alan Modra <amodra@bigpond.net.au> + + * elf64-ppc.c (ppc64_elf_copy_indirect_symbol): Don't copy got and + plt info when called to transfer weak sym info. + +2003-02-05 Alan Modra <amodra@bigpond.net.au> + + * reloc.c: Add PPC and PPC64 TLS relocs. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + * elf64-ppc.c (TP_OFFSET, DTP_OFFSET): Declare. + (ppc64_elf_howto_raw): Add TLS howto's. Adjust R_PPC64_NONE to be + against a 32 bit field. + (ppc64_elf_reloc_type_lookup): Handle TLS relocs. + (_ppc64_elf_section_data): Add t_symndx and comments. + (ppc64_elf_section_data): Use elf_section_data macro. + (ppc64_elf_new_section_hook): American spelling. + (struct got_entry, struct plt_entry): New. + (MUST_BE_DYN_RELOC): Rename from IS_ABSOLUTE_RELOC. + (struct ppc_stub_hash_entry): Add "addend" field. + (struct ppc_link_hash_entry): Add "tls_type". + (TLS_TLS, TLS_GD_LD, TLS_LD, TLS_TPREL, TLS_DTPREL, + TLS_EXPLICIT): Define. + (struct ppc_link_hash_table): Add tls_sec, tls_get_addr, tlsld_got. + (link_hash_newfunc): Init new fields. + (ppc64_elf_link_hash_table_create): Likewise. Set init_refcount and + init_offset to NULL. + (ppc64_elf_copy_indirect_symbol): Copy got and plt info. Don't call + _bfd_elf_link_hash_copy_indirect, rather insert relevant code from + there. + (update_local_sym_info, update_plt_info): New functions. + (ppc64_elf_check_relocs): Use them. Handle TLS relocs. Adjust GOT + handling to use got.glist rather than got.refcount. Likewise for PLT. + (ppc64_elf_gc_sweep_hook): Handle TLS relocs, new GOT and PLT lists. + (func_desc_adjust): Adjust for new PLT list. + (ppc64_elf_adjust_dynamic_symbol): Likewise. + (get_sym_h, get_tls_type): New functions. + (ppc64_elf_edit_opd): Remove unused variable. Use get_sym_h. + (ppc64_elf_tls_optimize): New function. + (allocate_dynrelocs): Adjust for new PLT and GOT lists. Allocate + TLS relocs. + (ppc64_elf_size_dynamic_sections): Likewise. + (ppc_type_of_stub): Adjust for new PLT list. + (ppc_build_one_stub): Likewise. + (ppc64_elf_size_stubs): Likewise. Use get_sym_h. Treat __tls_get_addr + calls specially. + (ppc64_elf_relocate_section): Adjust for new GOT and PLT lists. Handle + TLS relocs. Report local syms using bfd_elf_local_sym_name. Don't + init GOT entries that have a reloc. Generate GOT relocs here.. + (ppc64_elf_finish_dynamic_symbol): ..not here. Adjust for PLT list. + * elf64-ppc.h (ppc64_elf_tls_optimize): Declare. + +2003-02-04 Andreas Schwab <schwab@suse.de> + + * elf32-m68k.c (elf_m68k_hash_entry): Define. + (elf_m68k_link_hash_traverse): Remove. + (elf_m68k_link_hash_newfunc): Use struct bfd_hash_entry and + elf_m68k_hash_entry instead of struct elf_m68k_link_hash_entry to + reduce casting. + (elf_m68k_check_relocs): Use elf_m68k_hash_entry instead of + casting. + (elf_m68k_size_dynamic_sections): Use elf_link_hash_traverse + instead of elf_m68k_link_hash_traverse. + (elf_m68k_discard_copies): Change first parameter to pointer to + struct elf_link_hash_entry and use elf_m68k_hash_entry when struct + elf_m68k_link_hash_entry is needed. + +2003-02-04 Alan Modra <amodra@bigpond.net.au> + + * elf-bfd.h (struct got_entry, struct plt_entry): Forward declare. + (struct elf_link_hash_entry): Add "glist" and "plist" fields to + "got" union, and declare as gotplt_union. Use gotplt_uinion for + "plt" field. + (struct elf_link_hash_table): Make "init_refcount" a gotplt_union. + Add "init_offset" field. + (struct elf_obj_tdata <local_got>): Add "struct got_entry **" to union. + (elf_local_got_ents): Declare. + * elf.c (_bfd_elf_link_hash_newfunc): Adjust initialization of "got" + and "plt". + (_bfd_elf_link_hash_hide_symbol): Use "init_offset". + (_bfd_elf_link_hash_table_init): Set "init_offset". + * elflink.h (NAME(bfd_elf,size_dynamic_sections)): Set init_refcount + from init_offset. + (elf_adjust_dynamic_symbol): Set plt and got offsets using init_offset. + + * elf.c (bfd_elf_local_sym_name): Split out from.. + (group_signature): ..here. + * elf-bfd.h (bfd_elf_local_sym_name): Declare. + +2003-02-04 Alan Modra <amodra@bigpond.net.au> + + * elf-bfd.h (enum elf_link_info_type): Remove. + (struct bfd_elf_section_data): Move sec_info_type, use_rela_p fields + to struct sec. Remove linkonce_p field. + (elf_linkonce_p): Delete. + (elf_discarded_section): Update for sec_info_type change. + * section.c (struct sec): Add sec_info_type, use_rela_p, has_tls_reloc, + flag11, flag12, flag13, flag14, flag15, flag16, flag20, flag24. + (ELF_INFO_TYPE_NONE): Define. + (ELF_INFO_TYPE_STABS): Define. + (ELF_INFO_TYPE_MERGE): Define. + (ELF_INFO_TYPE_EH_FRAME): Define. + (ELF_INFO_TYPE_JUST_SYMS): Define. + (STD_SECTION): Update struct sec initializer. + * ecoff.c (bfd_debug_section): Likewise. + * elf.c: Likewise. Update occurrences of sec_info_type and use_rela_p. + * elflink.h: Likewise. + * elf-eh-frame.c: Likewise. + * elf64-alpha.c: Likewise. + * elfxx-ia64.c: Likewise. + * elfxx-mips.c: Likewise. + * bfd-in2.h: Regenerate. + + * elf32-sparc.c (sec_do_relax): Use elf_section_data macro rather than + referring to used_by_bfd. + * elf64-sparc.c (sec_do_relax): Likewise. + * elf64-mmix.c (mmix_elf_section_data): Likewise. + * elfxx-mips.c (mips_elf_section_data): Likewise. + * ieee.c (ieee_slurp_section_data): Use ieee_per_section macro. + (ieee_get_section_contents): Likewise. + (ieee_new_section_hook): Formatting. + (ieee_canonicalize_reloc): Remove commented out code. + * mmo.c (mmo_section_data): Define. Use throughout file. + * oasys.c (oasys_get_section_contents): Use oasys_per_section macro. + 2003-01-31 Graydon Hoare <graydon@redhat.com> * Makefile.am (opncls.lo): Add dependency upon libiberty.h. @@ -263,7 +773,7 @@ * elf64-alpha.c (alpha_dynamic_entries_for_reloc): GOTTPREL and TPREL also get a reloc if shared. Remove SREL support. (elf64_alpha_emit_dynrel): New. - (elf64_alpha_relocate_section): Use it. Resolve dynamic TPREL + (elf64_alpha_relocate_section): Use it. Resolve dynamic TPREL and GOTTPREL relocs to local symbols against the tp base. (elf64_alpha_finish_dynamic_symbol): Use elf64_alpha_emit_dynrel. @@ -275,15 +785,15 @@ 2003-01-20 Svein E. Seldal <Svein.Seldal@solidas.com> * coffcode.h (coff_set_flags): Added get/set arch hooks. - + 2003-01-20 Fabio Alemagna <falemagn@aros.org> * elf32-sh.c: Treat elfNN_bed like other macros defined in elfxx-target.h and #undef it before #define'ing it. * elf32-i386.c: Likewise. - * elf32-sh64.c: Likewise. - * elf64-alpha.c: Likewise. - * elf64-sh64.c: Likewise. + * elf32-sh64.c: Likewise. + * elf64-alpha.c: Likewise. + * elf64-sh64.c: Likewise. 2003-01-20 Martin Schwidefsky <schwidefsky@de.ibm.com> @@ -361,7 +871,7 @@ * Makefile.am (ALL_MACHINES): Use cpu-msp430.lo, not cpu-msp430.c. (BFD32_BACKENDS): Use elf32-msp430.lo, not elf32-msp430.c. * Makefile.in: Regenerate. - + 2003-01-08 Alexandre Oliva <aoliva@redhat.com> * elfn32-mips.c (prev_reloc_section): New. @@ -398,7 +908,7 @@ (bfd_archures_list): Add bfd_iq2000_arch. * configure.in: Handle bfd_elf32_iq2000_vec. * configure: Regenerate. - * reloc.c: Add BFD_RELOC_IQ2000_OFFSET_16, BFD_RELOC_IQ2000_OFFSET_21, + * reloc.c: Add BFD_RELOC_IQ2000_OFFSET_16, BFD_RELOC_IQ2000_OFFSET_21, and BFD_RELOC_IQ2000_UHI16. * targets.c (bfd_elf32_iq2000_vec): Declare. (bfd_target_vector): Add bfd_elf32_iq2000_vec. @@ -488,7 +998,7 @@ * archures.c (bfd_arch_get_compatible): Add third parameter 'accept_unknowns'. Only accept unknown format BFDs if accept_unknowns is true, or if the format is "binary". - * bfd-in2.h: Regenerate. + * bfd-in2.h: Regenerate. 2002-12-21 Nick Clifton <nickc@redhat.com> @@ -514,7 +1024,7 @@ * bfd-in2.h: Regenerate. * elf32-xstormy16.c (xstormy16_elf_howto): Add R_XSTORMY16_12. (xstormy16_reloc_map): Add R_XSTORMY16_12. - + 2002-12-19 Kazu Hirata <kazu@cs.umass.edu> * doc/bfdint.texi: Fix typos. diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 6f05319..401568f 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -877,8 +877,8 @@ corefile.lo: corefile.c $(INCDIR)/filenames.h format.lo: format.c $(INCDIR)/filenames.h init.lo: init.c $(INCDIR)/filenames.h libbfd.lo: libbfd.c $(INCDIR)/filenames.h -opncls.lo: opncls.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \ - $(INCDIR)/objalloc.h +opncls.lo: opncls.c $(INCDIR)/filenames.h $(INCDIR)/objalloc.h \ + $(INCDIR)/libiberty.h reloc.lo: reloc.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h section.lo: section.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h syms.lo: syms.c $(INCDIR)/filenames.h $(INCDIR)/safe-ctype.h \ @@ -1250,7 +1250,7 @@ elf32-pj.lo: elf32-pj.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf32-ppc.lo: elf32-ppc.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h \ - elf32-target.h + elf32-ppc.h elf32-target.h elf32-sh64.lo: elf32-sh64.c $(INCDIR)/filenames.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/../opcodes/sh64-opc.h \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index e6a600f..a05b342 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am # Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation @@ -799,7 +799,7 @@ configure.in version.h DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best SOURCES = $(libbfd_a_SOURCES) $(libbfd_la_SOURCES) OBJECTS = $(libbfd_a_OBJECTS) $(libbfd_la_OBJECTS) @@ -1410,8 +1410,8 @@ corefile.lo: corefile.c $(INCDIR)/filenames.h format.lo: format.c $(INCDIR)/filenames.h init.lo: init.c $(INCDIR)/filenames.h libbfd.lo: libbfd.c $(INCDIR)/filenames.h -opncls.lo: opncls.c $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \ - $(INCDIR)/objalloc.h +opncls.lo: opncls.c $(INCDIR)/filenames.h $(INCDIR)/objalloc.h \ + $(INCDIR)/libiberty.h reloc.lo: reloc.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h section.lo: section.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h syms.lo: syms.c $(INCDIR)/filenames.h $(INCDIR)/safe-ctype.h \ @@ -1783,7 +1783,7 @@ elf32-pj.lo: elf32-pj.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf32-ppc.lo: elf32-ppc.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h $(INCDIR)/elf/ppc.h $(INCDIR)/elf/reloc-macros.h \ - elf32-target.h + elf32-ppc.h elf32-target.h elf32-sh64.lo: elf32-sh64.c $(INCDIR)/filenames.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \ $(INCDIR)/bfdlink.h $(srcdir)/../opcodes/sh64-opc.h \ diff --git a/bfd/archures.c b/bfd/archures.c index 08015f9..62edda1 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -234,6 +234,7 @@ DESCRIPTION .#define bfd_mach_arm_5T 8 .#define bfd_mach_arm_5TE 9 .#define bfd_mach_arm_XScale 10 +.#define bfd_mach_arm_ep9312 11 . bfd_arch_ns32k, {* National Semiconductors ns32000 *} . bfd_arch_w65, {* WDC 65816 *} . bfd_arch_tic30, {* Texas Instruments TMS320C30 *} diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 3b1f9ab..917b46f 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -1,7 +1,8 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 - Free Software Foundation, Inc. + + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -68,7 +69,7 @@ extern "C" { #endif /* Forward declaration. */ -typedef struct _bfd bfd; +typedef struct bfd bfd; /* Boolean type used in bfd. Too many systems define their own versions of "boolean" for us to safely typedef a "boolean" of diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index a079599..9540eeb 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -6,9 +6,10 @@ Run "make headers" in your build bfd/ to regenerate. */ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 - Free Software Foundation, Inc. + + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -75,7 +76,7 @@ extern "C" { #endif /* Forward declaration. */ -typedef struct _bfd bfd; +typedef struct bfd bfd; /* Boolean type used in bfd. Too many systems define their own versions of "boolean" for us to safely typedef a "boolean" of @@ -1261,10 +1262,35 @@ typedef struct sec /* A mark flag used by some linker backends for garbage collection. */ unsigned int gc_mark : 1; - /* Used by the ELF code to mark sections which have been allocated - to segments. */ + /* The following flags are used by the ELF linker. */ + + /* Mark sections which have been allocated to segments. */ unsigned int segment_mark : 1; + /* Type of sec_info information. */ + unsigned int sec_info_type:3; +#define ELF_INFO_TYPE_NONE 0 +#define ELF_INFO_TYPE_STABS 1 +#define ELF_INFO_TYPE_MERGE 2 +#define ELF_INFO_TYPE_EH_FRAME 3 +#define ELF_INFO_TYPE_JUST_SYMS 4 + + /* Nonzero if this section uses RELA relocations, rather than REL. */ + unsigned int use_rela_p:1; + + /* Bits used by various backends. */ + unsigned int has_tls_reloc:1; + + /* Usused bits. */ + unsigned int flag11:1; + unsigned int flag12:1; + unsigned int flag13:1; + unsigned int flag14:1; + unsigned int flag15:1; + unsigned int flag16:4; + unsigned int flag20:4; + unsigned int flag24:8; + /* End of internal packed boolean fields. */ /* The virtual memory address of the section - where it will be @@ -1664,6 +1690,7 @@ enum bfd_architecture #define bfd_mach_arm_5T 8 #define bfd_mach_arm_5TE 9 #define bfd_mach_arm_XScale 10 +#define bfd_mach_arm_ep9312 11 bfd_arch_ns32k, /* National Semiconductors ns32000 */ bfd_arch_w65, /* WDC 65816 */ bfd_arch_tic30, /* Texas Instruments TMS320C30 */ @@ -2304,6 +2331,9 @@ to compensate for the borrow when the low bits are added. */ /* Like BFD_RELOC_LO16, but PC relative. */ BFD_RELOC_PCREL_LO16, +/* Like BFD_RELOC_16_PCREL_S2, but for MIPS Embedded PIC. */ + BFD_RELOC_MIPSEMB_16_PCREL_S2, + /* Relocation against a MIPS literal section. */ BFD_RELOC_MIPS_LITERAL, @@ -2463,6 +2493,48 @@ to compensate for the borrow when the low bits are added. */ BFD_RELOC_PPC64_PLTGOT16_DS, BFD_RELOC_PPC64_PLTGOT16_LO_DS, +/* PowerPC and PowerPC64 thread-local storage relocations. */ + BFD_RELOC_PPC_TLS, + BFD_RELOC_PPC_DTPMOD, + BFD_RELOC_PPC_TPREL16, + BFD_RELOC_PPC_TPREL16_LO, + BFD_RELOC_PPC_TPREL16_HI, + BFD_RELOC_PPC_TPREL16_HA, + BFD_RELOC_PPC_TPREL, + BFD_RELOC_PPC_DTPREL16, + BFD_RELOC_PPC_DTPREL16_LO, + BFD_RELOC_PPC_DTPREL16_HI, + BFD_RELOC_PPC_DTPREL16_HA, + BFD_RELOC_PPC_DTPREL, + BFD_RELOC_PPC_GOT_TLSGD16, + BFD_RELOC_PPC_GOT_TLSGD16_LO, + BFD_RELOC_PPC_GOT_TLSGD16_HI, + BFD_RELOC_PPC_GOT_TLSGD16_HA, + BFD_RELOC_PPC_GOT_TLSLD16, + BFD_RELOC_PPC_GOT_TLSLD16_LO, + BFD_RELOC_PPC_GOT_TLSLD16_HI, + BFD_RELOC_PPC_GOT_TLSLD16_HA, + BFD_RELOC_PPC_GOT_TPREL16, + BFD_RELOC_PPC_GOT_TPREL16_LO, + BFD_RELOC_PPC_GOT_TPREL16_HI, + BFD_RELOC_PPC_GOT_TPREL16_HA, + BFD_RELOC_PPC_GOT_DTPREL16, + BFD_RELOC_PPC_GOT_DTPREL16_LO, + BFD_RELOC_PPC_GOT_DTPREL16_HI, + BFD_RELOC_PPC_GOT_DTPREL16_HA, + BFD_RELOC_PPC64_TPREL16_DS, + BFD_RELOC_PPC64_TPREL16_LO_DS, + BFD_RELOC_PPC64_TPREL16_HIGHER, + BFD_RELOC_PPC64_TPREL16_HIGHERA, + BFD_RELOC_PPC64_TPREL16_HIGHEST, + BFD_RELOC_PPC64_TPREL16_HIGHESTA, + BFD_RELOC_PPC64_DTPREL16_DS, + BFD_RELOC_PPC64_DTPREL16_LO_DS, + BFD_RELOC_PPC64_DTPREL16_HIGHER, + BFD_RELOC_PPC64_DTPREL16_HIGHERA, + BFD_RELOC_PPC64_DTPREL16_HIGHEST, + BFD_RELOC_PPC64_DTPREL16_HIGHESTA, + /* IBM 370/390 relocations */ BFD_RELOC_I370_D12, @@ -3376,7 +3448,7 @@ typedef struct symbol_cache_entry instead, except that some symbols point to the global sections bfd_{abs,com,und}_section. This could be fixed by making these globals be per-bfd (or per-target-flavor). FIXME. */ - struct _bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ + struct bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ /* The text of the symbol. The name is left alone, and not copied; the application may not alter it. */ @@ -3537,7 +3609,7 @@ bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymb (ibfd, isymbol, obfd, osymbol)) /* Extracted from bfd.c. */ -struct _bfd +struct bfd { /* A unique identifier of the BFD */ unsigned int id; @@ -3568,7 +3640,7 @@ struct _bfd /* The caching routines use these to maintain a least-recently-used list of BFDs. */ - struct _bfd *lru_prev, *lru_next; + struct bfd *lru_prev, *lru_next; /* When a file is closed by the caching routines, BFD retains state information on the file here... */ @@ -3642,13 +3714,13 @@ struct _bfd /* Stuff only useful for archives. */ PTR arelt_data; - struct _bfd *my_archive; /* The containing archive BFD. */ - struct _bfd *next; /* The next BFD in the archive. */ - struct _bfd *archive_head; /* The first BFD in the archive. */ + struct bfd *my_archive; /* The containing archive BFD. */ + struct bfd *next; /* The next BFD in the archive. */ + struct bfd *archive_head; /* The first BFD in the archive. */ bfd_boolean has_armap; /* A chain of BFD structures involved in a link. */ - struct _bfd *link_next; + struct bfd *link_next; /* A field used by _bfd_generic_link_add_archive_symbols. This will be used only for archive elements. */ @@ -3804,33 +3876,31 @@ bfd_boolean bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags)); #define bfd_set_private_flags(abfd, flags) \ - BFD_SEND (abfd, _bfd_set_private_flags, \ - (abfd, flags)) + BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags)) #define bfd_sizeof_headers(abfd, reloc) \ - BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) + BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) #define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ - BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) + BFD_SEND (abfd, _bfd_find_nearest_line, \ + (abfd, sec, syms, off, file, func, line)) - /* Do these three do anything useful at all, for any back end? */ #define bfd_debug_info_start(abfd) \ - BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) + BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) #define bfd_debug_info_end(abfd) \ - BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) + BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) #define bfd_debug_info_accumulate(abfd, section) \ - BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) - + BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) #define bfd_stat_arch_elt(abfd, stat) \ - BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) + BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) #define bfd_update_armap_timestamp(abfd) \ - BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) + BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) #define bfd_set_arch_mach(abfd, arch, mach)\ - BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) + BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) #define bfd_relax_section(abfd, section, link_info, again) \ BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) @@ -4289,14 +4359,17 @@ const char ** bfd_target_list PARAMS ((void)); const bfd_target * -bfd_search_for_target PARAMS ((int (* search_func) (const bfd_target *, void *), void *)); +bfd_search_for_target PARAMS ((int (* search_func) + (const bfd_target *, void *), + void *)); /* Extracted from format.c. */ bfd_boolean bfd_check_format PARAMS ((bfd *abfd, bfd_format format)); bfd_boolean -bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, char ***matching)); +bfd_check_format_matches PARAMS ((bfd *abfd, bfd_format format, + char ***matching)); bfd_boolean bfd_set_format PARAMS ((bfd *abfd, bfd_format format)); @@ -1,6 +1,6 @@ /* Generic BFD library interface and support routines. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Cygnus Support. @@ -34,7 +34,7 @@ SECTION CODE_FRAGMENT . -.struct _bfd +.struct bfd .{ . {* A unique identifier of the BFD *} . unsigned int id; @@ -65,7 +65,7 @@ CODE_FRAGMENT . . {* The caching routines use these to maintain a . least-recently-used list of BFDs. *} -. struct _bfd *lru_prev, *lru_next; +. struct bfd *lru_prev, *lru_next; . . {* When a file is closed by the caching routines, BFD retains . state information on the file here... *} @@ -139,13 +139,13 @@ CODE_FRAGMENT . . {* Stuff only useful for archives. *} . PTR arelt_data; -. struct _bfd *my_archive; {* The containing archive BFD. *} -. struct _bfd *next; {* The next BFD in the archive. *} -. struct _bfd *archive_head; {* The first BFD in the archive. *} +. struct bfd *my_archive; {* The containing archive BFD. *} +. struct bfd *next; {* The next BFD in the archive. *} +. struct bfd *archive_head; {* The first BFD in the archive. *} . bfd_boolean has_armap; . . {* A chain of BFD structures involved in a link. *} -. struct _bfd *link_next; +. struct bfd *link_next; . . {* A field used by _bfd_generic_link_add_archive_symbols. This will . be used only for archive elements. *} @@ -567,7 +567,7 @@ FUNCTION bfd_get_reloc_upper_bound SYNOPSIS - long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect); + long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect); DESCRIPTION Return the number of bytes required to store the @@ -662,7 +662,7 @@ FUNCTION bfd_set_file_flags SYNOPSIS - bfd_boolean bfd_set_file_flags(bfd *abfd, flagword flags); + bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags); DESCRIPTION Set the flag word in the BFD @var{abfd} to the value @var{flags}. @@ -813,7 +813,7 @@ FUNCTION bfd_set_start_address SYNOPSIS - bfd_boolean bfd_set_start_address(bfd *abfd, bfd_vma vma); + bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma); DESCRIPTION Make @var{vma} the entry point of output BFD @var{abfd}. @@ -836,7 +836,7 @@ FUNCTION bfd_get_gp_size SYNOPSIS - unsigned int bfd_get_gp_size(bfd *abfd); + unsigned int bfd_get_gp_size (bfd *abfd); DESCRIPTION Return the maximum size of objects to be optimized using the GP @@ -863,7 +863,7 @@ FUNCTION bfd_set_gp_size SYNOPSIS - void bfd_set_gp_size(bfd *abfd, unsigned int i); + void bfd_set_gp_size (bfd *abfd, unsigned int i); DESCRIPTION Set the maximum size of objects to be optimized using the GP @@ -926,7 +926,7 @@ FUNCTION bfd_scan_vma SYNOPSIS - bfd_vma bfd_scan_vma(const char *string, const char **end, int base); + bfd_vma bfd_scan_vma (const char *string, const char **end, int base); DESCRIPTION Convert, like <<strtoul>>, a numerical expression @@ -1016,7 +1016,7 @@ FUNCTION bfd_copy_private_bfd_data SYNOPSIS - bfd_boolean bfd_copy_private_bfd_data(bfd *ibfd, bfd *obfd); + bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd); DESCRIPTION Copy private BFD information from the BFD @var{ibfd} to the @@ -1037,7 +1037,7 @@ FUNCTION bfd_merge_private_bfd_data SYNOPSIS - bfd_boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd); + bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd); DESCRIPTION Merge private BFD information from the BFD @var{ibfd} to the @@ -1058,7 +1058,7 @@ FUNCTION bfd_set_private_flags SYNOPSIS - bfd_boolean bfd_set_private_flags(bfd *abfd, flagword flags); + bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags); DESCRIPTION Set private BFD flag information in the BFD @var{abfd}. @@ -1069,43 +1069,41 @@ DESCRIPTION Not enough memory exists to create private data for @var{obfd}. .#define bfd_set_private_flags(abfd, flags) \ -. BFD_SEND (abfd, _bfd_set_private_flags, \ -. (abfd, flags)) +. BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags)) */ /* FUNCTION - stuff + Other functions DESCRIPTION - Stuff which should be documented: + The following functions exist but have not yet been documented. .#define bfd_sizeof_headers(abfd, reloc) \ -. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) +. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc)) . .#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ -. BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line)) +. BFD_SEND (abfd, _bfd_find_nearest_line, \ +. (abfd, sec, syms, off, file, func, line)) . -. {* Do these three do anything useful at all, for any back end? *} .#define bfd_debug_info_start(abfd) \ -. BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) +. BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) . .#define bfd_debug_info_end(abfd) \ -. BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) +. BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) . .#define bfd_debug_info_accumulate(abfd, section) \ -. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) -. +. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) . .#define bfd_stat_arch_elt(abfd, stat) \ -. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) +. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) . .#define bfd_update_armap_timestamp(abfd) \ -. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) +. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) . .#define bfd_set_arch_mach(abfd, arch, mach)\ -. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) +. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) . .#define bfd_relax_section(abfd, section, link_info, again) \ . BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) @@ -1265,7 +1263,7 @@ FUNCTION bfd_alt_mach_code SYNOPSIS - bfd_boolean bfd_alt_mach_code(bfd *abfd, int alternative); + bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative); DESCRIPTION diff --git a/bfd/coff-h8300.c b/bfd/coff-h8300.c index e21c5b5..2c99af1 100644 --- a/bfd/coff-h8300.c +++ b/bfd/coff-h8300.c @@ -1,6 +1,6 @@ /* BFD back-end for Hitachi H8/300 COFF binaries. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Steve Chamberlain, <sac@cygnus.com>. @@ -210,7 +210,7 @@ h8300_coff_link_hash_table_create (abfd) ret->vectors_sec = NULL; ret->funcvec_hash_table = NULL; - /* OK. Everything's intialized, return the base pointer. */ + /* OK. Everything's initialized, return the base pointer. */ return &ret->root.root; } @@ -396,13 +396,9 @@ reloc_processing (relent, reloc, symbols, abfd, section) rtype2howto (relent, reloc); if (((int) reloc->r_symndx) > 0) - { - relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx]; - } + relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx]; else - { - relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; - } + relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; relent->addend = reloc->r_offset; @@ -428,6 +424,7 @@ h8300_symbol_address_p (abfd, input_section, address) while (*s) { asymbol *p = *s; + if (p->section == input_section && (input_section->output_section->vma + input_section->output_offset @@ -472,8 +469,8 @@ h8300_reloc16_estimate (abfd, input_section, reloc, shrink, link_info) /* Only examine the relocs which might be relaxable. */ switch (reloc->howto->type) { - /* This is the 16/24 bit absolute branch which could become an 8 bit - pc-relative branch. */ + /* This is the 16/24 bit absolute branch which could become an 8 bit + pc-relative branch. */ case R_JMP1: case R_JMPL1: /* Get the address of the target of this branch. */ @@ -720,7 +717,6 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ - bfd_put_8 (abfd, gap, data + dst_address); dst_address++; src_address++; @@ -752,7 +748,6 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ - bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address); dst_address += 2; src_address += 2; @@ -773,7 +768,6 @@ h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr, { /* Everything looks OK. Apply the relocation and update the src/dst address appropriately. */ - bfd_put_8 (abfd, value & 0xff, data + dst_address); dst_address += 1; src_address += 1; diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c index f0c82a6..067f2b6 100644 --- a/bfd/coff-ppc.c +++ b/bfd/coff-ppc.c @@ -1,6 +1,6 @@ /* BFD back-end for PowerPC Microsoft Portable Executable files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Original version pieced together by Kim Knuttila (krk@cygnus.com) @@ -9,30 +9,29 @@ coff files, in particular, those for the rs/6000, alpha, mips, and intel backends, and the PE work for the arm. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ /* Current State: - objdump works - relocs generated by gas - ld will link files, but they do not run. - dlltool will not produce correct output in some .reloc cases, and will - not produce the right glue code for dll function calls. -*/ + not produce the right glue code for dll function calls. */ #include "bfd.h" #include "sysdep.h" @@ -58,15 +57,15 @@ extern bfd_boolean ppc_bfd_coff_final_link PARAMS ((bfd *, struct bfd_link_info *)); extern void dump_toc PARAMS ((PTR)); -/* The toc is a set of bfd_vma fields. We use the fact that valid */ -/* addresses are even (i.e. the bit representing "1" is off) to allow */ -/* us to encode a little extra information in the field */ -/* - Unallocated addresses are intialized to 1. */ -/* - Allocated addresses are even numbers. */ -/* The first time we actually write a reference to the toc in the bfd, */ -/* we want to record that fact in a fixup file (if it is asked for), so */ -/* we keep track of whether or not an address has been written by marking */ -/* the low order bit with a "1" upon writing */ +/* The toc is a set of bfd_vma fields. We use the fact that valid + addresses are even (i.e. the bit representing "1" is off) to allow + us to encode a little extra information in the field + - Unallocated addresses are initialized to 1. + - Allocated addresses are even numbers. + The first time we actually write a reference to the toc in the bfd, + we want to record that fact in a fixup file (if it is asked for), so + we keep track of whether or not an address has been written by marking + the low order bit with a "1" upon writing. */ #define SET_UNALLOCATED(x) ((x) = 1) #define IS_UNALLOCATED(x) ((x) == 1) @@ -75,10 +74,10 @@ extern void dump_toc PARAMS ((PTR)); #define MARK_AS_WRITTEN(x) ((x) |= 1) #define MAKE_ADDR_AGAIN(x) ((x) &= ~1) -/* Turn on this check if you suspect something amiss in the hash tables */ +/* Turn on this check if you suspect something amiss in the hash tables. */ #ifdef DEBUG_HASH -/* Need a 7 char string for an eye catcher */ +/* Need a 7 char string for an eye catcher. */ #define EYE "krkjunk" #define HASH_CHECK_DCL char eye_catcher[8]; @@ -101,17 +100,17 @@ extern void dump_toc PARAMS ((PTR)); #endif /* In order not to add an int to every hash table item for every coff - linker, we define our own hash table, derived from the coff one */ + linker, we define our own hash table, derived from the coff one. */ /* PE linker hash table entries. */ struct ppc_coff_link_hash_entry { - struct coff_link_hash_entry root; /* First entry, as required */ + struct coff_link_hash_entry root; /* First entry, as required. */ /* As we wonder around the relocs, we'll keep the assigned toc_offset - here */ - bfd_vma toc_offset; /* Our addition, as required */ + here. */ + bfd_vma toc_offset; /* Our addition, as required. */ int symbol_is_glue; unsigned long int glue_insn; @@ -122,7 +121,7 @@ struct ppc_coff_link_hash_entry struct ppc_coff_link_hash_table { - struct coff_link_hash_table root; /* First entry, as required */ + struct coff_link_hash_table root; /* First entry, as required. */ }; static struct bfd_hash_entry *ppc_coff_link_hash_newfunc @@ -172,11 +171,11 @@ ppc_coff_link_hash_newfunc (entry, table, string) if (ret) { /* Initialize the local fields. */ - SET_UNALLOCATED(ret->toc_offset); + SET_UNALLOCATED (ret->toc_offset); ret->symbol_is_glue = 0; ret->glue_insn = 0; - HASH_CHECK_INIT(ret); + HASH_CHECK_INIT (ret); } return (struct bfd_hash_entry *) ret; @@ -216,13 +215,13 @@ ppc_coff_link_hash_table_create (abfd) return &ret->root.root; } -/* Now, tailor coffcode.h to use our hash stuff */ +/* Now, tailor coffcode.h to use our hash stuff. */ #define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create -/* The nt loader points the toc register to &toc + 32768, in order to */ -/* use the complete range of a 16-bit displacement. We have to adjust */ -/* for this when we fix up loads displaced off the toc reg. */ +/* The nt loader points the toc register to &toc + 32768, in order to + use the complete range of a 16-bit displacement. We have to adjust + for this when we fix up loads displaced off the toc reg. */ #define TOC_LOAD_ADJUSTMENT (-32768) #define TOC_SECTION_NAME ".private.toc" @@ -234,7 +233,7 @@ ppc_coff_link_hash_table_create (abfd) from smaller values. Start with zero, widen, *then* decrement. */ #define MINUS_ONE (((bfd_vma)0) - 1) -/* these should definitely go in a header file somewhere... */ +/* These should definitely go in a header file somewhere... */ /* NOP */ #define IMAGE_REL_PPC_ABSOLUTE 0x0000 @@ -284,31 +283,31 @@ ppc_coff_link_hash_table_create (abfd) /* va of containing section (limited to 16 bits) */ #define IMAGE_REL_PPC_SECREL16 0x000F -/* stuff to handle immediate data when the number of bits in the */ -/* data is greater than the number of bits in the immediate field */ -/* We need to do (usually) 32 bit arithmetic on 16 bit chunks */ +/* Stuff to handle immediate data when the number of bits in the + data is greater than the number of bits in the immediate field + We need to do (usually) 32 bit arithmetic on 16 bit chunks. */ #define IMAGE_REL_PPC_REFHI 0x0010 #define IMAGE_REL_PPC_REFLO 0x0011 #define IMAGE_REL_PPC_PAIR 0x0012 -/* This is essentially the same as tocrel16, with TOCDEFN assumed */ +/* This is essentially the same as tocrel16, with TOCDEFN assumed. */ #define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 -/* Flag bits in IMAGE_RELOCATION.TYPE */ +/* Flag bits in IMAGE_RELOCATION.TYPE. */ -/* subtract reloc value rather than adding it */ +/* Subtract reloc value rather than adding it. */ #define IMAGE_REL_PPC_NEG 0x0100 -/* fix branch prediction bit to predict branch taken */ +/* Fix branch prediction bit to predict branch taken. */ #define IMAGE_REL_PPC_BRTAKEN 0x0200 -/* fix branch prediction bit to predict branch not taken */ +/* Fix branch prediction bit to predict branch not taken. */ #define IMAGE_REL_PPC_BRNTAKEN 0x0400 -/* toc slot defined in file (or, data in toc) */ +/* TOC slot defined in file (or, data in toc). */ #define IMAGE_REL_PPC_TOCDEFN 0x0800 -/* masks to isolate above values in IMAGE_RELOCATION.Type */ +/* Masks to isolate above values in IMAGE_RELOCATION.Type. */ #define IMAGE_REL_PPC_TYPEMASK 0x00FF #define IMAGE_REL_PPC_FLAGMASK 0x0F00 @@ -317,7 +316,7 @@ ppc_coff_link_hash_table_create (abfd) #define EXTRACT_JUNK(x) \ ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK)) -/* static helper functions to make relocation work */ +/* Static helper functions to make relocation work. */ /* (Work In Progress) */ static bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd, @@ -389,41 +388,36 @@ static bfd_boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto)); /* FIXME: It'll take a while to get through all of these. I only need a few to get us started, so those I'll make sure work. Those marked FIXME are either - completely unverified or have a specific unknown marked in the comment */ - -/*---------------------------------------------------------------------------*/ -/* */ -/* Relocation entries for Windows/NT on PowerPC. */ -/* */ -/* From the document "" we find the following listed as used relocs: */ -/* */ -/* ABSOLUTE : The noop */ -/* ADDR[64|32|16] : fields that hold addresses in data fields or the */ -/* 16 bit displacement field on a load/store. */ -/* ADDR[24|14] : fields that hold addresses in branch and cond */ -/* branches. These represent [26|16] bit addresses. */ -/* The low order 2 bits are preserved. */ -/* REL[24|14] : branches relative to the Instruction Address */ -/* register. These represent [26|16] bit addresses, */ -/* as before. The instruction field will be zero, and */ -/* the address of the SYM will be inserted at link time. */ -/* TOCREL16 : 16 bit displacement field referring to a slot in */ -/* toc. */ -/* TOCREL14 : 16 bit displacement field, similar to REL14 or ADDR14. */ -/* ADDR32NB : 32 bit address relative to the virtual origin. */ -/* (On the alpha, this is always a linker generated thunk)*/ -/* (i.e. 32bit addr relative to the image base) */ -/* SECREL : The value is relative to the start of the section */ -/* containing the symbol. */ -/* SECTION : access to the header containing the item. Supports the */ -/* codeview debugger. */ -/* */ -/* In particular, note that the document does not indicate that the */ -/* relocations listed in the header file are used. */ -/* */ -/* */ -/* */ -/*---------------------------------------------------------------------------*/ + completely unverified or have a specific unknown marked in the comment. */ + +/* Relocation entries for Windows/NT on PowerPC. + + From the document "" we find the following listed as used relocs: + + ABSOLUTE : The noop + ADDR[64|32|16] : fields that hold addresses in data fields or the + 16 bit displacement field on a load/store. + ADDR[24|14] : fields that hold addresses in branch and cond + branches. These represent [26|16] bit addresses. + The low order 2 bits are preserved. + REL[24|14] : branches relative to the Instruction Address + register. These represent [26|16] bit addresses, + as before. The instruction field will be zero, and + the address of the SYM will be inserted at link time. + TOCREL16 : 16 bit displacement field referring to a slot in + toc. + TOCREL14 : 16 bit displacement field, similar to REL14 or ADDR14. + ADDR32NB : 32 bit address relative to the virtual origin. + (On the alpha, this is always a linker generated thunk) + (i.e. 32bit addr relative to the image base) + SECREL : The value is relative to the start of the section + containing the symbol. + SECTION : access to the header containing the item. Supports the + codeview debugger. + + In particular, note that the document does not indicate that the + relocations listed in the header file are used. */ + static reloc_howto_type ppc_coff_howto_table[] = { @@ -767,7 +761,7 @@ static reloc_howto_type ppc_coff_howto_table[] = }; -/* Some really cheezy macros that can be turned on to test stderr :-) */ +/* Some really cheezy macros that can be turned on to test stderr :-) */ #ifdef DEBUG_RELOC #define UN_IMPL(x) \ @@ -792,16 +786,14 @@ static reloc_howto_type ppc_coff_howto_table[] = #define n_name _n._n_name #define n_zeroes _n._n_n._n_zeroes -#define n_offset _n._n_n._n_offset - -*/ +#define n_offset _n._n_n._n_offset */ -#define DUMP_RELOC2(n,r) \ -{ \ - fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", \ - n, r->r_symndx, r->r_vaddr,\ +#define DUMP_RELOC2(n,r) \ +{ \ + fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", \ + n, r->r_symndx, r->r_vaddr, \ (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \ - ?" ":" TOCDEFN" ); \ + ?" ":" TOCDEFN" ); \ } #else @@ -810,14 +802,13 @@ static reloc_howto_type ppc_coff_howto_table[] = #define DUMP_RELOC2(n,r) #endif -/* toc construction and management routines */ +/* TOC construction and management routines. */ /* This file is compiled twice, and these variables are defined in one of the compilations. FIXME: This is confusing and weird. Also, BFD should not use global variables. */ -extern bfd* bfd_of_toc_owner; +extern bfd * bfd_of_toc_owner; extern long int global_toc_size; - extern long int import_table_size; extern long int first_thunk_address; extern long int thunk_size; @@ -858,7 +849,7 @@ record_toc (toc_section, our_toc_offset, cat, name) enum ref_category cat; const char *name; { - /* add this entry to our toc addr-offset-name list */ + /* Add this entry to our toc addr-offset-name list. */ bfd_size_type amt = sizeof (struct list_ele); struct list_ele *t = (struct list_ele *) bfd_malloc (amt); @@ -889,7 +880,7 @@ static bfd_boolean ppc_record_toc_entry static void ppc_mark_symbol_as_glue PARAMS ((bfd *, int, struct internal_reloc *)); -/* record a toc offset against a symbol */ +/* Record a toc offset against a symbol. */ static bfd_boolean ppc_record_toc_entry(abfd, info, sec, sym, toc_kind) bfd *abfd; @@ -914,16 +905,19 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind) if (h == 0) { local_syms = obj_coff_local_toc_table(abfd); + if (local_syms == 0) { unsigned int i; bfd_size_type amt; + /* allocate a table */ amt = (bfd_size_type) obj_raw_syment_count (abfd) * sizeof (int); local_syms = (int *) bfd_zalloc (abfd, amt); if (local_syms == 0) return FALSE; obj_coff_local_toc_table (abfd) = local_syms; + for (i = 0; i < obj_raw_syment_count (abfd); ++i) { SET_UNALLOCATED (local_syms[i]); @@ -935,7 +929,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind) local_syms[sym] = global_toc_size; global_toc_size += 4; - /* The size must fit in a 16bit displacment */ + /* The size must fit in a 16bit displacment. */ if (global_toc_size > 65535) { (*_bfd_error_handler) (_("TOC overflow")); @@ -948,14 +942,14 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind) { name = h->root.root.root.string; - /* check to see if there's a toc slot allocated. If not, do it - here. It will be used in relocate_section */ + /* Check to see if there's a toc slot allocated. If not, do it + here. It will be used in relocate_section. */ if (IS_UNALLOCATED(h->toc_offset)) { h->toc_offset = global_toc_size; global_toc_size += 4; - /* The size must fit in a 16bit displacment */ + /* The size must fit in a 16bit displacment. */ if (global_toc_size >= 65535) { (*_bfd_error_handler) (_("TOC overflow")); @@ -968,7 +962,7 @@ ppc_record_toc_entry(abfd, info, sec, sym, toc_kind) return TRUE; } -/* record a toc offset against a symbol */ +/* Record a toc offset against a symbol. */ static void ppc_mark_symbol_as_glue(abfd, sym, rel) bfd *abfd; @@ -1013,9 +1007,9 @@ static bfd_boolean in_reloc_p(abfd, howto) #if 0 -/* this function is in charge of performing all the ppc PE relocations */ -/* Don't yet know if we want to do this this particular way ... (krk) */ -/* FIXME: (it is not yet enabled) */ +/* This function is in charge of performing all the ppc PE relocations + Don't yet know if we want to do this this particular way ... (krk). */ +/* FIXME: (it is not yet enabled). */ static bfd_reloc_status_type pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, @@ -1028,8 +1022,8 @@ pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, bfd *output_bfd; char **error_message; { - /* the consth relocation comes in two parts, we have to remember - the state between calls, in these variables */ + /* The consth relocation comes in two parts, we have to remember + the state between calls, in these variables. */ static bfd_boolean part1_consth_active = FALSE; static unsigned long part1_consth_value; @@ -1041,7 +1035,7 @@ pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, if (output_bfd) { - /* Partial linking - do nothing */ + /* Partial linking - do nothing. */ reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } @@ -1049,7 +1043,7 @@ pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, if (symbol_in != NULL && bfd_is_und_section (symbol_in->section)) { - /* Keep the state machine happy in case we're called again */ + /* Keep the state machine happy in case we're called again. */ if (r_type == IMAGE_REL_PPC_REFHI) { part1_consth_active = TRUE; @@ -1151,7 +1145,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, sec = NULL; val = 0; - /* FIXME: PAIR unsupported in the following code */ + /* FIXME: PAIR unsupported in the following code. */ if (h == NULL) { if (symndx == -1) @@ -1189,7 +1183,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, rstat = bfd_reloc_ok; - /* Each case must do its own relocation, setting rstat appropriately */ + /* Each case must do its own relocation, setting rstat appropriately. */ switch (r_type) { default: @@ -1217,16 +1211,15 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } } - /* - * Amazing bit tricks present. As we may have seen earlier, we - * use the 1 bit to tell us whether or not a toc offset has been - * allocated. Now that they've all been allocated, we will use - * the 1 bit to tell us if we've written this particular toc - * entry out. - */ + /* Amazing bit tricks present. As we may have seen earlier, we + use the 1 bit to tell us whether or not a toc offset has been + allocated. Now that they've all been allocated, we will use + the 1 bit to tell us if we've written this particular toc + entry out. */ fixit = FALSE; if (h == 0) - { /* it is a file local symbol */ + { + /* It is a file local symbol. */ int *local_toc_table; const char *name; @@ -1238,15 +1231,14 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, if (IS_WRITTEN(our_toc_offset)) { - /* if it has been written out, it is marked with the + /* If it has been written out, it is marked with the 1 bit. Fix up our offset, but do not write it out - again. - */ + again. */ MAKE_ADDR_AGAIN(our_toc_offset); } else { - /* write out the toc entry */ + /* Write out the toc entry. */ record_toc (toc_section, our_toc_offset, priv, strdup (name)); @@ -1277,13 +1269,12 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, Import Address Table is mapped immediately following the toc, some trippy library code trying for speed on dll linkage, takes advantage of that and considers - the IAT to be part of the toc, thus saving a load. - */ + the IAT to be part of the toc, thus saving a load. */ our_toc_offset = val - (toc_section->output_section->vma + toc_section->output_offset); - /* The size must still fit in a 16bit displacment */ + /* The size must still fit in a 16bit displacment. */ if ((bfd_vma) our_toc_offset >= 65535) { (*_bfd_error_handler) @@ -1297,12 +1288,11 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, record_toc (toc_section, our_toc_offset, pub, strdup (name)); } - else if (IS_WRITTEN(our_toc_offset)) + else if (IS_WRITTEN (our_toc_offset)) { - /* if it has been written out, it is marked with the + /* If it has been written out, it is marked with the 1 bit. Fix up our offset, but do not write it out - again. - */ + again. */ MAKE_ADDR_AGAIN(our_toc_offset); } else @@ -1310,13 +1300,13 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, record_toc(toc_section, our_toc_offset, pub, strdup (name)); - /* write out the toc entry */ + /* Write out the toc entry. */ bfd_put_32 (output_bfd, val, toc_section->contents + our_toc_offset); MARK_AS_WRITTEN(h->toc_offset); - /* The tricky part is that this is the address that */ - /* needs a .reloc entry for it */ + /* The tricky part is that this is the address that + needs a .reloc entry for it. */ fixit = TRUE; } } @@ -1324,22 +1314,21 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, if (fixit && info->base_file) { /* So if this is non pcrelative, and is referenced - to a section or a common symbol, then it needs a reloc */ + to a section or a common symbol, then it needs a reloc. */ - /* relocation to a symbol in a section which + /* Relocation to a symbol in a section which isn't absolute - we output the address here - to a file */ - + to a file. */ bfd_vma addr = (toc_section->output_section->vma + toc_section->output_offset + our_toc_offset); - if (coff_data(output_bfd)->pe) + if (coff_data (output_bfd)->pe) addr -= pe_data(output_bfd)->pe_opthdr.ImageBase; fwrite (&addr, 1,4, (FILE *) info->base_file); } - /* FIXME: this test is conservative */ + /* FIXME: this test is conservative. */ if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN && (bfd_vma) our_toc_offset > toc_section->_raw_size) { @@ -1351,21 +1340,21 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, return FALSE; } - /* Now we know the relocation for this toc reference */ + /* Now we know the relocation for this toc reference. */ relocation = our_toc_offset + TOC_LOAD_ADJUSTMENT; rstat = _bfd_relocate_contents (howto, input_bfd, relocation, loc); } break; case IMAGE_REL_PPC_IFGLUE: { - /* To solve this, we need to know whether or not the symbol */ - /* appearing on the call instruction is a glue function or not. */ - /* A glue function must announce itself via a IMGLUE reloc, and */ - /* the reloc contains the required toc restore instruction */ - + /* To solve this, we need to know whether or not the symbol + appearing on the call instruction is a glue function or not. + A glue function must announce itself via a IMGLUE reloc, and + the reloc contains the required toc restore instruction. */ bfd_vma x; const char *my_name; - DUMP_RELOC2(howto->name, rel); + + DUMP_RELOC2 (howto->name, rel); if (h != 0) { @@ -1379,25 +1368,24 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } break; case IMAGE_REL_PPC_SECREL: - /* Unimplemented: codeview debugging information */ + /* Unimplemented: codeview debugging information. */ /* For fast access to the header of the section containing the item. */ break; case IMAGE_REL_PPC_SECTION: - /* Unimplemented: codeview debugging information */ + /* Unimplemented: codeview debugging information. */ /* Is used to indicate that the value should be relative to the beginning of the section that contains the - symbol */ + symbol. */ break; case IMAGE_REL_PPC_ABSOLUTE: { const char *my_name; + if (h == 0) - my_name = (syms+symndx)->_n._n_name; + my_name = (syms+symndx)->_n._n_name; else - { - my_name = h->root.root.root.string; - } + my_name = h->root.root.root.string; fprintf (stderr, _("Warning: unsupported reloc %s <file %s, section %s>\n"), @@ -1413,8 +1401,9 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, case IMAGE_REL_PPC_IMGLUE: { /* There is nothing to do now. This reloc was noted in the first - pass over the relocs, and the glue instruction extracted */ + pass over the relocs, and the glue instruction extracted. */ const char *my_name; + if (h->symbol_is_glue == 1) break; my_name = h->root.root.root.string; @@ -1429,13 +1418,15 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, case IMAGE_REL_PPC_ADDR32NB: { const char *name = 0; - DUMP_RELOC2(howto->name, rel); + + DUMP_RELOC2 (howto->name, rel); if (strncmp(".idata$2",input_section->name,8) == 0 && first_thunk_address == 0) { - /* set magic values */ + /* Set magic values. */ int idata5offset; struct coff_link_hash_entry *myh; + myh = coff_link_hash_lookup (coff_hash_table (info), "__idata5_magic__", FALSE, FALSE, TRUE); @@ -1457,7 +1448,8 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } if (h == 0) - { /* it is a file local symbol */ + { + /* It is a file local symbol. */ sym = syms + symndx; name = sym->_n._n_name; } @@ -1466,11 +1458,11 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, char *target = 0; name = h->root.root.root.string; - if (strcmp(".idata$2", name) == 0) + if (strcmp (".idata$2", name) == 0) target = "__idata2_magic__"; - else if (strcmp(".idata$4", name) == 0) + else if (strcmp (".idata$4", name) == 0) target = "__idata4_magic__"; - else if (strcmp(".idata$5", name) == 0) + else if (strcmp (".idata$5", name) == 0) target = "__idata5_magic__"; if (target != 0) @@ -1514,10 +1506,10 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } rstat = _bfd_relocate_contents (howto, - input_bfd, - val - - pe_data(output_bfd)->pe_opthdr.ImageBase, - loc); + input_bfd, + val - + pe_data (output_bfd)->pe_opthdr.ImageBase, + loc); } break; @@ -1542,24 +1534,23 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, break; } - if ( info->base_file ) + if (info->base_file) { /* So if this is non pcrelative, and is referenced - to a section or a common symbol, then it needs a reloc */ - if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto)) + to a section or a common symbol, then it needs a reloc. */ + if (sym && pe_data(output_bfd)->in_reloc_p (output_bfd, howto)) { - /* relocation to a symbol in a section which + /* Relocation to a symbol in a section which isn't absolute - we output the address here - to a file */ + to a file. */ bfd_vma addr = rel->r_vaddr - input_section->vma + input_section->output_offset + input_section->output_section->vma; - if (coff_data(output_bfd)->pe) - { - addr -= pe_data(output_bfd)->pe_opthdr.ImageBase; - } + if (coff_data (output_bfd)->pe) + addr -= pe_data (output_bfd)->pe_opthdr.ImageBase; + fwrite (&addr, 1,4, (FILE *) info->base_file); } } @@ -1595,12 +1586,9 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_vaddr - input_section->vma))) - { - return FALSE; - } + return FALSE; } } - } return TRUE; @@ -1686,21 +1674,17 @@ ppc_allocate_toc_section (info) bfd_size_type amt; static char test_char = '1'; - if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */ + if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */ return TRUE; if (bfd_of_toc_owner == 0) - { - /* No toc owner? Something is very wrong. */ - abort (); - } + /* No toc owner? Something is very wrong. */ + abort (); s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME); if (s == NULL) - { - /* No toc section? Something is very wrong. */ - abort (); - } + /* No toc section? Something is very wrong. */ + abort (); amt = global_toc_size; foo = (bfd_byte *) bfd_alloc (bfd_of_toc_owner, amt); @@ -1720,58 +1704,55 @@ ppc_process_before_allocation (abfd, info) asection *sec; struct internal_reloc *i, *rel; - /* here we have a bfd that is to be included on the link. We have a hook + /* Here we have a bfd that is to be included on the link. We have a hook to do reloc rummaging, before section sizes are nailed down. */ + _bfd_coff_get_external_symbols (abfd); - _bfd_coff_get_external_symbols(abfd); - - /* rummage around all the relocs and map the toc */ + /* Rummage around all the relocs and map the toc. */ sec = abfd->sections; if (sec == 0) - { - return TRUE; - } + return TRUE; for (; sec != 0; sec = sec->next) - { - if (sec->reloc_count == 0) - continue; + { + if (sec->reloc_count == 0) + continue; - /* load the relocs */ - /* FIXME: there may be a storage leak here */ - i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0); + /* load the relocs */ + /* FIXME: there may be a storage leak here */ + i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0); - if (i == 0) - abort (); + if (i == 0) + abort (); - for (rel=i;rel<i+sec->reloc_count;++rel) - { - unsigned short r_type = EXTRACT_TYPE (rel->r_type); - unsigned short r_flags = EXTRACT_FLAGS(rel->r_type); - bfd_boolean ok = TRUE; + for (rel = i; rel < i + sec->reloc_count; ++rel) + { + unsigned short r_type = EXTRACT_TYPE (rel->r_type); + unsigned short r_flags = EXTRACT_FLAGS (rel->r_type); + bfd_boolean ok = TRUE; - DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, rel); - switch(r_type) - { - case IMAGE_REL_PPC_TOCREL16: - /* if TOCDEFN is on, ignore as someone else has allocated the - toc entry */ - if ( (r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN ) - ok = ppc_record_toc_entry(abfd, info, sec, - rel->r_symndx, default_toc); - if (!ok) - return FALSE; - break; - case IMAGE_REL_PPC_IMGLUE: - ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel); - break; - default: - break; - } - } - } + switch(r_type) + { + case IMAGE_REL_PPC_TOCREL16: + /* If TOCDEFN is on, ignore as someone else has allocated the + toc entry. */ + if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN) + ok = ppc_record_toc_entry(abfd, info, sec, + rel->r_symndx, default_toc); + if (!ok) + return FALSE; + break; + case IMAGE_REL_PPC_IMGLUE: + ppc_mark_symbol_as_glue (abfd, rel->r_symndx, rel); + break; + default: + break; + } + } + } return TRUE; } @@ -1779,13 +1760,8 @@ ppc_process_before_allocation (abfd, info) #endif static bfd_reloc_status_type -ppc_refhi_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_refhi_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1806,13 +1782,8 @@ ppc_refhi_reloc (abfd, #if 0 static bfd_reloc_status_type -ppc_reflo_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_reflo_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; @@ -1833,13 +1804,8 @@ ppc_reflo_reloc (abfd, #endif static bfd_reloc_status_type -ppc_pair_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_pair_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1858,13 +1824,8 @@ ppc_pair_reloc (abfd, } static bfd_reloc_status_type -ppc_toc16_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_toc16_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1873,33 +1834,24 @@ ppc_toc16_reloc (abfd, bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED; { - UN_IMPL("TOCREL16"); - DUMP_RELOC("TOCREL16",reloc_entry); + UN_IMPL ("TOCREL16"); + DUMP_RELOC ("TOCREL16",reloc_entry); if (output_bfd == (bfd *) NULL) - { - return bfd_reloc_continue; - } + return bfd_reloc_continue; return bfd_reloc_ok; } #if 0 -/* ADDR32NB : 32 bit address relative to the virtual origin. */ -/* (On the alpha, this is always a linker generated thunk)*/ -/* (i.e. 32bit addr relative to the image base) */ -/* */ -/* */ +/* ADDR32NB : 32 bit address relative to the virtual origin. + (On the alpha, this is always a linker generated thunk) + (i.e. 32bit addr relative to the image base). */ static bfd_reloc_status_type -ppc_addr32nb_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_addr32nb_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; @@ -1917,13 +1869,8 @@ ppc_addr32nb_reloc (abfd, #endif static bfd_reloc_status_type -ppc_secrel_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_secrel_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1942,13 +1889,8 @@ ppc_secrel_reloc (abfd, } static bfd_reloc_status_type -ppc_section_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_section_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1967,13 +1909,8 @@ ppc_section_reloc (abfd, } static bfd_reloc_status_type -ppc_imglue_reloc (abfd, - reloc_entry, - symbol, - data, - input_section, - output_bfd, - error_message) +ppc_imglue_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; @@ -1996,17 +1933,14 @@ ppc_imglue_reloc (abfd, /* FIXME: There is a possiblity that when we read in a reloc from a file, that there are some bits encoded in the upper portion of the - type field. Not yet implemented. -*/ -static void ppc_coff_rtype2howto PARAMS ((arelent *relent, - struct internal_reloc *internal)); + type field. Not yet implemented. */ +static void ppc_coff_rtype2howto PARAMS ((arelent *, struct internal_reloc *)); static void ppc_coff_rtype2howto (relent, internal) arelent *relent; struct internal_reloc *internal; { - /* We can encode one of three things in the type field, aside from the type: 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction @@ -2015,19 +1949,18 @@ ppc_coff_rtype2howto (relent, internal) the branch is expected to be taken or not. 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file For now, we just strip this stuff to find the type, and ignore it other - than that. - */ + than that. */ reloc_howto_type *howto; unsigned short r_type = EXTRACT_TYPE (internal->r_type); unsigned short r_flags = EXTRACT_FLAGS(internal->r_type); unsigned short junk = EXTRACT_JUNK (internal->r_type); - /* the masking process only slices off the bottom byte for r_type. */ + /* The masking process only slices off the bottom byte for r_type. */ if ( r_type > MAX_RELOC_INDEX ) abort (); - /* check for absolute crap */ - if ( junk != 0 ) + /* Check for absolute crap. */ + if (junk != 0) abort (); switch(r_type) @@ -2040,15 +1973,15 @@ ppc_coff_rtype2howto (relent, internal) case IMAGE_REL_PPC_ADDR32NB: case IMAGE_REL_PPC_SECTION: case IMAGE_REL_PPC_SECREL: - DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); howto = ppc_coff_howto_table + r_type; break; case IMAGE_REL_PPC_IMGLUE: - DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); howto = ppc_coff_howto_table + r_type; break; case IMAGE_REL_PPC_TOCREL16: - DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); if (r_flags & IMAGE_REL_PPC_TOCDEFN) howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN; else @@ -2064,7 +1997,6 @@ ppc_coff_rtype2howto (relent, internal) } relent->howto = howto; - } static reloc_howto_type * @@ -2086,19 +2018,18 @@ coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp) the branch is expected to be taken or not. 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file For now, we just strip this stuff to find the type, and ignore it other - than that. - */ + than that. */ - unsigned short r_type = EXTRACT_TYPE (rel->r_type); - unsigned short r_flags = EXTRACT_FLAGS(rel->r_type); - unsigned short junk = EXTRACT_JUNK (rel->r_type); + unsigned short r_type = EXTRACT_TYPE (rel->r_type); + unsigned short r_flags = EXTRACT_FLAGS (rel->r_type); + unsigned short junk = EXTRACT_JUNK (rel->r_type); - /* the masking process only slices off the bottom byte for r_type. */ - if ( r_type > MAX_RELOC_INDEX ) + /* The masking process only slices off the bottom byte for r_type. */ + if (r_type > MAX_RELOC_INDEX) abort (); - /* check for absolute crap */ - if ( junk != 0 ) + /* Check for absolute crap. */ + if (junk != 0) abort (); switch(r_type) @@ -2141,7 +2072,7 @@ coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp) return howto; } -/* a cheesy little macro to make the code a little more readable */ +/* A cheesy little macro to make the code a little more readable. */ #define HOW2MAP(bfd_rtype,ppc_rtype) \ case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype] @@ -2167,7 +2098,6 @@ ppc_coff_reloc_type_lookup (abfd, code) default: return NULL; } - /*NOTREACHED*/ } #undef HOW2MAP @@ -2229,8 +2159,7 @@ ppc_coff_reloc_type_lookup (abfd, code) 2. It's not clear to me that being the last bfd read necessarily means that you are the last bfd closed. 3. Doing it on a "swap in" hook depends on when the "swap in" is called, - and how often, etc. It's not clear to me that there isn't a hole here. -*/ + and how often, etc. It's not clear to me that there isn't a hole here. */ static void ppc_coff_swap_sym_in_hook PARAMS ((bfd *, PTR, PTR)); static void @@ -2239,21 +2168,19 @@ ppc_coff_swap_sym_in_hook (abfd, ext1, in1) PTR ext1 ATTRIBUTE_UNUSED; PTR in1; { - struct internal_syment *in = (struct internal_syment *)in1; + struct internal_syment * in = (struct internal_syment *)in1; - if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */ + if (bfd_of_toc_owner != 0) /* We already have a toc, so go home. */ return; - if (strcmp(in->_n._n_name, ".toc") == 0) + if (strcmp (in->_n._n_name, ".toc") == 0) { flagword flags; register asection *s; - s = bfd_get_section_by_name ( abfd , TOC_SECTION_NAME); + s = bfd_get_section_by_name (abfd, TOC_SECTION_NAME); if (s != NULL) - { - return; - } + return; flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ; @@ -2262,12 +2189,10 @@ ppc_coff_swap_sym_in_hook (abfd, ext1, in1) if (s == NULL || !bfd_set_section_flags (abfd, s, flags) || !bfd_set_section_alignment (abfd, s, 2)) - { - /* FIXME: set appropriate bfd error */ - abort (); - } + /* FIXME: set appropriate bfd error. */ + abort (); - /* save the bfd for later allocation */ + /* Save the bfd for later allocation. */ bfd_of_toc_owner = abfd; } @@ -2297,7 +2222,7 @@ ppc_get_last() return bfd_of_toc_owner; } -/* this piece of machinery exists only to guarantee that the bfd that holds +/* This piece of machinery exists only to guarantee that the bfd that holds the toc section is written last. This does depend on bfd_make_section attaching a new section to the @@ -2306,8 +2231,7 @@ ppc_get_last() This is otherwise intended to be functionally the same as cofflink.c:_bfd_coff_final_link(). It is specifically different only where the POWERPC_LE_PE macro modifies the code. It is left in as a - precise form of comment. krk@cygnus.com -*/ + precise form of comment. krk@cygnus.com */ /* Do the final link step. */ @@ -2382,9 +2306,9 @@ ppc_bfd_coff_final_link (abfd, info) { o->reloc_count = 0; o->lineno_count = 0; + for (p = o->link_order_head; p != NULL; p = p->next) { - if (p->type == bfd_indirect_link_order) { asection *sec; @@ -2437,8 +2361,10 @@ ppc_bfd_coff_final_link (abfd, info) amt = abfd->section_count + 1; amt *= sizeof (struct coff_link_section_info); finfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt); + if (finfo.section_info == NULL) goto error_return; + for (i = 0; i <= abfd->section_count; i++) { finfo.section_info[i].relocs = NULL; @@ -2451,6 +2377,7 @@ ppc_bfd_coff_final_link (abfd, info) line_filepos = rel_filepos; linesz = bfd_coff_linesz (abfd); max_output_reloc_count = 0; + for (o = abfd->sections; o != NULL; o = o->next) { if (o->lineno_count == 0) @@ -2605,7 +2532,6 @@ ppc_bfd_coff_final_link (abfd, info) #endif /* Free up the buffers used by _bfd_coff_link_input_bfd. */ - coff_debug_merge_hash_table_free (&finfo.debug_merge); debug_merge_allocated = FALSE; diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 7ce60db..ee50a10 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -1,24 +1,24 @@ /* Support for the generic parts of most COFF variants, for BFD. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Most of this hacked by Steve Chamberlain, @@ -225,7 +225,7 @@ SUBSUBSECTION This routine runs though the provided symbol table and uses the offsets generated by the previous pass and the pointers generated when the symbol table was read in to create the - structured hierachy required by coff. It changes each pointer + structured hierarchy required by coff. It changes each pointer to a symbol into the index into the symbol table of the asymbol. o <<coff_write_symbols>> @@ -558,15 +558,15 @@ sec_to_styp_flags (sec_name, sec_flags) /* For now, the read/write bits are mapped onto SEC_READONLY, even though the semantics don't quite match. The bits from the input - are retained in pei_section_data(abfd, section)->pe_flags */ + are retained in pei_section_data(abfd, section)->pe_flags. */ - styp_flags |= IMAGE_SCN_MEM_READ; /* always readable. */ + styp_flags |= IMAGE_SCN_MEM_READ; /* Always readable. */ if ((sec_flags & SEC_READONLY) == 0) - styp_flags |= IMAGE_SCN_MEM_WRITE; /* Invert READONLY for write */ + styp_flags |= IMAGE_SCN_MEM_WRITE; /* Invert READONLY for write. */ if (sec_flags & SEC_CODE) - styp_flags |= IMAGE_SCN_MEM_EXECUTE; /* CODE->EXECUTE */ + styp_flags |= IMAGE_SCN_MEM_EXECUTE; /* CODE->EXECUTE. */ if (sec_flags & SEC_SHARED) - styp_flags |= IMAGE_SCN_MEM_SHARED; /* Shared remains meaningful */ + styp_flags |= IMAGE_SCN_MEM_SHARED; /* Shared remains meaningful. */ return styp_flags; } @@ -693,12 +693,12 @@ styp_to_sec_flags (abfd, hdr, name, section, flags_ptr) else sec_flags |= SEC_ALLOC | SEC_LOAD; -#ifdef STYP_LIT /* A29k readonly text/data section type */ +#ifdef STYP_LIT /* A29k readonly text/data section type. */ if ((styp_flags & STYP_LIT) == STYP_LIT) sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY); #endif /* STYP_LIT */ -#ifdef STYP_OTHER_LOAD /* Other loaded sections */ +#ifdef STYP_OTHER_LOAD /* Other loaded sections. */ if (styp_flags & STYP_OTHER_LOAD) sec_flags = (SEC_LOAD | SEC_ALLOC); #endif /* STYP_SDATA */ @@ -802,7 +802,7 @@ handle_COMDAT (abfd, sec_flags, hdr, name, section) gas-generated, and look for <something> (whatever follows the $) as the comdat symbol. */ - /* All 3 branches use this */ + /* All 3 branches use this. */ symname = _bfd_coff_internal_syment_name (abfd, &isym, buf); if (symname == NULL) @@ -930,7 +930,7 @@ handle_COMDAT (abfd, sec_flags, hdr, name, section) #ifndef TARGET_UNDERSCORE #define TARGET_UNDERSCORE 0 #endif - /* Is this the name we're looking for? */ + /* Is this the name we're looking for ? */ if (strcmp (target_name, symname + (TARGET_UNDERSCORE ? 1 : 0)) != 0) { @@ -1344,7 +1344,8 @@ Special entry points for gdb to swap in coff symbol table parts: .#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\ . ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr)) .#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\ -. ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr)) +. ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook)\ +. (abfd, filehdr, aouthdr)) . .#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name, section, flags_ptr)\ . ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook)\ @@ -1369,7 +1370,8 @@ Special entry points for gdb to swap in coff symbol table parts: . ((coff_backend_info (abfd)->_bfd_coff_print_aux)\ . (abfd, file, base, symbol, aux, indaux)) . -.#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ +.#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order,\ +. reloc, data, src_ptr, dst_ptr)\ . ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ . (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) . @@ -1397,7 +1399,8 @@ Special entry points for gdb to swap in coff symbol table parts: .#define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\ . ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\ . (obfd, info, ibfd, sec, rel, adjustedp)) -.#define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\ +.#define bfd_coff_link_add_one_symbol(info, abfd, name, flags, section,\ +. value, string, cp, coll, hashp)\ . ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\ . (info, abfd, name, flags, section, value, string, cp, coll, hashp)) . @@ -1420,14 +1423,13 @@ coff_bad_format_hook (abfd, filehdr) if (BADMAG (*internal_f)) return FALSE; - /* if the optional header is NULL or not the correct size then + /* If the optional header is NULL or not the correct size then quit; the only difference I can see between m88k dgux headers (MC88DMAGIC) and Intel 960 readwrite headers (I960WRMAGIC) is that the optional header is of a different size. But the mips keeps extra stuff in it's opthdr, so dont check - when doing that - */ + when doing that. */ #if defined(M88) || defined(I960) if (internal_f->f_opthdr != 0 && bfd_coff_aoutsz (abfd) != internal_f->f_opthdr) @@ -1453,6 +1455,7 @@ coff_set_custom_section_alignment (abfd, section, alignment_table, table_size) for (i = 0; i < table_size; ++i) { const char *secname = bfd_get_section_name (abfd, section); + if (alignment_table[i].comparison_length == (unsigned int) -1 ? strcmp (alignment_table[i].name, secname) == 0 : strncmp (alignment_table[i].name, secname, @@ -1566,13 +1569,13 @@ coff_set_alignment_hook (abfd, section, scnhdr) unsigned int i; #ifdef I960 - /* Extract ALIGN from 2**ALIGN stored in section header */ + /* Extract ALIGN from 2**ALIGN stored in section header. */ for (i = 0; i < 32; i++) if ((1 << i) >= hdr->s_align) break; #endif #ifdef TIC80COFF - /* TI tools puts the alignment power in bits 8-11 */ + /* TI tools puts the alignment power in bits 8-11. */ i = (hdr->s_flags >> 8) & 0xF ; #endif #ifdef COFF_DECODE_ALIGNMENT @@ -1588,7 +1591,7 @@ coff_set_alignment_hook (abfd, section, scnhdr) #else /* ! COFF_ALIGN_IN_SECTION_HEADER */ #ifdef COFF_WITH_PE -/* a couple of macros to help setting the alignment power field */ +/* A couple of macros to help setting the alignment power field. */ #define ALIGN_SET(field,x,y) \ if (((field) & IMAGE_SCN_ALIGN_64BYTES) == x )\ {\ @@ -1649,7 +1652,7 @@ coff_set_alignment_hook (abfd, section, scnhdr) section->lma = hdr->s_vaddr; - /* check for extended relocs */ + /* Check for extended relocs. */ if (hdr->s_flags & IMAGE_SCN_LNK_NRELOC_OVFL) { struct external_reloc dst; @@ -1745,6 +1748,7 @@ coff_mkobject (abfd) #endif /* Create the COFF backend specific information. */ + #ifndef coff_mkobject_hook static PTR coff_mkobject_hook (abfd, filehdr, aouthdr) @@ -2125,7 +2129,7 @@ coff_set_arch_mach_hook (abfd, filehdr) #ifdef TICOFF0MAGIC #ifdef TICOFF_TARGET_ARCH - /* this TI COFF section should be used by all new TI COFF v0 targets */ + /* This TI COFF section should be used by all new TI COFF v0 targets. */ case TICOFF0MAGIC: arch = TICOFF_TARGET_ARCH; machine = TICOFF_TARGET_MACHINE_GET (internal_f->f_flags); @@ -2134,8 +2138,8 @@ coff_set_arch_mach_hook (abfd, filehdr) #endif #ifdef TICOFF1MAGIC - /* this TI COFF section should be used by all new TI COFF v1/2 targets */ - /* TI COFF1 and COFF2 use the target_id field to specify which arch */ + /* This TI COFF section should be used by all new TI COFF v1/2 targets. */ + /* TI COFF1 and COFF2 use the target_id field to specify which arch. */ case TICOFF1MAGIC: case TICOFF2MAGIC: switch (internal_f->f_target_id) @@ -2174,7 +2178,7 @@ coff_set_arch_mach_hook (abfd, filehdr) break; #endif - default: /* Unreadable input file type */ + default: /* Unreadable input file type. */ arch = bfd_arch_obscure; break; } @@ -2215,7 +2219,6 @@ static bfd_boolean coff_pointerize_aux_hook PARAMS ((bfd *, combined_entry_type *, combined_entry_type *, unsigned int, combined_entry_type *)); -/*ARGSUSED*/ static bfd_boolean coff_pointerize_aux_hook (abfd, table_base, symbol, indaux, aux) bfd *abfd ATTRIBUTE_UNUSED; @@ -2255,7 +2258,6 @@ static bfd_boolean coff_pointerize_aux_hook PARAMS ((bfd *, combined_entry_type *, combined_entry_type *, unsigned int, combined_entry_type *)); -/*ARGSUSED*/ static bfd_boolean coff_pointerize_aux_hook (abfd, table_base, symbol, indaux, aux) bfd *abfd ATTRIBUTE_UNUSED; @@ -2360,7 +2362,7 @@ SUBSUBSECTION static int compare_arelent_ptr PARAMS ((const PTR, const PTR)); -/* AUX's ld wants relocations to be sorted */ +/* AUX's ld wants relocations to be sorted. */ static int compare_arelent_ptr (x, y) const PTR x; @@ -2393,7 +2395,7 @@ coff_write_relocs (abfd, first_undef) p = s->orelocation; #else { - /* sort relocations before we write them out */ + /* Sort relocations before we write them out. */ bfd_size_type amt; amt = s->reloc_count; @@ -2412,10 +2414,11 @@ coff_write_relocs (abfd, first_undef) #ifdef COFF_WITH_PE if (obj_pe (abfd) && s->reloc_count >= 0xffff) { - /* encode real count here as first reloc */ + /* Encode real count here as first reloc. */ struct internal_reloc n; + memset ((PTR) & n, 0, sizeof (n)); - /* add one to count *this* reloc (grr) */ + /* Add one to count *this* reloc (grr). */ n.r_vaddr = s->reloc_count + 1; coff_swap_reloc_out (abfd, &n, &dst); if (bfd_bwrite ((PTR) & dst, (bfd_size_type) bfd_coff_relsz (abfd), @@ -2428,6 +2431,7 @@ coff_write_relocs (abfd, first_undef) { struct internal_reloc n; arelent *q = p[i]; + memset ((PTR) & n, 0, sizeof (n)); /* Now we've renumbered the symbols we know where the @@ -2445,11 +2449,13 @@ coff_write_relocs (abfd, first_undef) int j; const char *sname = q->sym_ptr_ptr[0]->name; asymbol **outsyms = abfd->outsymbols; + for (j = first_undef; outsyms[j]; j++) { const char *intable = outsyms[j]->name; + if (strcmp (intable, sname) == 0) { - /* got a hit, so repoint the reloc */ + /* Got a hit, so repoint the reloc. */ q->sym_ptr_ptr = outsyms + j; break; } @@ -2492,12 +2498,13 @@ coff_write_relocs (abfd, first_undef) #endif #ifdef SELECT_RELOC - /* Work out reloc type from what is required */ + /* Work out reloc type from what is required. */ SELECT_RELOC (n, q->howto); #else n.r_type = q->howto->type; #endif coff_swap_reloc_out (abfd, &n, &dst); + if (bfd_bwrite ((PTR) & dst, (bfd_size_type) bfd_coff_relsz (abfd), abfd) != bfd_coff_relsz (abfd)) return FALSE; @@ -2593,12 +2600,12 @@ coff_set_flags (abfd, magicp, flagsp) #ifdef TICOFF_DEFAULT_MAGIC case TICOFF_TARGET_ARCH: - /* if there's no indication of which version we want, use the default */ + /* If there's no indication of which version we want, use the default. */ if (!abfd->xvec ) *magicp = TICOFF_DEFAULT_MAGIC; else { - /* we may want to output in a different COFF version */ + /* We may want to output in a different COFF version. */ switch (abfd->xvec->name[4]) { case '0': @@ -3091,8 +3098,8 @@ coff_compute_section_file_positions (abfd) #ifdef ALIGN_SECTIONS_IN_FILE if ((abfd->flags & EXEC_P) != 0) { - /* make sure this section is aligned on the right boundary - by - padding the previous section up if necessary */ + /* Make sure this section is aligned on the right boundary - by + padding the previous section up if necessary. */ old_sofar = sofar; #ifdef RS6000COFF_C @@ -3128,9 +3135,7 @@ coff_compute_section_file_positions (abfd) } #endif if (previous != (asection *) NULL) - { - previous->_raw_size += sofar - old_sofar; - } + previous->_raw_size += sofar - old_sofar; } #endif @@ -3152,7 +3157,7 @@ coff_compute_section_file_positions (abfd) sofar += current->_raw_size; #ifdef ALIGN_SECTIONS_IN_FILE - /* make sure that this section is of the right size too */ + /* Make sure that this section is of the right size too. */ if ((abfd->flags & EXEC_P) == 0) { bfd_size_type old_size; @@ -3241,10 +3246,11 @@ coff_add_missing_symbols (abfd) { coff_symbol_type *csym = coff_symbol_from (abfd, sympp[i]); const char *name; + if (csym) { - /* only do this if there is a coff representation of the input - symbol */ + /* Only do this if there is a coff representation of the input + symbol. */ if (csym->native && csym->native->u.syment.n_sclass == C_FILE) { need_file = 0; @@ -3278,11 +3284,11 @@ coff_add_missing_symbols (abfd) if (!sympp2) return FALSE; memcpy (sympp2, sympp, i * sizeof (asymbol *)); + if (need_file) - { - /* @@ Generate fake .file symbol, in sympp2[i], and increment i. */ - abort (); - } + /* @@ Generate fake .file symbol, in sympp2[i], and increment i. */ + abort (); + if (need_text) sympp2[i++] = coff_section_symbol (abfd, _TEXT); if (need_data) @@ -3419,7 +3425,7 @@ coff_write_object_contents (abfd) bfd_set_error (bfd_error_system_call); /* Make a pass through the symbol table to count line number entries and - put them into the correct asections */ + put them into the correct asections. */ lnno_size = coff_count_linenumbers (abfd) * bfd_coff_linesz (abfd); @@ -3431,13 +3437,13 @@ coff_write_object_contents (abfd) reloc_base = obj_relocbase (abfd); - /* Work out the size of the reloc and linno areas */ + /* Work out the size of the reloc and linno areas. */ for (current = abfd->sections; current != NULL; current = current->next) { #ifdef COFF_WITH_PE - /* we store the actual reloc count in the first reloc's addr */ + /* We store the actual reloc count in the first reloc's addr. */ if (obj_pe (abfd) && current->reloc_count >= 0xffff) reloc_count ++; #endif @@ -3449,7 +3455,7 @@ coff_write_object_contents (abfd) lineno_base = reloc_base + reloc_size; sym_base = lineno_base + lnno_size; - /* Indicate in each section->line_filepos its actual file address */ + /* Indicate in each section->line_filepos its actual file address. */ for (current = abfd->sections; current != NULL; current = current->next) { @@ -3468,7 +3474,7 @@ coff_write_object_contents (abfd) current->rel_filepos = reloc_base; reloc_base += current->reloc_count * bfd_coff_relsz (abfd); #ifdef COFF_WITH_PE - /* extra reloc to hold real count */ + /* Extra reloc to hold real count. */ if (obj_pe (abfd) && current->reloc_count >= 0xffff) reloc_base += bfd_coff_relsz (abfd); #endif @@ -3564,19 +3570,14 @@ coff_write_object_contents (abfd) section.s_paddr = 0; #endif - /* - If this section has no size or is unloadable then the scnptr - will be 0 too - */ + /* If this section has no size or is unloadable then the scnptr + will be 0 too. */ if (current->_raw_size == 0 || (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0) - { - section.s_scnptr = 0; - } + section.s_scnptr = 0; else - { - section.s_scnptr = current->filepos; - } + section.s_scnptr = current->filepos; + section.s_relptr = current->rel_filepos; section.s_lnnoptr = current->line_filepos; section.s_nreloc = current->reloc_count; @@ -3606,17 +3607,11 @@ coff_write_object_contents (abfd) section.s_flags = sec_to_styp_flags (current->name, current->flags); if (!strcmp (current->name, _TEXT)) - { - text_sec = current; - } + text_sec = current; else if (!strcmp (current->name, _DATA)) - { - data_sec = current; - } + data_sec = current; else if (!strcmp (current->name, _BSS)) - { - bss_sec = current; - } + bss_sec = current; #ifdef I960 section.s_align = (current->alignment_power @@ -3624,7 +3619,7 @@ coff_write_object_contents (abfd) : 0); #endif #ifdef TIC80COFF - /* TI COFF puts the alignment power in bits 8-11 of the flags */ + /* TI COFF puts the alignment power in bits 8-11 of the flags. */ section.s_flags |= (current->alignment_power & 0xF) << 8; #endif #ifdef COFF_ENCODE_ALIGNMENT @@ -3781,14 +3776,11 @@ coff_write_object_contents (abfd) /* Don't include the internal abs section in the section count */ - /* - We will NOT put a fucking timestamp in the header here. Every time you + /* We will NOT put a fucking timestamp in the header here. Every time you put it back, I will come in and take it out again. I'm sorry. This field does not belong here. We fill it with a 0 so it compares the - same but is not a reasonable time. -- gnu@cygnus.com - */ + same but is not a reasonable time. -- gnu@cygnus.com */ internal_f.f_timdat = 0; - internal_f.f_flags = 0; if (abfd->flags & EXEC_P) @@ -3825,18 +3817,16 @@ coff_write_object_contents (abfd) #endif #ifdef TI_TARGET_ID - /* target id is used in TI COFF v1 and later; COFF0 won't use this field, - but it doesn't hurt to set it internally */ + /* Target id is used in TI COFF v1 and later; COFF0 won't use this field, + but it doesn't hurt to set it internally. */ internal_f.f_target_id = TI_TARGET_ID; #endif #ifdef TIC80_TARGET_ID internal_f.f_target_id = TIC80_TARGET_ID; #endif - /* - FIXME, should do something about the other byte orders and - architectures. - */ + /* FIXME, should do something about the other byte orders and + architectures. */ #ifdef RS6000COFF_C if ((abfd->flags & DYNAMIC) != 0) @@ -3847,11 +3837,11 @@ coff_write_object_contents (abfd) memset (&internal_a, 0, sizeof internal_a); - /* Set up architecture-dependent stuff */ - + /* Set up architecture-dependent stuff. */ { unsigned int magic = 0; unsigned short flags = 0; + coff_set_flags (abfd, &magic, &flags); internal_f.f_magic = magic; internal_f.f_flags |= flags; @@ -3860,14 +3850,13 @@ coff_write_object_contents (abfd) #ifdef A29K #ifdef ULTRA3 /* NYU's machine */ /* FIXME: This is a bogus check. I really want to see if there - * is a .shbss or a .shdata section, if so then set the magic - * number to indicate a shared data executable. - */ + is a .shbss or a .shdata section, if so then set the magic + number to indicate a shared data executable. */ if (internal_f.f_nscns >= 7) - internal_a.magic = SHMAGIC; /* Shared magic */ + internal_a.magic = SHMAGIC; /* Shared magic. */ else #endif /* ULTRA3 */ - internal_a.magic = NMAGIC; /* Assume separate i/d */ + internal_a.magic = NMAGIC; /* Assume separate i/d. */ #define __A_MAGIC_SET__ #endif /* A29K */ #ifdef TICOFF_AOUT_MAGIC @@ -3982,7 +3971,7 @@ coff_write_object_contents (abfd) /* FIXME: Does anybody ever set this to another value? */ internal_a.vstamp = 0; - /* Now should write relocs, strings, syms */ + /* Now should write relocs, strings, syms. */ obj_sym_filepos (abfd) = sym_base; if (bfd_get_symcount (abfd) != 0) @@ -4165,7 +4154,7 @@ coff_write_object_contents (abfd) if (abfd->flags & EXEC_P) { /* Note that peicode.h fills in a PEAOUTHDR, not an AOUTHDR. - include/coff/pe.h sets AOUTSZ == sizeof (PEAOUTHDR)) */ + include/coff/pe.h sets AOUTSZ == sizeof (PEAOUTHDR)). */ char * buff; bfd_size_type amount = bfd_coff_aoutsz (abfd); @@ -4214,7 +4203,7 @@ coff_set_section_contents (abfd, section, location, offset, count) file_ptr offset; bfd_size_type count; { - if (! abfd->output_has_begun) /* set by bfd.c handler */ + if (! abfd->output_has_begun) /* Set by bfd.c handler. */ { if (! coff_compute_section_file_positions (abfd)) return FALSE; @@ -4241,7 +4230,7 @@ coff_set_section_contents (abfd, section, location, offset, count) code has been tested on ISC 4.1 by me, and on SCO by Robert Lipe <robertl@arnet.com> (Thanks!). - Gvran Uddeborg <gvran@uddeborg.pp.se> */ + Gvran Uddeborg <gvran@uddeborg.pp.se>. */ if (strcmp (section->name, _LIB) == 0) { @@ -4365,6 +4354,7 @@ coff_slurp_line_table (abfd, asect) while (counter < asect->lineno_count) { struct internal_lineno dst; + bfd_coff_swap_lineno_in (abfd, src, &dst); cache_ptr->line_number = dst.l_lnno; @@ -4430,19 +4420,16 @@ coff_slurp_symbol_table (abfd) coff_symbol_type *cached_area; unsigned int *table_ptr; bfd_size_type amt; - unsigned int number_of_symbols = 0; if (obj_symbols (abfd)) return TRUE; - /* Read in the symbol table */ + /* Read in the symbol table. */ if ((native_symbols = coff_get_normalized_symtab (abfd)) == NULL) - { - return FALSE; - } /* on error */ + return FALSE; - /* Allocate enough room for all the symbols in cached form */ + /* Allocate enough room for all the symbols in cached form. */ amt = obj_raw_syment_count (abfd); amt *= sizeof (coff_symbol_type); cached_area = (coff_symbol_type *) bfd_alloc (abfd, amt); @@ -4460,6 +4447,7 @@ coff_slurp_symbol_table (abfd) coff_symbol_type *dst = cached_area; unsigned int last_native_index = obj_raw_syment_count (abfd); unsigned int this_index = 0; + while (this_index < last_native_index) { combined_entry_type *src = native_symbols + this_index; @@ -4483,8 +4471,7 @@ coff_slurp_symbol_table (abfd) dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL; dst->symbol.flags |= BSF_NOT_AT_END | BSF_FUNCTION; #endif - /* Fall through to next case */ - + /* Fall through to next case. */ #endif case C_EXT: @@ -4497,10 +4484,10 @@ coff_slurp_symbol_table (abfd) case C_HIDEXT: #endif #ifdef C_SYSTEM - case C_SYSTEM: /* System Wide variable */ + case C_SYSTEM: /* System Wide variable. */ #endif #ifdef COFF_WITH_PE - /* In PE, 0x68 (104) denotes a section symbol */ + /* In PE, 0x68 (104) denotes a section symbol. */ case C_SECTION: /* In PE, 0x69 (105) denotes a weak external symbol. */ case C_NT_WEAK: @@ -4574,16 +4561,16 @@ coff_slurp_symbol_table (abfd) break; - case C_STAT: /* static */ + case C_STAT: /* Static. */ #ifdef I960 - case C_LEAFSTAT: /* static leaf procedure */ + case C_LEAFSTAT: /* Static leaf procedure. */ #endif #if defined ARM - case C_THUMBSTAT: /* Thumb static */ - case C_THUMBLABEL: /* Thumb label */ - case C_THUMBSTATFUNC:/* Thumb static function */ + case C_THUMBSTAT: /* Thumb static. */ + case C_THUMBLABEL: /* Thumb label. */ + case C_THUMBSTATFUNC:/* Thumb static function. */ #endif - case C_LABEL: /* label */ + case C_LABEL: /* Label. */ if (src->u.syment.n_scnum == N_DEBUG) dst->symbol.flags = BSF_DEBUGGING; else @@ -4606,35 +4593,35 @@ coff_slurp_symbol_table (abfd) dst->symbol.value = src->u.syment.n_value; break; - case C_MOS: /* member of structure */ - case C_EOS: /* end of structure */ -#ifdef NOTDEF /* C_AUTOARG has the same value */ + case C_MOS: /* Member of structure. */ + case C_EOS: /* End of structure. */ +#ifdef NOTDEF /* C_AUTOARG has the same value. */ #ifdef C_GLBLREG - case C_GLBLREG: /* A29k-specific storage class */ + case C_GLBLREG: /* A29k-specific storage class. */ #endif #endif - case C_REGPARM: /* register parameter */ - case C_REG: /* register variable */ - /* C_AUTOARG conflictes with TI COFF C_UEXT */ + case C_REGPARM: /* Register parameter. */ + case C_REG: /* register variable. */ + /* C_AUTOARG conflictes with TI COFF C_UEXT. */ #if !defined (TIC80COFF) && !defined (TICOFF) #ifdef C_AUTOARG - case C_AUTOARG: /* 960-specific storage class */ + case C_AUTOARG: /* 960-specific storage class. */ #endif #endif - case C_TPDEF: /* type definition */ + case C_TPDEF: /* Type definition. */ case C_ARG: - case C_AUTO: /* automatic variable */ - case C_FIELD: /* bit field */ - case C_ENTAG: /* enumeration tag */ - case C_MOE: /* member of enumeration */ - case C_MOU: /* member of union */ - case C_UNTAG: /* union tag */ + case C_AUTO: /* Automatic variable. */ + case C_FIELD: /* Bit field. */ + case C_ENTAG: /* Enumeration tag. */ + case C_MOE: /* Member of enumeration. */ + case C_MOU: /* Member of union. */ + case C_UNTAG: /* Union tag. */ dst->symbol.flags = BSF_DEBUGGING; dst->symbol.value = (src->u.syment.n_value); break; - case C_FILE: /* file name */ - case C_STRTAG: /* structure tag */ + case C_FILE: /* File name. */ + case C_STRTAG: /* Structure tag. */ #ifdef RS6000COFF_C case C_GSYM: case C_LSYM: @@ -4654,8 +4641,8 @@ coff_slurp_symbol_table (abfd) break; #ifdef RS6000COFF_C - case C_BINCL: /* beginning of include file */ - case C_EINCL: /* ending of include file */ + case C_BINCL: /* Beginning of include file. */ + case C_EINCL: /* Ending of include file. */ /* The value is actually a pointer into the line numbers of the file. We locate the line number entry, and set the section to the section which contains it, and @@ -4696,9 +4683,9 @@ coff_slurp_symbol_table (abfd) break; #endif - case C_BLOCK: /* ".bb" or ".eb" */ - case C_FCN: /* ".bf" or ".ef" (or PE ".lf") */ - case C_EFCN: /* physical end of function */ + case C_BLOCK: /* ".bb" or ".eb". */ + case C_FCN: /* ".bf" or ".ef" (or PE ".lf"). */ + case C_EFCN: /* Physical end of function. */ #if defined COFF_WITH_PE /* PE sets the symbol to a value relative to the start of the section. */ @@ -4720,7 +4707,7 @@ coff_slurp_symbol_table (abfd) #endif break; - case C_STATLAB: /* Static load time label */ + case C_STATLAB: /* Static load time label. */ dst->symbol.value = src->u.syment.n_value; dst->symbol.flags = BSF_GLOBAL; break; @@ -4733,22 +4720,22 @@ coff_slurp_symbol_table (abfd) && src->u.syment.n_scnum == 0) break; /* Fall through. */ - case C_EXTDEF: /* external definition */ - case C_ULABEL: /* undefined label */ - case C_USTATIC: /* undefined static */ + case C_EXTDEF: /* External definition. */ + case C_ULABEL: /* Undefined label. */ + case C_USTATIC: /* Undefined static. */ #ifndef COFF_WITH_PE /* C_LINE in regular coff is 0x68. NT has taken over this storage - class to represent a section symbol */ - case C_LINE: /* line # reformatted as symbol table entry */ + class to represent a section symbol. */ + case C_LINE: /* line # reformatted as symbol table entry. */ /* NT uses 0x67 for a weak symbol, not C_ALIAS. */ - case C_ALIAS: /* duplicate tag */ + case C_ALIAS: /* Duplicate tag. */ #endif - /* New storage classes for TI COFF */ + /* New storage classes for TI COFF. */ #if defined(TIC80COFF) || defined(TICOFF) - case C_UEXT: /* Tentative external definition */ + case C_UEXT: /* Tentative external definition. */ #endif - case C_EXTLAB: /* External load time label */ - case C_HIDDEN: /* ext symbol in dmert public lib */ + case C_EXTLAB: /* External load time label. */ + case C_HIDDEN: /* Ext symbol in dmert public lib. */ default: (*_bfd_error_handler) (_("%s: Unrecognized storage class %d for %s symbol `%s'"), @@ -4768,17 +4755,18 @@ coff_slurp_symbol_table (abfd) this_index += (src->u.syment.n_numaux) + 1; dst++; number_of_symbols++; - } /* walk the native symtab */ - } /* bfdize the native symtab */ + } + } obj_symbols (abfd) = cached_area; obj_raw_syments (abfd) = native_symbols; bfd_get_symcount (abfd) = number_of_symbols; obj_convert (abfd) = table_ptr; - /* Slurp the line tables for each section too */ + /* Slurp the line tables for each section too. */ { asection *p; + p = abfd->sections; while (p) { @@ -4786,6 +4774,7 @@ coff_slurp_symbol_table (abfd) p = p->next; } } + return TRUE; } /* coff_slurp_symbol_table() */ @@ -5012,15 +5001,15 @@ coff_slurp_reloc_table (abfd, asect, symbols) refering to the symbols in the raw data have not been modified, so we have to have a negative addend to compensate. - Note that symbols which used to be common must be left alone */ + Note that symbols which used to be common must be left alone. */ - /* Calculate any reloc addend by looking at the symbol */ + /* Calculate any reloc addend by looking at the symbol. */ CALC_ADDEND (abfd, ptr, dst, cache_ptr); cache_ptr->address -= asect->vma; /* !! cache_ptr->section = (asection *) NULL;*/ - /* Fill in the cache_ptr->howto field from dst.r_type */ + /* Fill in the cache_ptr->howto field from dst.r_type. */ RTYPE2HOWTO (cache_ptr, &dst); #endif /* RELOC_PROCESSING */ @@ -5088,16 +5077,16 @@ coff_canonicalize_reloc (abfd, section, relptr, symbols) if (section->flags & SEC_CONSTRUCTOR) { - /* this section has relocs made up by us, they are not in the - file, so take them out of their chain and place them into - the data area provided */ + /* This section has relocs made up by us, they are not in the + file, so take them out of their chain and place them into + the data area provided. */ arelent_chain *chain = section->constructor_chain; + for (count = 0; count < section->reloc_count; count++) { *relptr++ = &chain->relent; chain = chain->next; } - } else { diff --git a/bfd/config.bfd b/bfd/config.bfd index 96d4765..c678496 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -189,6 +189,10 @@ case "${targ}" in targ_defvec=bfd_elf32_bigarm_vec targ_selvecs=bfd_elf32_littlearm_vec ;; + arm-*-kaos* | strongarm-*-kaos*) + targ_defvec=bfd_elf32_littlearm_vec + targ_selvecs=bfd_elf32_bigarm_vec + ;; arm-*-elf | arm-*-freebsd* | arm*-*-linux-gnu* | arm*-*-conix* | arm*-*-uclinux*) targ_defvec=bfd_elf32_littlearm_vec targ_selvecs=bfd_elf32_bigarm_vec @@ -370,6 +374,10 @@ case "${targ}" in targ_defvec=bfd_elf32_i386_vec targ_selvecs=i386coff_vec ;; + i[3456]86-*-kaos*) + targ_defvec=bfd_elf32_i386_vec + targ_selvecs=bfd_elf32_i386_vec + ;; i[3456]86-*-nto*) targ_defvec=bfd_elf32_i386_vec targ_selvecs=i386coff_vec @@ -901,6 +909,11 @@ case "${targ}" in targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec ppcboot_vec" targ64_selvecs="bfd_elf64_powerpc_vec bfd_elf64_powerpcle_vec" ;; + powerpc-*-kaos*) + targ_defvec=bfd_elf32_powerpc_vec + targ_selvecs="bfd_elf32_powerpcle_vec ppcboot_vec" + targ64_selvecs="bfd_elf64_powerpc_vec bfd_elf64_powerpcle_vec" + ;; powerpc-*-darwin* | powerpc-*-macos10* | powerpc-*-rhapsody*) targ_defvec=mach_o_be_vec targ_selvecs="mach_o_be_vec mach_o_le_vec mach_o_fat_vec pef_vec pef_xlib_vec sym_vec" @@ -1025,7 +1038,7 @@ case "${targ}" in targ_selvecs="bfd_elf32_shlnbsd_vec shcoff_vec shlcoff_vec" ;; - shl*-*-elf* | sh[1234]l*-*-elf* | sh3el*-*-elf*) + shl*-*-elf* | sh[1234]l*-*-elf* | sh3el*-*-elf* | shl*-*-kaos*) targ_defvec=bfd_elf32_shl_vec targ_selvecs="bfd_elf32_sh_vec shlcoff_vec shcoff_vec shlcoff_small_vec shcoff_small_vec" #ifdef BFD64 @@ -1033,7 +1046,7 @@ case "${targ}" in #endif targ_underscore=yes ;; - sh-*-elf* | sh[1234]*-elf* | sh-*-rtemself*) + sh-*-elf* | sh[1234]*-elf* | sh-*-rtemself* | sh-*-kaos*) targ_defvec=bfd_elf32_sh_vec targ_selvecs="bfd_elf32_shl_vec shcoff_vec shlcoff_vec shcoff_small_vec shlcoff_small_vec" #ifdef BFD64 diff --git a/bfd/cpu-arm.c b/bfd/cpu-arm.c index cd4bf14..923c250 100644 --- a/bfd/cpu-arm.c +++ b/bfd/cpu-arm.c @@ -95,7 +95,8 @@ processors[] = { bfd_mach_arm_4, "strongarm"}, { bfd_mach_arm_4, "strongarm110" }, { bfd_mach_arm_4, "strongarm1100" }, - { bfd_mach_arm_XScale, "xscale" } + { bfd_mach_arm_XScale, "xscale" }, + { bfd_mach_arm_ep9312, "ep9312" } }; static bfd_boolean @@ -140,7 +141,8 @@ static const bfd_arch_info_type arch_info_struct[] = N (bfd_mach_arm_5, "armv5", FALSE, & arch_info_struct[7]), N (bfd_mach_arm_5T, "armv5t", FALSE, & arch_info_struct[8]), N (bfd_mach_arm_5TE, "armv5te", FALSE, & arch_info_struct[9]), - N (bfd_mach_arm_XScale, "xscale", FALSE, NULL) + N (bfd_mach_arm_XScale, "xscale", FALSE, & arch_info_struct[10]), + N (bfd_mach_arm_ep9312, "ep9312", FALSE, NULL) }; const bfd_arch_info_type bfd_arm_arch = diff --git a/bfd/doc/ChangeLog b/bfd/doc/ChangeLog index 2af10b0..b133991 100644 --- a/bfd/doc/ChangeLog +++ b/bfd/doc/ChangeLog @@ -1,3 +1,10 @@ +2003-02-12 Bob Wilson <bob.wilson@acm.org> + + * bfd.texinfo: Fix quotes for texinfo. Make section title + capitalization more consistent. Use @example instead of @lisp. + Replace FDL appendix with include of fdl.texi. + * fdl.texi: New file. + 2002-11-18 Klee Dienes <kdienes@apple.com> * Makefile.am (DOCFILES): Add bfdwin.texi, bfdio.texi. @@ -172,43 +179,43 @@ Wed May 24 12:03:25 2000 Hans-Peter Nilsson <hp@axis.com> * bfdint.texi (BFD_JUMP_TABLE macros): Fix typo. -Fri Apr 7 17:54:38 2000 Andrew Cagney <cagney@b1.cygnus.com> +2000-04-07 Andrew Cagney <cagney@b1.cygnus.com> * Makefile.in: Rebuild with current autoconf/automake. -Thu Feb 4 23:21:36 1999 Ian Lance Taylor <ian@cygnus.com> +1999-02-04 Ian Lance Taylor <ian@cygnus.com> * Makefile.in: Rebuild with current autoconf/automake. -Thu Jul 23 09:36:44 1998 Nick Clifton <nickc@cygnus.com> +1998-07-23 Nick Clifton <nickc@cygnus.com> * bfdint.texi (BFD ELF processor required): Add paragraph describing the necessity to create "include/elf/CPU.h". -Thu May 7 14:45:43 1998 Ian Lance Taylor <ian@cygnus.com> +1998-05-07 Ian Lance Taylor <ian@cygnus.com> * Makefile.am (chew.o): Add -I options for intl srcdir and objdir. * Makefile.in: Rebuild. -Mon Apr 27 20:19:24 1998 Ian Lance Taylor <ian@cygnus.com> +1998-04-27 Ian Lance Taylor <ian@cygnus.com> * bfdint.texi: New file. * Makefile.am (noinst_TEXINFOS): New variable. * Makefile.in: Rebuild. -Mon Apr 13 16:48:56 1998 Ian Lance Taylor <ian@cygnus.com> +1998-04-13 Ian Lance Taylor <ian@cygnus.com> * Makefile.in: Rebuild. -Mon Apr 6 14:06:55 1998 Ian Lance Taylor <ian@cygnus.com> +1998-04-06 Ian Lance Taylor <ian@cygnus.com> * Makefile.am (STAGESTUFF): Remove variable. (CLEANFILES): Don't remove $(STAGESTUFF). (DISTCLEANFILES, MAINTAINERCLEANFILES): New variables. * Makefile.in: Rebuild. -Fri Mar 27 16:25:25 1998 Ian Lance Taylor <ian@cygnus.com> +1998-03-27 Ian Lance Taylor <ian@cygnus.com> * chew.c (skip_white_and_starts): Remove unused declaration. (skip_white_and_stars): Add casts to avoid warnings. @@ -223,12 +230,12 @@ Fri Mar 27 16:25:25 1998 Ian Lance Taylor <ian@cygnus.com> (print): Change printf format string. (main): Call usage for an unrecognized option. -Fri Feb 13 14:37:14 1998 Ian Lance Taylor <ian@cygnus.com> +1998-02-13 Ian Lance Taylor <ian@cygnus.com> * Makefile.am (AUTOMAKE_OPTIONS): Define. * Makefile.in: Rebuild. -Mon Jan 26 15:38:36 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> +1998-01-26 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * doc.str (bodytext): Don't output @* at the end. * chew.c (kill_bogus_lines): Make sure that a period at the @@ -238,45 +245,45 @@ Mon Jan 26 15:38:36 1998 Andreas Schwab <schwab@issan.informatik.uni-dortmund. * Makefile.am (s-reloc, s-syms): Depend on doc.str. * Makefile.in: Rebuild. -Wed Oct 1 14:41:28 1997 Ian Lance Taylor <ian@cygnus.com> +1997-10-01 Ian Lance Taylor <ian@cygnus.com> * Makefile.am (libbfd.h): Don't use cpu-h8300.c, cpu-i960.c, or elfcode.h as input files; they don't contribute anything. * Makefile.in: Rebuild. -Fri Aug 15 04:55:15 1997 Doug Evans <dje@canuck.cygnus.com> +1997-08-15 Doug Evans <dje@canuck.cygnus.com> * Makefile.am (libbfd.h, libcoff.h): Invoke $(MKDOC) as ./$(MKDOC). * Makefile.in: Rebuild. -Fri Aug 1 12:59:58 1997 Ian Lance Taylor <ian@cygnus.com> +1997-08-01 Ian Lance Taylor <ian@cygnus.com> * Makefile.am (CC_FOR_BUILD): Don't set explicitly. * Makefile.in: Rebuild. -Thu Jul 31 20:00:12 1997 Ian Lance Taylor <ian@cygnus.com> +1997-07-31 Ian Lance Taylor <ian@cygnus.com> * Makefile.am: New file, based on old Makefile.in. * Makefile.in: Now built with automake. -Tue Jul 22 14:44:00 1997 Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE> +1997-07-22 Robert Hoehne <robert.hoehne@Mathematik.TU-Chemnitz.DE> * Makefile.in: Change stamp-* files to s-* files. Use bfdt.texi rather than bfd.texi. (DOCFILES): Change bfd.texi to bfdt.texi. * bfd.texinfo: Include bfdt.texi, not bfd.texi. -Mon Jun 16 15:33:15 1997 Ian Lance Taylor <ian@cygnus.com> +1997-06-16 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (CC, CFLAGS): Substitute from configure script. From Jeff Makey <jeff@cts.com>. -Tue Apr 15 12:37:41 1997 Ian Lance Taylor <ian@cygnus.com> +1997-04-15 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (install-info): Use mkinstalldirs to build $(infodir). -Tue Apr 8 12:49:46 1997 Ian Lance Taylor <ian@cygnus.com> +1997-04-08 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (install-info): Permit info files to be in srcdir. (stamp-*): Add a stamp-X target for each X.texi target. @@ -285,61 +292,61 @@ Tue Apr 8 12:49:46 1997 Ian Lance Taylor <ian@cygnus.com> (distclean): Depend upon mostlyclean. Remove stamp-*. Don't remove $(DOCFILES). -Mon Apr 7 15:23:26 1997 Ian Lance Taylor <ian@cygnus.com> +1997-04-07 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (distclean): Don't remove *.info files. -Thu Feb 13 20:50:02 1997 Klaus Kaempf (kkaempf@progis.de) +1997-02-13 Klaus Kaempf (kkaempf@progis.de) * makefile.vms: New file. -Tue Jun 18 18:32:28 1996 Ian Lance Taylor <ian@cygnus.com> +1996-06-18 Ian Lance Taylor <ian@cygnus.com> * chew.c (kill_bogus_lines): Reset sl when not at the start of a line. From Uwe Ohse <uwe@tirka.gun.de>. -Tue Jan 30 14:10:46 1996 Ian Lance Taylor <ian@cygnus.com> +1996-01-30 Ian Lance Taylor <ian@cygnus.com> From Ronald F. Guilmette <rfg@monkeys.com>: * Makefile.in (libbfd.h): Depend upon proto.str. (libcoff.h, bfd.h): Likewise. -Fri Nov 3 14:46:48 1995 Fred Fish <fnf@cygnus.com> +1995-11-03 Fred Fish <fnf@cygnus.com> * Makefile.in (SRCDOC, SRCPROT, core.texi, bfd.h): Use corefile.c, renamed from core.c. -Wed Nov 1 14:28:23 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de> +1995-11-01 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de> * chew.c: Include <ctype.h>. -Fri Oct 6 16:23:34 1995 Ken Raeburn <raeburn@cygnus.com> +1995-10-06 Ken Raeburn <raeburn@cygnus.com> Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> * Makefile.in (Makefile): Only remake this Makefile. -Wed Oct 4 15:51:05 1995 Ken Raeburn <raeburn@cygnus.com> +1995-10-04 Ken Raeburn <raeburn@cygnus.com> * chew.c: Include <stdio.h>. -Tue Sep 12 18:14:50 1995 Ian Lance Taylor <ian@cygnus.com> +1995-09-12 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (maintainer-clean): New target. -Thu Aug 31 12:18:43 1995 Ian Lance Taylor <ian@cygnus.com> +1995-08-31 Ian Lance Taylor <ian@cygnus.com> * Makefile.in (bfd.h): Add additional #endif at end of bfd.h if __cplusplus is defined. -Tue Nov 29 16:13:34 1994 Doug Evans <dje@canuck.cygnus.com> +1994-11-29 Doug Evans <dje@canuck.cygnus.com> * chew.c (write_buffer): New argument `f', all callers changed. (stdout, stderr, print, drop, idrop): New forth words. * proto.str (COMMENT): New command. * doc.str (COMMENT): Likewise. -Mon Sep 12 11:44:17 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) +1994-09-12 Ian Lance Taylor (ian@sanguine.cygnus.com) * Makefile.in (DOCFILES): Remove ctor.texi. (IPROTOS): Remove ctor.ip. @@ -349,7 +356,7 @@ Mon Sep 12 11:44:17 1994 Ian Lance Taylor (ian@sanguine.cygnus.com) $(MKDOC) run on $(srcdir)/../ctor.c. * bfd.texinfo (Constructors): Remove section. -Fri Sep 2 13:33:44 1994 Ken Raeburn (raeburn@cujo.cygnus.com) +1994-09-02 Ken Raeburn (raeburn@cujo.cygnus.com) * chew.c: Include assert.h. Added prototypes for most functions. Changed most uses of int to long. Do bounds checking on the @@ -371,46 +378,46 @@ Fri Sep 2 13:33:44 1994 Ken Raeburn (raeburn@cujo.cygnus.com) * doc.str, proto.str: Handle new commands SENUM, ENUM, ENUMX, ENUMEQ, ENUMEQX, ENUMDOC. -Wed Jan 12 18:37:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) +1994-01-12 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * bfd.texinfo: Added Linker Functions node. * Makefile.in (DOCFILES): Added linker.texi. (SRCDOC): Added linker.c. (linker.texi): New target. -Tue Jan 4 10:52:56 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) +1994-01-04 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * chew.c: Don't rely on a correct declaration of exit. (chew_exit): New function which just calls exit. (main): Use it. -Mon Jan 3 11:40:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com) +1994-01-03 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * bfd.texinfo: Added Hash Tables node. * Makefile.in (DOCFILES): Added hash.texi. (SRCDOC): Added hash.c. (hash.texi): New target. -Thu Dec 30 16:57:04 1993 Ken Raeburn (raeburn@cujo.cygnus.com) +1993-12-30 Ken Raeburn (raeburn@cujo.cygnus.com) * Makefile.in: Delete all references to seclet.c, since it's just been deleted. Don't mention hash.c, linker.c, or genlink.h yet, since they don't contain documentation yet (hint, hint!). -Fri Nov 5 10:58:53 1993 David J. Mackenzie (djm@thepub.cygnus.com) +1993-11-05 David J. Mackenzie (djm@thepub.cygnus.com) * bfd.texinfo: Small cleanups. -Fri Nov 19 03:46:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) +1993-11-19 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (archures.texi): Depends on $(MKDOC). -Tue Aug 10 14:22:39 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) +1993-08-10 Ken Raeburn (raeburn@cambridge.cygnus.com) * bfd.texinfo (BFD back end): Don't include elfcode.texi, since it's empty now and that triggers a makeinfo bug. -Mon Aug 9 16:27:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) +1993-08-09 Ken Raeburn (raeburn@cambridge.cygnus.com) * bfd.texinfo (BFD back end): New section on ELF, includes elf.texi and elfcode.texi. @@ -418,74 +425,74 @@ Mon Aug 9 16:27:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) (SRCDOC): Include elfcode.h, elf.c. (elf.texi, elfcode.texi): New intermediate targets. -Thu Jun 24 13:48:13 1993 David J. Mackenzie (djm@thepub.cygnus.com) +1993-06-24 David J. Mackenzie (djm@thepub.cygnus.com) * Makefile.in (.c.o, chew.o): Put CFLAGS last. * bfdsumm.texi: New file, broken out of bfd.texinfo, to share with ld.texinfo. -Mon Jun 14 12:07:07 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com) +1993-06-14 david d `zoo' zuhn (zoo at rtl.cygnus.com) * Makefile.in (install-info): remove parentdir cruft, -Wed Jun 9 16:00:32 1993 Jim Kingdon (kingdon@cygnus.com) +1993-06-09 Jim Kingdon (kingdon@cygnus.com) * Makefile.in (mostlyclean): Remove chew.o. -Tue May 25 14:46:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com) +1993-05-25 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (libbfd.h): Use elfcode.h, not elf32.c. -Mon May 24 15:50:07 1993 Ken Raeburn (raeburn@cygnus.com) +1993-05-24 Ken Raeburn (raeburn@cygnus.com) * chew.c (compile): Add a couple of missing casts. -Wed May 12 14:45:14 1993 Ian Lance Taylor (ian@cygnus.com) +1993-05-12 Ian Lance Taylor (ian@cygnus.com) * Makefile.in (CC_FOR_BUILD): New variable, define to be $(CC). (chew.o, $(MKDOC)): Build using CC_FOR_BUILD rather than CC, since it must run on the build machine. -Tue Apr 6 22:38:10 1993 John Gilmore (gnu@cygnus.com) +1993-04-07 John Gilmore (gnu@cygnus.com) * Makefile.in (chew): Don't compile from .c to executable in a single step; it puts a temporary .o filename into the executable, which makes multi-stage comparisons fail. Compile chew.c to chew.o, and link that, which makes identical executables every time. -Wed Mar 24 17:26:29 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com) +1993-03-24 david d `zoo' zuhn (zoo at poseidon.cygnus.com) * Makefile.in: fix typo (bfd.texinfo not bfd.texino) -Fri Mar 19 01:13:00 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com) +1993-03-19 Ken Raeburn (raeburn@kr-pc.cygnus.com) * bfd.texinfo: Since BFD version number has been bumped, do same to "version number" on title page, and elsewhere. Should be fixed to extract real version number. -Tue Mar 16 12:15:13 1993 Per Bothner (bothner@rtl.cygnus.com) +1993-03-16 Per Bothner (bothner@rtl.cygnus.com) * Makefile.in: Add *clean rules. -Mon Jan 11 18:43:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com) +1993-01-11 Ian Lance Taylor (ian@tweedledumb.cygnus.com) * Makefile.in (libbfd.h): Removed duplicate init.c and libbfd.c. Added seclet.c. (bfd.h): Added dependency on bfd.c and seclet.c. Added seclet.c to build. -Thu Dec 17 19:35:43 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com) +1992-12-17 david d `zoo' zuhn (zoo at cirdan.cygnus.com) * Makefile.in: added dvi target, define and use $(TEXI2DVI) -Thu Dec 3 17:42:48 1992 Ken Raeburn (raeburn@cambridge.cygnus.com) +1992-12-03 Ken Raeburn (raeburn@cambridge.cygnus.com) * Makefile.in (TEXIDIR): New variable. (bfd.dvi): Look for bfd.texinfo in $(srcdir). Generate index. * bfd.texinfo: Minor doc fixes. -Thu Nov 5 03:13:55 1992 John Gilmore (gnu@cygnus.com) +1992-11-05 John Gilmore (gnu@cygnus.com) Cleanup: Replace all uses of EXFUN in the BFD sources, with PARAMS. @@ -493,70 +500,70 @@ Thu Nov 5 03:13:55 1992 John Gilmore (gnu@cygnus.com) (paramstuff): Replace exfunstuff with function to generate PARAMS. * proto.str: Use paramstuff rather than exfunstuff. -Mon Aug 17 12:40:32 1992 Steve Chamberlain (sac@thepub.cygnus.com) +1992-08-17 Steve Chamberlain (sac@thepub.cygnus.com) * chew.c: various patches provided by Howard Chu. -Fri Jun 19 18:59:54 1992 John Gilmore (gnu at cygnus.com) +1992-06-19 John Gilmore (gnu at cygnus.com) * Makefile.in (libbfd.h): Add elf.c as a source of prototypes. -Mon May 11 18:55:59 1992 John Gilmore (gnu at cygnus.com) +1992-05-11 John Gilmore (gnu at cygnus.com) * chew.c: exit() should be declared by config files, not by portable source code. Its type could be int or void function. -Mon May 4 13:45:57 1992 K. Richard Pixley (rich@rtl.cygnus.com) +1992-05-04 K. Richard Pixley (rich@rtl.cygnus.com) * Makefile.in: another CFLAGS correction. -Tue Apr 28 10:21:32 1992 K. Richard Pixley (rich@rtl.cygnus.com) +1992-04-28 K. Richard Pixley (rich@rtl.cygnus.com) * Makefile.in: Do the CFLAGS thing. -Fri Apr 10 22:34:52 1992 Fred Fish (fnf@cygnus.com) +1992-04-11 Fred Fish (fnf@cygnus.com) * Makefile.in (MINUS_G): Add macro and default to -g. -Fri Mar 6 18:53:18 1992 Steve Chamberlain (sac@thepub.cygnus.com) +1992-03-06 Steve Chamberlain (sac@thepub.cygnus.com) * chew.c: now has -w switch turn on warnings -Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com) +1992-02-26 K. Richard Pixley (rich@cygnus.com) * Makefile.in, configure.in: removed traces of namesubdir, -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced copyrights to '92, changed some from Cygnus to FSF. -Tue Dec 10 22:11:05 1991 K. Richard Pixley (rich at rtl.cygnus.com) +1991-12-10 K. Richard Pixley (rich at rtl.cygnus.com) * Makefile.in: build chew into the current directory. Complete the MKDOC macro transition. -Tue Dec 10 08:26:28 1991 Steve Chamberlain (sac at rtl.cygnus.com) +1991-12-10 Steve Chamberlain (sac at rtl.cygnus.com) * chew.c: don't core dump when can't open file * Makefile.in: get proto.str from the right place when built in odd directories -Tue Dec 10 04:07:25 1991 K. Richard Pixley (rich at rtl.cygnus.com) +1991-12-10 K. Richard Pixley (rich at rtl.cygnus.com) * Makefile.in: infodir belongs in datadir. -Sat Dec 7 17:01:23 1991 Steve Chamberlain (sac at rtl.cygnus.com) +1991-12-07 Steve Chamberlain (sac at rtl.cygnus.com) * chew.c: Much modified * proto.str, doc.str: New files for extracting to product prototypes and documents respectively. -Fri Dec 6 22:57:12 1991 K. Richard Pixley (rich at rtl.cygnus.com) +1991-12-06 K. Richard Pixley (rich at rtl.cygnus.com) * Makefile.in: added standards.text support, host/site/target inclusion hooks, install using INSTALL_DATA rather than cp, don't echo on install. -Thu Dec 5 22:46:17 1991 K. Richard Pixley (rich at rtl.cygnus.com) +1991-12-05 K. Richard Pixley (rich at rtl.cygnus.com) * Makefile.in: idestdir and ddestdir go away. Added copyrights and shift gpl to v2. Added ChangeLog if it didn't exist. docdir diff --git a/bfd/doc/bfd.texinfo b/bfd/doc/bfd.texinfo index f12222e..d6a427f 100644 --- a/bfd/doc/bfd.texinfo +++ b/bfd/doc/bfd.texinfo @@ -1,6 +1,6 @@ \input texinfo.tex @setfilename bfd.info -@c Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 2000 +@c Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1997, 2000, 2003 @c Free Software Foundation, Inc. @c @tex @@ -30,14 +30,14 @@ END-INFO-DIR-ENTRY @ifinfo This file documents the BFD library. -Copyright (C) 1991, 2000, 2001 Free Software Foundation, Inc. +Copyright (C) 1991, 2000, 2001, 2003 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the - section entitled "GNU Free Documentation License". + section entitled ``GNU Free Documentation License''. @ignore Permission is granted to process this file through Tex and print the @@ -75,14 +75,14 @@ notice identical to this one except for the removal of this paragraph @end tex @vskip 0pt plus 1filll -Copyright @copyright{} 1991, 2001 Free Software Foundation, Inc. +Copyright @copyright{} 1991, 2001, 2003 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the - section entitled "GNU Free Documentation License". + section entitled ``GNU Free Documentation License''. @end titlepage @end iftex @@ -170,17 +170,17 @@ For example, this sequence does what you would probably expect: return the number of sections in an object file attached to a BFD @code{abfd}. -@lisp +@example @c @cartouche #include "bfd.h" -unsigned int number_of_sections(abfd) +unsigned int number_of_sections (abfd) bfd *abfd; @{ - return bfd_count_sections(abfd); + return bfd_count_sections (abfd); @} @c @end cartouche -@end lisp +@end example The abstraction used within BFD is that an object file has: @@ -205,7 +205,7 @@ IEEE-695. @include bfdsumm.texi @node BFD front end, BFD back ends, Overview, Top -@chapter BFD front end +@chapter BFD Front End @include bfdt.texi @include bfdio.texi @@ -228,7 +228,7 @@ IEEE-695. @end menu @node Memory Usage, Initialization, BFD front end, BFD front end -@section Memory usage +@section Memory Usage BFD keeps all of its internal structures in obstacks. There is one obstack per open BFD file, into which the current state is stored. When a BFD is closed, the obstack is deleted, and so everything which has been @@ -324,370 +324,9 @@ All of BFD lives in one directory. @include mmo.texi @node GNU Free Documentation License, Index, BFD back ends, Top -@chapter GNU Free Documentation License -@cindex GNU Free Documentation License - - GNU Free Documentation License - - Version 1.1, March 2000 - - Copyright (C) 2000 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - -0. PREAMBLE - -The purpose of this License is to make a manual, textbook, or other -written document "free" in the sense of freedom: to assure everyone -the effective freedom to copy and redistribute it, with or without -modifying it, either commercially or noncommercially. Secondarily, -this License preserves for the author and publisher a way to get -credit for their work, while not being considered responsible for -modifications made by others. - -This License is a kind of "copyleft", which means that derivative -works of the document must themselves be free in the same sense. It -complements the GNU General Public License, which is a copyleft -license designed for free software. - -We have designed this License in order to use it for manuals for free -software, because free software needs free documentation: a free -program should come with manuals providing the same freedoms that the -software does. But this License is not limited to software manuals; -it can be used for any textual work, regardless of subject matter or -whether it is published as a printed book. We recommend this License -principally for works whose purpose is instruction or reference. - - -1. APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work that contains a -notice placed by the copyright holder saying it can be distributed -under the terms of this License. The "Document", below, refers to any -such manual or work. Any member of the public is a licensee, and is -addressed as "you". - -A "Modified Version" of the Document means any work containing the -Document or a portion of it, either copied verbatim, or with -modifications and/or translated into another language. - -A "Secondary Section" is a named appendix or a front-matter section of -the Document that deals exclusively with the relationship of the -publishers or authors of the Document to the Document's overall subject -(or to related matters) and contains nothing that could fall directly -within that overall subject. (For example, if the Document is in part a -textbook of mathematics, a Secondary Section may not explain any -mathematics.) The relationship could be a matter of historical -connection with the subject or with related matters, or of legal, -commercial, philosophical, ethical or political position regarding -them. - -The "Invariant Sections" are certain Secondary Sections whose titles -are designated, as being those of Invariant Sections, in the notice -that says that the Document is released under this License. - -The "Cover Texts" are certain short passages of text that are listed, -as Front-Cover Texts or Back-Cover Texts, in the notice that says that -the Document is released under this License. - -A "Transparent" copy of the Document means a machine-readable copy, -represented in a format whose specification is available to the -general public, whose contents can be viewed and edited directly and -straightforwardly with generic text editors or (for images composed of -pixels) generic paint programs or (for drawings) some widely available -drawing editor, and that is suitable for input to text formatters or -for automatic translation to a variety of formats suitable for input -to text formatters. A copy made in an otherwise Transparent file -format whose markup has been designed to thwart or discourage -subsequent modification by readers is not Transparent. A copy that is -not "Transparent" is called "Opaque". - -Examples of suitable formats for Transparent copies include plain -ASCII without markup, Texinfo input format, LaTeX input format, SGML -or XML using a publicly available DTD, and standard-conforming simple -HTML designed for human modification. Opaque formats include -PostScript, PDF, proprietary formats that can be read and edited only -by proprietary word processors, SGML or XML for which the DTD and/or -processing tools are not generally available, and the -machine-generated HTML produced by some word processors for output -purposes only. - -The "Title Page" means, for a printed book, the title page itself, -plus such following pages as are needed to hold, legibly, the material -this License requires to appear in the title page. For works in -formats which do not have any title page as such, "Title Page" means -the text near the most prominent appearance of the work's title, -preceding the beginning of the body of the text. - - -2. VERBATIM COPYING - -You may copy and distribute the Document in any medium, either -commercially or noncommercially, provided that this License, the -copyright notices, and the license notice saying this License applies -to the Document are reproduced in all copies, and that you add no other -conditions whatsoever to those of this License. You may not use -technical measures to obstruct or control the reading or further -copying of the copies you make or distribute. However, you may accept -compensation in exchange for copies. If you distribute a large enough -number of copies you must also follow the conditions in section 3. - -You may also lend copies, under the same conditions stated above, and -you may publicly display copies. - - -3. COPYING IN QUANTITY - -If you publish printed copies of the Document numbering more than 100, -and the Document's license notice requires Cover Texts, you must enclose -the copies in covers that carry, clearly and legibly, all these Cover -Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on -the back cover. Both covers must also clearly and legibly identify -you as the publisher of these copies. The front cover must present -the full title with all words of the title equally prominent and -visible. You may add other material on the covers in addition. -Copying with changes limited to the covers, as long as they preserve -the title of the Document and satisfy these conditions, can be treated -as verbatim copying in other respects. - -If the required texts for either cover are too voluminous to fit -legibly, you should put the first ones listed (as many as fit -reasonably) on the actual cover, and continue the rest onto adjacent -pages. - -If you publish or distribute Opaque copies of the Document numbering -more than 100, you must either include a machine-readable Transparent -copy along with each Opaque copy, or state in or with each Opaque copy -a publicly-accessible computer-network location containing a complete -Transparent copy of the Document, free of added material, which the -general network-using public has access to download anonymously at no -charge using public-standard network protocols. If you use the latter -option, you must take reasonably prudent steps, when you begin -distribution of Opaque copies in quantity, to ensure that this -Transparent copy will remain thus accessible at the stated location -until at least one year after the last time you distribute an Opaque -copy (directly or through your agents or retailers) of that edition to -the public. - -It is requested, but not required, that you contact the authors of the -Document well before redistributing any large number of copies, to give -them a chance to provide you with an updated version of the Document. - - -4. MODIFICATIONS - -You may copy and distribute a Modified Version of the Document under -the conditions of sections 2 and 3 above, provided that you release -the Modified Version under precisely this License, with the Modified -Version filling the role of the Document, thus licensing distribution -and modification of the Modified Version to whoever possesses a copy -of it. In addition, you must do these things in the Modified Version: - -A. Use in the Title Page (and on the covers, if any) a title distinct - from that of the Document, and from those of previous versions - (which should, if there were any, be listed in the History section - of the Document). You may use the same title as a previous version - if the original publisher of that version gives permission. -B. List on the Title Page, as authors, one or more persons or entities - responsible for authorship of the modifications in the Modified - Version, together with at least five of the principal authors of the - Document (all of its principal authors, if it has less than five). -C. State on the Title page the name of the publisher of the - Modified Version, as the publisher. -D. Preserve all the copyright notices of the Document. -E. Add an appropriate copyright notice for your modifications - adjacent to the other copyright notices. -F. Include, immediately after the copyright notices, a license notice - giving the public permission to use the Modified Version under the - terms of this License, in the form shown in the Addendum below. -G. Preserve in that license notice the full lists of Invariant Sections - and required Cover Texts given in the Document's license notice. -H. Include an unaltered copy of this License. -I. Preserve the section entitled "History", and its title, and add to - it an item stating at least the title, year, new authors, and - publisher of the Modified Version as given on the Title Page. If - there is no section entitled "History" in the Document, create one - stating the title, year, authors, and publisher of the Document as - given on its Title Page, then add an item describing the Modified - Version as stated in the previous sentence. -J. Preserve the network location, if any, given in the Document for - public access to a Transparent copy of the Document, and likewise - the network locations given in the Document for previous versions - it was based on. These may be placed in the "History" section. - You may omit a network location for a work that was published at - least four years before the Document itself, or if the original - publisher of the version it refers to gives permission. -K. In any section entitled "Acknowledgements" or "Dedications", - preserve the section's title, and preserve in the section all the - substance and tone of each of the contributor acknowledgements - and/or dedications given therein. -L. Preserve all the Invariant Sections of the Document, - unaltered in their text and in their titles. Section numbers - or the equivalent are not considered part of the section titles. -M. Delete any section entitled "Endorsements". Such a section - may not be included in the Modified Version. -N. Do not retitle any existing section as "Endorsements" - or to conflict in title with any Invariant Section. - -If the Modified Version includes new front-matter sections or -appendices that qualify as Secondary Sections and contain no material -copied from the Document, you may at your option designate some or all -of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. -These titles must be distinct from any other section titles. - -You may add a section entitled "Endorsements", provided it contains -nothing but endorsements of your Modified Version by various -parties--for example, statements of peer review or that the text has -been approved by an organization as the authoritative definition of a -standard. - -You may add a passage of up to five words as a Front-Cover Text, and a -passage of up to 25 words as a Back-Cover Text, to the end of the list -of Cover Texts in the Modified Version. Only one passage of -Front-Cover Text and one of Back-Cover Text may be added by (or -through arrangements made by) any one entity. If the Document already -includes a cover text for the same cover, previously added by you or -by arrangement made by the same entity you are acting on behalf of, -you may not add another; but you may replace the old one, on explicit -permission from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this License -give permission to use their names for publicity for or to assert or -imply endorsement of any Modified Version. - - -5. COMBINING DOCUMENTS - -You may combine the Document with other documents released under this -License, under the terms defined in section 4 above for modified -versions, provided that you include in the combination all of the -Invariant Sections of all of the original documents, unmodified, and -list them all as Invariant Sections of your combined work in its -license notice. - -The combined work need only contain one copy of this License, and -multiple identical Invariant Sections may be replaced with a single -copy. If there are multiple Invariant Sections with the same name but -different contents, make the title of each such section unique by -adding at the end of it, in parentheses, the name of the original -author or publisher of that section if known, or else a unique number. -Make the same adjustment to the section titles in the list of -Invariant Sections in the license notice of the combined work. - -In the combination, you must combine any sections entitled "History" -in the various original documents, forming one section entitled -"History"; likewise combine any sections entitled "Acknowledgements", -and any sections entitled "Dedications". You must delete all sections -entitled "Endorsements." - - -6. COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other documents -released under this License, and replace the individual copies of this -License in the various documents with a single copy that is included in -the collection, provided that you follow the rules of this License for -verbatim copying of each of the documents in all other respects. - -You may extract a single document from such a collection, and distribute -it individually under this License, provided you insert a copy of this -License into the extracted document, and follow this License in all -other respects regarding verbatim copying of that document. - - -7. AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other separate -and independent documents or works, in or on a volume of a storage or -distribution medium, does not as a whole count as a Modified Version -of the Document, provided no compilation copyright is claimed for the -compilation. Such a compilation is called an "aggregate", and this -License does not apply to the other self-contained works thus compiled -with the Document, on account of their being thus compiled, if they -are not themselves derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these -copies of the Document, then if the Document is less than one quarter -of the entire aggregate, the Document's Cover Texts may be placed on -covers that surround only the Document within the aggregate. -Otherwise they must appear on covers around the whole aggregate. - - -8. TRANSLATION - -Translation is considered a kind of modification, so you may -distribute translations of the Document under the terms of section 4. -Replacing Invariant Sections with translations requires special -permission from their copyright holders, but you may include -translations of some or all Invariant Sections in addition to the -original versions of these Invariant Sections. You may include a -translation of this License provided that you also include the -original English version of this License. In case of a disagreement -between the translation and the original English version of this -License, the original English version will prevail. - - -9. TERMINATION - -You may not copy, modify, sublicense, or distribute the Document except -as expressly provided for under this License. Any other attempt to -copy, modify, sublicense or distribute the Document is void, and will -automatically terminate your rights under this License. However, -parties who have received copies, or rights, from you under this -License will not have their licenses terminated so long as such -parties remain in full compliance. - - -10. FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions -of the GNU Free Documentation License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. See -http://www.gnu.org/copyleft/. - -Each version of the License is given a distinguishing version number. -If the Document specifies that a particular numbered version of this -License "or any later version" applies to it, you have the option of -following the terms and conditions either of that specified version or -of any later version that has been published (not as a draft) by the -Free Software Foundation. If the Document does not specify a version -number of this License, you may choose any version ever published (not -as a draft) by the Free Software Foundation. - - -ADDENDUM: How to use this License for your documents - -To use this License in a document you have written, include a copy of -the License in the document and put the following copyright and -license notices just after the title page: - -@smallexample - Copyright (c) YEAR YOUR NAME. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.1 - or any later version published by the Free Software Foundation; - with the Invariant Sections being LIST THEIR TITLES, with the - Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. - A copy of the license is included in the section entitled "GNU - Free Documentation License". -@end smallexample - -If you have no Invariant Sections, write "with no Invariant Sections" -instead of saying which ones are invariant. If you have no -Front-Cover Texts, write "no Front-Cover Texts" instead of -"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. - -If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of -free software license, such as the GNU General Public License, -to permit their use in free software. - -@node Index, , GNU Free Documentation License , Top +@include fdl.texi + +@node Index, , GNU Free Documentation License, Top @unnumbered Index @printindex cp diff --git a/bfd/doc/fdl.texi b/bfd/doc/fdl.texi new file mode 100644 index 0000000..176233c --- /dev/null +++ b/bfd/doc/fdl.texi @@ -0,0 +1,366 @@ +@c -*-texinfo-*- +@appendix GNU Free Documentation License +@center Version 1.1, March 2000 + +@display +Copyright (C) 2000, Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +@end display +@sp 1 +@enumerate 0 +@item +PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document ``free'' in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of ``copyleft'', which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +@sp 1 +@item +APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The ``Document'', below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as ``you.'' + +A ``Modified Version'' of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A ``Secondary Section'' is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The ``Invariant Sections'' are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The ``Cover Texts'' are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A ``Transparent'' copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not ``Transparent'' is called ``Opaque.'' + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The ``Title Page'' means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, ``Title Page'' means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. +@sp 1 +@item +VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. +@sp 1 +@item +COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. +@sp 1 +@item +MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission.@* +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five).@* +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher.@* +D. Preserve all the copyright notices of the Document.@* +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices.@* +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below.@* +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice.@* +H. Include an unaltered copy of this License.@* +I. Preserve the section entitled ``History'', and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled ``History'' in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence.@* +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the ``History'' section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission.@* +K. In any section entitled ``Acknowledgements'' or ``Dedications'', + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein.@* +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles.@* +M. Delete any section entitled ``Endorsements.'' Such a section + may not be included in the Modified Version.@* +N. Do not retitle any existing section as ``Endorsements'' + or to conflict in title with any Invariant Section.@* +@sp 1 +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled ``Endorsements'', provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. +@sp 1 +@item +COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled ``History'' +in the various original documents, forming one section entitled +``History''; likewise combine any sections entitled ``Acknowledgements'', +and any sections entitled ``Dedications.'' You must delete all sections +entitled ``Endorsements.'' +@sp 1 +@item +COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. +@sp 1 +@item +AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an ``aggregate'', and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. +@sp 1 +@item +TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. +@sp 1 +@item +TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. +@sp 1 +@item +FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License ``or any later version'' applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + +@end enumerate + +@unnumberedsec ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +@smallexample +@group +Copyright (C) @var{year} @var{your name}. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 +or any later version published by the Free Software Foundation; +with the Invariant Sections being @var{list their titles}, with the +Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. +A copy of the license is included in the section entitled "GNU +Free Documentation License." +@end group +@end smallexample + +If you have no Invariant Sections, write ``with no Invariant Sections'' +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write ``no Front-Cover Texts'' instead of +``Front-Cover Texts being @var{list}''; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/bfd/ecoff.c b/bfd/ecoff.c index 752752f..1ba7d56 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -1,6 +1,6 @@ /* Generic ECOFF (Extended-COFF) routines. - Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, + 2002, 2003 Free Software Foundation, Inc. Original version by Per Bothner. Full support added by Ian Lance Taylor, ian@cygnus.com. @@ -81,6 +81,10 @@ static asection bfd_debug_section = "*DEBUG*", 0, 0, NULL, 0, 0, 0, /* linker_mark, linker_has_input, gc_mark, segment_mark, */ 0, 0, 0, 0, + /* sec_info_type, use_rela_p, has_tls_reloc, flag11, flag12, */ + 0, 0, 0, 0, 0, + /* flag13, flag14, flag15, flag16, flag20, flag24, */ + 0, 0, 0, 0, 0, 0, /* vma, lma, _cooked_size, _raw_size, */ 0, 0, 0, 0, /* output_offset, output_section, alignment_power, */ diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 394f70c..2e5587c 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -80,6 +80,8 @@ typedef struct } elf_symbol_type; struct elf_strtab_hash; +struct got_entry; +struct plt_entry; /* ELF linker hash table entries. */ @@ -146,23 +148,23 @@ struct elf_link_hash_entry /* If this symbol requires an entry in the global offset table, the processor specific backend uses this field to track usage and - final offset. We use a union and two names primarily to document - the intent of any particular piece of code. The field should be - used as a count until size_dynamic_sections, at which point the - contents of the .got is fixed. Afterward, if this field is -1, - then the symbol does not require a global offset table entry. */ - union + final offset. Two schemes are supported: The first assumes that + a symbol may only have one GOT entry, and uses REFCOUNT until + size_dynamic_sections, at which point the contents of the .got is + fixed. Afterward, if OFFSET is -1, then the symbol does not + require a global offset table entry. The second scheme allows + multiple GOT entries per symbol, managed via a linked list + pointed to by GLIST. */ + union gotplt_union { bfd_signed_vma refcount; bfd_vma offset; + struct got_entry *glist; + struct plt_entry *plist; } got; /* Same, but tracks a procedure linkage table entry. */ - union - { - bfd_signed_vma refcount; - bfd_vma offset; - } plt; + union gotplt_union plt; /* Symbol size. */ bfd_size_type size; @@ -229,16 +231,6 @@ struct elf_link_loaded_list bfd *abfd; }; -enum elf_link_info_type -{ - ELF_INFO_TYPE_NONE, - ELF_INFO_TYPE_STABS, - ELF_INFO_TYPE_MERGE, - ELF_INFO_TYPE_EH_FRAME, - ELF_INFO_TYPE_JUST_SYMS, - ELF_INFO_TYPE_LAST -}; - /* Structures used by the eh_frame optimization code. */ struct cie_header { @@ -333,9 +325,13 @@ struct elf_link_hash_table /* The value to use when initialising got.refcount/offset and plt.refcount/offset in an elf_link_hash_entry. Set to zero when - the values are refcounts. Set to -1 in size_dynamic_sections - when the values may be offsets. */ - bfd_signed_vma init_refcount; + the values are refcounts. Set to init_offset in + size_dynamic_sections when the values may be offsets. */ + union gotplt_union init_refcount; + + /* The value to use for got.refcount/offset and plt.refcount/offset + when the values may be offsets. Normally (bfd_vma) -1. */ + union gotplt_union init_offset; /* The number of symbols found in the link which must be put into the .dynsym section. */ @@ -989,29 +985,19 @@ struct bfd_elf_section_data /* A pointer used for various section optimizations. */ PTR sec_info; - - /* Type of sec_info information. */ - enum elf_link_info_type sec_info_type; - - /* Nonzero if this section uses RELA relocations, rather than REL. */ - unsigned int use_rela_p:1; - - /* Nonzero when a group is COMDAT. */ - unsigned int linkonce_p:1; }; #define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd) #define elf_group_name(sec) (elf_section_data(sec)->group.name) #define elf_group_id(sec) (elf_section_data(sec)->group.id) #define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group) -#define elf_linkonce_p(sec) (elf_section_data(sec)->linkonce_p) /* Return TRUE if section has been discarded. */ -#define elf_discarded_section(sec) \ - (!bfd_is_abs_section(sec) \ - && bfd_is_abs_section((sec)->output_section) \ - && elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ - && elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) +#define elf_discarded_section(sec) \ + (!bfd_is_abs_section (sec) \ + && bfd_is_abs_section ((sec)->output_section) \ + && sec->sec_info_type != ELF_INFO_TYPE_MERGE \ + && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) #define get_elf_backend_data(abfd) \ ((struct elf_backend_data *) (abfd)->xvec->backend_data) @@ -1119,17 +1105,14 @@ struct elf_obj_tdata minus the sh_info field of the symbol table header. */ struct elf_link_hash_entry **sym_hashes; - /* A mapping from local symbols to offsets into the global offset - table, used when linking. This is indexed by the symbol index. - Like for the globals, we use a union and two names primarily to - document the intent of any particular piece of code. The field - should be used as a count until size_dynamic_sections, at which - point the contents of the .got is fixed. Afterward, if an entry - is -1, then the symbol does not require a global offset table entry. */ + /* Track usage and final offsets of GOT entries for local symbols. + This array is indexed by symbol index. Elements are used + identically to "got" in struct elf_link_hash_entry. */ union { bfd_signed_vma *refcounts; bfd_vma *offsets; + struct got_entry **ents; } local_got; /* A mapping from local symbols to offsets into the various linker @@ -1236,6 +1219,7 @@ struct elf_obj_tdata #define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes) #define elf_local_got_refcounts(bfd) (elf_tdata(bfd) -> local_got.refcounts) #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets) +#define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents) #define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers) #define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name) #define elf_dt_soname(bfd) (elf_tdata(bfd) -> dt_soname) @@ -1273,6 +1257,8 @@ extern char *bfd_elf_get_str_section extern Elf_Internal_Sym *bfd_elf_get_elf_syms PARAMS ((bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, PTR, Elf_External_Sym_Shndx *)); +extern const char *bfd_elf_local_sym_name + PARAMS ((bfd *, Elf_Internal_Sym *)); extern bfd_boolean _bfd_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *)); diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c index 7c12674..7764074 100644 --- a/bfd/elf-eh-frame.c +++ b/bfd/elf-eh-frame.c @@ -1,5 +1,5 @@ /* .eh_frame section optimization. - Copyright 2001, 2002 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. Written by Jakub Jelinek <jakub@redhat.com>. This file is part of BFD, the Binary File Descriptor library. @@ -33,7 +33,7 @@ static bfd_signed_vma read_signed_leb128 static int get_DW_EH_PE_width PARAMS ((int, int)); static bfd_vma read_value - PARAMS ((bfd *, bfd_byte *, int)); + PARAMS ((bfd *, bfd_byte *, int, int)); static void write_value PARAMS ((bfd *, bfd_byte *, bfd_vma, int)); static int cie_compare @@ -141,22 +141,42 @@ int get_DW_EH_PE_width (encoding, ptr_size) return 0; } +#define get_DW_EH_PE_signed(encoding) (((encoding) & DW_EH_PE_signed) != 0) + /* Read a width sized value from memory. */ static bfd_vma -read_value (abfd, buf, width) +read_value (abfd, buf, width, is_signed) bfd *abfd; bfd_byte *buf; int width; + int is_signed; { bfd_vma value; switch (width) { - case 2: value = bfd_get_16 (abfd, buf); break; - case 4: value = bfd_get_32 (abfd, buf); break; - case 8: value = bfd_get_64 (abfd, buf); break; - default: BFD_FAIL (); return 0; + case 2: + if (is_signed) + value = bfd_get_signed_16 (abfd, buf); + else + value = bfd_get_16 (abfd, buf); + break; + case 4: + if (is_signed) + value = bfd_get_signed_32 (abfd, buf); + else + value = bfd_get_32 (abfd, buf); + break; + case 8: + if (is_signed) + value = bfd_get_signed_64 (abfd, buf); + else + value = bfd_get_64 (abfd, buf); + break; + default: + BFD_FAIL (); + return 0; } return value; @@ -605,7 +625,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec, } elf_section_data (sec)->sec_info = sec_info; - elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME; + sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME; /* Ok, now we can assign new offsets. */ offset = 0; @@ -758,7 +778,7 @@ _bfd_elf_eh_frame_section_offset (output_bfd, sec, offset) struct eh_frame_sec_info *sec_info; unsigned int lo, hi, mid; - if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME) + if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) return offset; sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; @@ -828,7 +848,7 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents) ptr_size = (elf_elfheader (sec->owner)->e_ident[EI_CLASS] == ELFCLASS64) ? 8 : 4; - if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_EH_FRAME) + if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) return bfd_set_section_contents (abfd, sec->output_section, contents, (file_ptr) sec->output_offset, @@ -925,7 +945,9 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents) { bfd_vma value; - value = read_value (abfd, buf, per_width); + value = read_value (abfd, buf, per_width, + get_DW_EH_PE_signed + (per_encoding)); value += (sec_info->entry[i].offset - sec_info->entry[i].new_offset); write_value (abfd, buf, value, per_width); @@ -961,7 +983,9 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents) buf += 4; width = get_DW_EH_PE_width (sec_info->entry[i].fde_encoding, ptr_size); - address = value = read_value (abfd, buf, width); + address = value = read_value (abfd, buf, width, + get_DW_EH_PE_signed + (sec_info->entry[i].fde_encoding)); if (value) { switch (sec_info->entry[i].fde_encoding & 0xf0) @@ -1005,7 +1029,9 @@ _bfd_elf_write_section_eh_frame (abfd, info, sec, contents) buf += sec_info->entry[i].lsda_offset; width = get_DW_EH_PE_width (sec_info->entry[i].lsda_encoding, ptr_size); - value = read_value (abfd, buf, width); + value = read_value (abfd, buf, width, + get_DW_EH_PE_signed + (sec_info->entry[i].lsda_encoding)); if (value) { if ((sec_info->entry[i].lsda_encoding & 0xf0) @@ -97,6 +97,12 @@ static bfd_boolean elfcore_grok_netbsd_procinfo PARAMS ((bfd *, Elf_Internal_Note *)); static bfd_boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *)); +static bfd_boolean elfcore_grok_nto_gregs + PARAMS ((bfd *, Elf_Internal_Note *, pid_t)); +static bfd_boolean elfcore_grok_nto_status + PARAMS ((bfd *, Elf_Internal_Note *, pid_t *)); +static bfd_boolean elfcore_grok_nto_note + PARAMS ((bfd *, Elf_Internal_Note *)); /* Swap version information in and out. The version information is currently size independent. If that ever changes, this code will @@ -476,6 +482,23 @@ bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset, return intsym_buf; } +/* Look up a symbol name. */ +const char * +bfd_elf_local_sym_name (abfd, isym) + bfd *abfd; + Elf_Internal_Sym *isym; +{ + unsigned int iname = isym->st_name; + unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link; + if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION) + { + iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name; + shindex = elf_elfheader (abfd)->e_shstrndx; + } + + return bfd_elf_string_from_elf_section (abfd, shindex, iname); +} + /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP sections. The first element is the flags, the rest are section pointers. */ @@ -497,8 +520,6 @@ group_signature (abfd, ghdr) unsigned char esym[sizeof (Elf64_External_Sym)]; Elf_External_Sym_Shndx eshndx; Elf_Internal_Sym isym; - unsigned int iname; - unsigned int shindex; /* First we need to ensure the symbol table is available. */ if (! bfd_section_from_shdr (abfd, ghdr->sh_link)) @@ -510,16 +531,7 @@ group_signature (abfd, ghdr) &isym, esym, &eshndx) == NULL) return NULL; - /* Look up the symbol name. */ - iname = isym.st_name; - shindex = hdr->sh_link; - if (iname == 0 && ELF_ST_TYPE (isym.st_info) == STT_SECTION) - { - iname = elf_elfsections (abfd)[isym.st_shndx]->sh_name; - shindex = elf_elfheader (abfd)->e_shstrndx; - } - - return bfd_elf_string_from_elf_section (abfd, shindex, iname); + return bfd_elf_local_sym_name (abfd, &isym); } /* Set next_in_group list pointer, and group name for NEWSECT. */ @@ -969,11 +981,8 @@ merge_sections_remove_hook (abfd, sec) bfd *abfd ATTRIBUTE_UNUSED; asection *sec; { - struct bfd_elf_section_data *sec_data; - - sec_data = elf_section_data (sec); - BFD_ASSERT (sec_data->sec_info_type == ELF_INFO_TYPE_MERGE); - sec_data->sec_info_type = ELF_INFO_TYPE_NONE; + BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE); + sec->sec_info_type = ELF_INFO_TYPE_NONE; } /* Finish SHF_MERGE section merging. */ @@ -1001,7 +1010,7 @@ _bfd_elf_link_just_syms (sec, info) if (!is_elf_hash_table (info)) return; - elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_JUST_SYMS; + sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS; } /* Copy the program header and other data from one object module to @@ -1423,8 +1432,8 @@ _bfd_elf_link_hash_newfunc (entry, table, string) ret->vtable_entries_size = 0; ret->vtable_entries_used = NULL; ret->vtable_parent = NULL; - ret->got.refcount = htab->init_refcount; - ret->plt.refcount = htab->init_refcount; + ret->got = htab->init_refcount; + ret->plt = htab->init_refcount; ret->size = 0; ret->type = STT_NOTYPE; ret->other = 0; @@ -1499,7 +1508,7 @@ _bfd_elf_link_hash_hide_symbol (info, h, force_local) struct elf_link_hash_entry *h; bfd_boolean force_local; { - h->plt.offset = (bfd_vma) -1; + h->plt = elf_hash_table (info)->init_offset; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; if (force_local) { @@ -1529,8 +1538,9 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc) table->dynobj = NULL; /* Make sure can_refcount is extended to the width and signedness of init_refcount before we subtract one from it. */ - table->init_refcount = get_elf_backend_data (abfd)->can_refcount; - --table->init_refcount; + table->init_refcount.refcount = get_elf_backend_data (abfd)->can_refcount; + table->init_refcount.refcount -= 1; + table->init_offset.offset = -(bfd_vma) 1; /* The first dynamic symbol is a dummy. */ table->dynsymcount = 1; table->dynstr = NULL; @@ -2007,8 +2017,7 @@ bfd_section_from_shdr (abfd, shindex) /* In the section to which the relocations apply, mark whether its relocations are of the REL or RELA variety. */ if (hdr->sh_size != 0) - elf_section_data (target_sect)->use_rela_p - = (hdr->sh_type == SHT_RELA); + target_sect->use_rela_p = hdr->sh_type == SHT_RELA; abfd->flags |= HAS_RELOC; return TRUE; } @@ -2148,8 +2157,7 @@ _bfd_elf_new_section_hook (abfd, sec) } /* Indicate whether or not this section should use RELA relocations. */ - sdata->use_rela_p - = get_elf_backend_data (abfd)->default_use_rela_p; + sec->use_rela_p = get_elf_backend_data (abfd)->default_use_rela_p; return TRUE; } @@ -2507,7 +2515,7 @@ elf_fake_sections (abfd, asect, failedptrarg) && !_bfd_elf_init_reloc_shdr (abfd, &elf_section_data (asect)->rel_hdr, asect, - elf_section_data (asect)->use_rela_p)) + asect->use_rela_p)) *failedptr = TRUE; } @@ -3540,7 +3548,7 @@ elf_sort_sections (arg1, arg2) /* Put !SEC_LOAD sections after SEC_LOAD ones. */ -#define TOEND(x) (((x)->flags & (SEC_LOAD|SEC_THREAD_LOCAL)) == 0) +#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0) if (TOEND (sec1)) { @@ -4654,13 +4662,20 @@ copy_private_bfd_data (ibfd, obfd) && ! section->segment_mark) /* Returns TRUE iff seg1 starts after the end of seg2. */ -#define SEGMENT_AFTER_SEGMENT(seg1, seg2) \ - (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr)) - - /* Returns TRUE iff seg1 and seg2 overlap. */ +#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field) \ + (seg1->field >= SEGMENT_END (seg2, seg2->field)) + + /* Returns TRUE iff seg1 and seg2 overlap. Segments overlap iff both + their VMA address ranges and their LMA address ranges overlap. + It is possible to have overlapping VMA ranges without overlapping LMA + ranges. RedBoot images for example can have both .data and .bss mapped + to the same VMA range, but with the .data section mapped to a different + LMA. */ #define SEGMENT_OVERLAPS(seg1, seg2) \ - (!(SEGMENT_AFTER_SEGMENT (seg1, seg2) \ - || SEGMENT_AFTER_SEGMENT (seg2, seg1))) + ( !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_vaddr) \ + || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_vaddr)) \ + && !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_paddr) \ + || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_paddr))) /* Initialise the segment mark field. */ for (section = ibfd->sections; section != NULL; section = section->next) @@ -4758,13 +4773,14 @@ copy_private_bfd_data (ibfd, obfd) continue; /* Compute how many sections might be placed into this segment. */ - section_count = 0; - for (section = ibfd->sections; section != NULL; section = section->next) + for (section = ibfd->sections, section_count = 0; + section != NULL; + section = section->next) if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed)) ++section_count; - - /* Allocate a segment map big enough to contain all of the - sections we have selected. */ + + /* Allocate a segment map big enough to contain + all of the sections we have selected. */ amt = sizeof (struct elf_segment_map); amt += ((bfd_size_type) section_count - 1) * sizeof (asection *); map = (struct elf_segment_map *) bfd_alloc (obfd, amt); @@ -4836,7 +4852,7 @@ copy_private_bfd_data (ibfd, obfd) and possibly its LMA changed, and a new segment or segments will have to be created to contain the other sections. - 4. The sections have been moved, but not be the same amount. + 4. The sections have been moved, but not by the same amount. In this case we can change the segment's LMA to match the LMA of the first section and we will have to create a new segment or segments to contain the other sections. @@ -5080,10 +5096,8 @@ copy_private_bfd_data (ibfd, obfd) if (map->p_paddr != 0) break; if (map == NULL) - { - for (map = map_first; map != NULL; map = map->next) - map->p_paddr_valid = 0; - } + for (map = map_first; map != NULL; map = map->next) + map->p_paddr_valid = 0; elf_tdata (obfd)->segment_map = map_first; @@ -5190,8 +5204,7 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec) elf_next_in_group (osec) = elf_next_in_group (isec); elf_group_name (osec) = elf_group_name (isec); - elf_section_data (osec)->use_rela_p - = elf_section_data (isec)->use_rela_p; + osec->use_rela_p = isec->use_rela_p; return TRUE; } @@ -5308,7 +5321,7 @@ swap_out_syms (abfd, sttp, relocatable_p) symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx); } - /* now generate the data (for "contents") */ + /* Now generate the data (for "contents"). */ { /* Fill in zeroth symbol and swap it out. */ Elf_Internal_Sym sym; @@ -5374,6 +5387,7 @@ swap_out_syms (abfd, sttp, relocatable_p) value += sec->output_offset; sec = sec->output_section; } + /* Don't add in the section vma for relocatable output. */ if (! relocatable_p) value += sec->vma; @@ -5425,7 +5439,16 @@ swap_out_syms (abfd, sttp, relocatable_p) section of a symbol to be a section that is actually in the output file. */ sec2 = bfd_get_section_by_name (abfd, sec->name); - BFD_ASSERT (sec2 != 0); + if (sec2 == NULL) + { + _bfd_error_handler (_("\ +Unable to find equivalent output section for symbol '%s' from section '%s'"), + syms[idx]->name ? syms[idx]->name : "<Local sym>", + sec->name); + bfd_set_error (bfd_error_invalid_operation); + return FALSE; + } + shndx = _bfd_elf_section_from_bfd_section (abfd, sec2); BFD_ASSERT (shndx != -1); } @@ -5446,7 +5469,7 @@ swap_out_syms (abfd, sttp, relocatable_p) if (syms[idx]->section->flags & SEC_THREAD_LOCAL) type = STT_TLS; - /* Processor-specific types */ + /* Processor-specific types. */ if (type_ptr != NULL && bed->elf_backend_get_symbol_type) type = ((*bed->elf_backend_get_symbol_type) @@ -6950,6 +6973,104 @@ elfcore_grok_netbsd_note (abfd, note) /* NOTREACHED */ } +static bfd_boolean +elfcore_grok_nto_status (abfd, note, tid) + bfd *abfd; + Elf_Internal_Note *note; + pid_t *tid; +{ + void *ddata = note->descdata; + char buf[100]; + char *name; + asection *sect; + + /* nto_procfs_status 'pid' field is at offset 0. */ + elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata); + + /* nto_procfs_status 'tid' field is at offset 4. */ + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4); + + /* nto_procfs_status 'what' field is at offset 14. */ + elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, (bfd_byte *) ddata + 14); + + /* Pass tid back. */ + *tid = elf_tdata (abfd)->core_lwpid; + + /* Make a ".qnx_core_status/%d" section. */ + sprintf (buf, ".qnx_core_status/%d", *tid); + + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); + if (name == NULL) + return FALSE; + strcpy (name, buf); + + sect = bfd_make_section (abfd, name); + if (sect == NULL) + return FALSE; + + sect->_raw_size = note->descsz; + sect->filepos = note->descpos; + sect->flags = SEC_HAS_CONTENTS; + sect->alignment_power = 2; + + return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect)); +} + +static bfd_boolean +elfcore_grok_nto_gregs (abfd, note, tid) + bfd *abfd; + Elf_Internal_Note *note; + pid_t tid; +{ + char buf[100]; + char *name; + asection *sect; + + /* Make a ".reg/%d" section. */ + sprintf (buf, ".reg/%d", tid); + + name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1); + if (name == NULL) + return FALSE; + strcpy (name, buf); + + sect = bfd_make_section (abfd, name); + if (sect == NULL) + return FALSE; + + sect->_raw_size = note->descsz; + sect->filepos = note->descpos; + sect->flags = SEC_HAS_CONTENTS; + sect->alignment_power = 2; + + return elfcore_maybe_make_sect (abfd, ".reg", sect); +} + +#define BFD_QNT_CORE_INFO 7 +#define BFD_QNT_CORE_STATUS 8 +#define BFD_QNT_CORE_GREG 9 +#define BFD_QNT_CORE_FPREG 10 + +static bfd_boolean +elfcore_grok_nto_note (abfd, note) + bfd *abfd; + Elf_Internal_Note *note; +{ + /* Every GREG section has a STATUS section before it. Store the + tid from the previous call to pass down to the next gregs + function. */ + static pid_t tid = 1; + + switch (note->type) + { + case BFD_QNT_CORE_INFO: return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note); + case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid); + case BFD_QNT_CORE_GREG: return elfcore_grok_nto_gregs (abfd, note, tid); + case BFD_QNT_CORE_FPREG: return elfcore_grok_prfpreg (abfd, note); + default: return TRUE; + } +} + /* Function: elfcore_write_note Inputs: @@ -7189,6 +7310,11 @@ elfcore_read_notes (abfd, offset, size) if (! elfcore_grok_netbsd_note (abfd, &in)) goto error; } + else if (strncmp (in.namedata, "QNX", 3) == 0) + { + if (! elfcore_grok_nto_note (abfd, &in)) + goto error; + } else { if (! elfcore_grok_note (abfd, &in)) @@ -7336,7 +7462,7 @@ _bfd_elf_rela_local_sym (abfd, sym, sec, rel) + sym->st_value); if ((sec->flags & SEC_MERGE) && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE) + && sec->sec_info_type == ELF_INFO_TYPE_MERGE) { asection *msec; @@ -7361,7 +7487,7 @@ _bfd_elf_rel_local_sym (abfd, sym, psec, addend) { asection *sec = *psec; - if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE) + if (sec->sec_info_type != ELF_INFO_TYPE_MERGE) return sym->st_value + addend; return _bfd_merged_section_offset (abfd, psec, @@ -7379,7 +7505,7 @@ _bfd_elf_section_offset (abfd, info, sec, offset) struct bfd_elf_section_data *sec_data; sec_data = elf_section_data (sec); - switch (sec_data->sec_info_type) + switch (sec->sec_info_type) { case ELF_INFO_TYPE_STABS: return _bfd_stab_section_offset (abfd, diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 48eb873..509b481 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -1,5 +1,5 @@ /* 32-bit ELF support for ARM - Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -86,6 +86,8 @@ static void arm_add_to_rel #endif static enum elf_reloc_type_class elf32_arm_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); +static bfd_boolean elf32_arm_object_p + PARAMS ((bfd *)); #ifndef ELFARM_NABI_C_INCLUDED static void record_arm_to_thumb_glue @@ -927,13 +929,16 @@ elf32_thumb_to_arm_stub (info, name, input_bfd, output_bfd, input_section, BFD_ASSERT (my_offset <= globals->thumb_glue_size); - /* Now go back and fix up the original BL insn to point - to here. */ - ret_offset = (s->output_offset - + my_offset - - (input_section->output_offset - + offset + addend) - - 8); + /* Now go back and fix up the original BL insn to point to here. */ + ret_offset = + /* Address of where the stub is located. */ + (s->output_section->vma + s->output_offset + my_offset) + /* Address of where the BL is located. */ + - (input_section->output_section->vma + input_section->output_offset + offset) + /* Addend in the relocation. */ + - addend + /* Biassing for PC-relative addressing. */ + - 8; tmp = bfd_get_32 (input_bfd, hit_data - input_section->vma); @@ -2108,6 +2113,20 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section, return TRUE; } +/* Set the right machine number. */ + +static bfd_boolean +elf32_arm_object_p (abfd) + bfd *abfd; +{ + /* XXX - we ought to examine a .note section here. */ + + if (elf_elfheader (abfd)->e_flags & EF_ARM_MAVERICK_FLOAT) + bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_ep9312); + + return TRUE; +} + /* Function to keep ARM specific flags in the ELF header. */ static bfd_boolean elf32_arm_set_private_flags (abfd, flags) @@ -2310,12 +2329,28 @@ ERROR: %s passes floats in integer registers, whereas %s passes them in float re { if (in_flags & EF_ARM_VFP_FLOAT) _bfd_error_handler (_("\ -ERROR: %s uses VFP instructions, whereas %s uses FPA instructions"), +ERROR: %s uses VFP instructions, whereas %s does not"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + else + _bfd_error_handler (_("\ +ERROR: %s uses FPA instructions, whereas %s does not"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + + flags_compatible = FALSE; + } + + if ((in_flags & EF_ARM_MAVERICK_FLOAT) != (out_flags & EF_ARM_MAVERICK_FLOAT)) + { + if (in_flags & EF_ARM_MAVERICK_FLOAT) + _bfd_error_handler (_("\ +ERROR: %s uses Maverick instructions, whereas %s does not"), bfd_archive_filename (ibfd), bfd_get_filename (obfd)); else _bfd_error_handler (_("\ -ERROR: %s uses FPA instructions, whereas %s uses VFP instructions"), +ERROR: %s uses Maverick instructions, whereas %s does not"), bfd_archive_filename (ibfd), bfd_get_filename (obfd)); @@ -2410,6 +2445,8 @@ elf32_arm_print_private_bfd_data (abfd, ptr) if (flags & EF_ARM_VFP_FLOAT) fprintf (file, _(" [VFP float format]")); + else if (flags & EF_ARM_MAVERICK_FLOAT) + fprintf (file, _(" [Maverick float format]")); else fprintf (file, _(" [FPA float format]")); @@ -2430,7 +2467,8 @@ elf32_arm_print_private_bfd_data (abfd, ptr) flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI - | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT); + | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT + | EF_ARM_MAVERICK_FLOAT); break; case EF_ARM_EABI_VER1: @@ -3622,7 +3660,6 @@ elf32_arm_reloc_type_class (rela) } } - #define ELF_ARCH bfd_arch_arm #define ELF_MACHINE_CODE EM_ARM #define ELF_MAXPAGESIZE 0x8000 @@ -3647,6 +3684,7 @@ elf32_arm_reloc_type_class (rela) #define elf_backend_size_dynamic_sections elf32_arm_size_dynamic_sections #define elf_backend_post_process_headers elf32_arm_post_process_headers #define elf_backend_reloc_type_class elf32_arm_reloc_type_class +#define elf_backend_object_p elf32_arm_object_p #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1 diff --git a/bfd/elf32-cris.c b/bfd/elf32-cris.c index 6b6c906..40327b6 100644 --- a/bfd/elf32-cris.c +++ b/bfd/elf32-cris.c @@ -1,24 +1,24 @@ /* CRIS-specific support for 32-bit ELF. - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Axis Communications AB. Written by Hans-Peter Nilsson, based on elf32-fr30.c PIC and shlib bits based primarily on elf32-m68k.c and elf32-i386.c. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -940,7 +940,6 @@ cris_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 2646f3d..b204c57 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -1,6 +1,6 @@ /* BFD back-end for HP PA-RISC ELF files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001, - 2002 Free Software Foundation, Inc. + 2002, 2003 Free Software Foundation, Inc. Original code by Center for Software Science @@ -8,21 +8,21 @@ University of Utah Largely rewritten by Alan Modra <alan@linuxcare.com.au> -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -111,7 +111,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ : ldw -24(%sp),%rp ; restore the original rp : ldsid (%rp),%r1 : mtsp %r1,%sr0 - : be,n 0(%sr0,%rp) ; inter-space return */ + : be,n 0(%sr0,%rp) ; inter-space return. */ #define PLT_ENTRY_SIZE 8 #define GOT_ENTRY_SIZE 4 @@ -1685,10 +1685,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs) bfd_signed_vma *local_got_refcounts; bfd_signed_vma *local_plt_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - struct elf_link_hash_entry *h; - struct elf32_hppa_link_hash_table *htab; - bfd *dynobj; elf_section_data (sec)->local_dynrel = NULL; @@ -1698,112 +1694,81 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs) local_plt_refcounts = local_got_refcounts; if (local_plt_refcounts != NULL) local_plt_refcounts += symtab_hdr->sh_info; - htab = hppa_link_hash_table (info); - dynobj = htab->elf.dynobj; - if (dynobj == NULL) - return TRUE; relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch ((unsigned int) ELF32_R_TYPE (rel->r_info)) - { - case R_PARISC_DLTIND14F: - case R_PARISC_DLTIND14R: - case R_PARISC_DLTIND21L: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; - - case R_PARISC_PCREL12F: - case R_PARISC_PCREL17C: - case R_PARISC_PCREL17F: - case R_PARISC_PCREL22F: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } - break; - - case R_PARISC_PLABEL14R: - case R_PARISC_PLABEL21L: - case R_PARISC_PLABEL32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf32_hppa_link_hash_entry *eh; - struct elf32_hppa_dyn_reloc_entry **pp; - struct elf32_hppa_dyn_reloc_entry *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - - if (h->plt.refcount > 0) - h->plt.refcount -= 1; + { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; - eh = (struct elf32_hppa_link_hash_entry *) h; + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf32_hppa_link_hash_entry *eh; + struct elf32_hppa_dyn_reloc_entry **pp; + struct elf32_hppa_dyn_reloc_entry *p; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { -#if RELATIVE_DYNRELOCS - if (!IS_ABSOLUTE_RELOC (rtype)) - p->relative_count -= 1; -#endif - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - else if (local_plt_refcounts != NULL) - { - if (local_plt_refcounts[r_symndx] > 0) - local_plt_refcounts[r_symndx] -= 1; - } - break; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf32_hppa_link_hash_entry *) h; - case R_PARISC_DIR32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf32_hppa_link_hash_entry *eh; - struct elf32_hppa_dyn_reloc_entry **pp; - struct elf32_hppa_dyn_reloc_entry *p; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + r_type = ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PARISC_DLTIND14F: + case R_PARISC_DLTIND14R: + case R_PARISC_DLTIND21L: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount -= 1; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + } + break; - eh = (struct elf32_hppa_link_hash_entry *) h; + case R_PARISC_PCREL12F: + case R_PARISC_PCREL17C: + case R_PARISC_PCREL17F: + case R_PARISC_PCREL22F: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + break; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { -#if RELATIVE_DYNRELOCS - if (!IS_ABSOLUTE_RELOC (R_PARISC_DIR32)) - p->relative_count -= 1; -#endif - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + case R_PARISC_PLABEL14R: + case R_PARISC_PLABEL21L: + case R_PARISC_PLABEL32: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + else if (local_plt_refcounts != NULL) + { + if (local_plt_refcounts[r_symndx] > 0) + local_plt_refcounts[r_symndx] -= 1; + } + break; - default: - break; - } + default: + break; + } + } return TRUE; } @@ -2686,12 +2651,15 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) asection *curr; asection *prev; bfd_size_type total; + bfd_boolean big_sec; curr = tail; if (tail->_cooked_size) total = tail->_cooked_size; else total = tail->_raw_size; + big_sec = total >= stub_group_size; + while ((prev = PREV_SEC (curr)) != NULL && ((total += curr->output_offset - prev->output_offset) < stub_group_size)) @@ -2719,8 +2687,11 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) while (tail != curr && (tail = prev) != NULL); /* But wait, there's more! Input sections up to 240000 - bytes before the stub section can be handled by it too. */ - if (!stubs_always_before_branch) + bytes before the stub section can be handled by it too. + Don't do this if we have a really large section after the + stubs, as adding more stubs increases the chance that + branches may not reach into the stub section. */ + if (!stubs_always_before_branch && !big_sec) { total = 0; while (prev != NULL @@ -2901,11 +2872,22 @@ elf32_hppa_size_stubs (output_bfd, stub_bfd, info, multi_subspace, group_size, if (stub_group_size == 1) { /* Default values. */ - stub_group_size = 7680000; - if (htab->has_17bit_branch || htab->multi_subspace) - stub_group_size = 240000; - if (htab->has_12bit_branch) - stub_group_size = 7500; + if (stubs_always_before_branch) + { + stub_group_size = 7680000; + if (htab->has_17bit_branch || htab->multi_subspace) + stub_group_size = 240000; + if (htab->has_12bit_branch) + stub_group_size = 7500; + } + else + { + stub_group_size = 6971392; + if (htab->has_17bit_branch || htab->multi_subspace) + stub_group_size = 217856; + if (htab->has_12bit_branch) + stub_group_size = 6808; + } } group_sections (htab, stub_group_size, stubs_always_before_branch); @@ -3688,14 +3670,11 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT && h->elf.type != STT_PARISC_MILLI) { - if (info->symbolic && !info->allow_shlib_undefined) - { - if (!((*info->callbacks->undefined_symbol) - (info, h->elf.root.root.string, input_bfd, - input_section, rel->r_offset, FALSE))) - return FALSE; - warned_undef = TRUE; - } + if (!((*info->callbacks->undefined_symbol) + (info, h->elf.root.root.string, input_bfd, + input_section, rel->r_offset, FALSE))) + return FALSE; + warned_undef = TRUE; } else { diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 69292da..a751d98 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1279,9 +1279,6 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - int r_type; - struct elf_link_hash_entry *h; elf_section_data (sec)->local_dynrel = NULL; @@ -1291,85 +1288,74 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch ((r_type = elf_i386_tls_transition (info, - ELF32_R_TYPE (rel->r_info), - ELF32_R_SYM (rel->r_info) - >= symtab_hdr->sh_info))) - { - case R_386_TLS_LDM: - if (elf_i386_hash_table (info)->tls_ldm_got.refcount > 0) - elf_i386_hash_table (info)->tls_ldm_got.refcount -= 1; - break; - - case R_386_TLS_GD: - case R_386_TLS_IE_32: - case R_386_TLS_IE: - case R_386_TLS_GOTIE: - case R_386_GOT32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - if (r_type != R_386_TLS_IE) - break; - /* Fall through */ + { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; - case R_386_TLS_LE_32: - case R_386_TLS_LE: - if (!info->shared) - break; - /* Fall through */ + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_i386_link_hash_entry *eh; + struct elf_i386_dyn_relocs **pp; + struct elf_i386_dyn_relocs *p; - case R_386_32: - case R_386_PC32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf_i386_link_hash_entry *eh; - struct elf_i386_dyn_relocs **pp; - struct elf_i386_dyn_relocs *p; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf_i386_link_hash_entry *) h; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; + r_type = ELF32_R_TYPE (rel->r_info); + r_type = elf_i386_tls_transition (info, r_type, h != NULL); + switch (r_type) + { + case R_386_TLS_LDM: + if (elf_i386_hash_table (info)->tls_ldm_got.refcount > 0) + elf_i386_hash_table (info)->tls_ldm_got.refcount -= 1; + break; - eh = (struct elf_i386_link_hash_entry *) h; + case R_386_TLS_GD: + case R_386_TLS_IE_32: + case R_386_TLS_IE: + case R_386_TLS_GOTIE: + case R_386_GOT32: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount -= 1; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + } + break; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF32_R_TYPE (rel->r_info) == R_386_PC32) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + case R_386_32: + case R_386_PC32: + if (info->shared) + break; + /* Fall through */ - case R_386_PLT32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } - break; + case R_386_PLT32: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + break; - default: - break; - } + default: + break; + } + } return TRUE; } @@ -1523,9 +1509,9 @@ elf_i386_adjust_dynamic_symbol (info, h) will be called from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol routine, we'll need to do something about initializing any .plt and .got entries in elf_i386_relocate_section. */ -#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \ ((DYN) \ - && ((INFO)->shared \ + && ((SHARED) \ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ && ((H)->dynindx != -1 \ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) @@ -1567,7 +1553,8 @@ allocate_dynrelocs (h, inf) return FALSE; } - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) + if (info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { asection *s = htab->splt; @@ -1653,7 +1640,8 @@ allocate_dynrelocs (h, inf) htab->srelgot->_raw_size += sizeof (Elf32_External_Rel); else if (tls_type == GOT_TLS_GD) htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rel); - else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) + else if (info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) htab->srelgot->_raw_size += sizeof (Elf32_External_Rel); } else @@ -2261,7 +2249,6 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) ; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -2290,7 +2277,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, off = h->got.offset; dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) || (info->shared && (info->symbolic || h->dynindx == -1 @@ -2627,7 +2614,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (rel->r_offset >= 2); type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2); switch (type) - { + { case 0x8b: /* movl */ BFD_ASSERT ((val & 0xc7) == 0x05); @@ -2649,7 +2636,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, default: BFD_FAIL (); break; - } + } } bfd_put_32 (output_bfd, -tpoff (info, relocation), contents + rel->r_offset); @@ -2724,7 +2711,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section, if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; bfd_byte *loc; diff --git a/bfd/elf32-m68k.c b/bfd/elf32-m68k.c index 2f49dad..19a2ce8 100644 --- a/bfd/elf32-m68k.c +++ b/bfd/elf32-m68k.c @@ -2,21 +2,21 @@ Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -46,6 +46,8 @@ static bfd_boolean elf_m68k_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); static bfd_boolean elf_m68k_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); +static bfd_boolean elf_m68k_discard_copies + PARAMS ((struct elf_link_hash_entry *, PTR)); static bfd_boolean elf_m68k_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); @@ -88,7 +90,7 @@ static reloc_howto_type howto_table[] = { HOWTO(R_68K_GLOB_DAT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", FALSE, 0, 0xffffffff,FALSE), HOWTO(R_68K_JMP_SLOT, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", FALSE, 0, 0xffffffff,FALSE), HOWTO(R_68K_RELATIVE, 0, 2,32, FALSE,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", FALSE, 0, 0xffffffff,FALSE), - /* GNU extension to record C++ vtable hierarchy */ + /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_68K_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -102,7 +104,7 @@ static reloc_howto_type howto_table[] = { 0, /* src_mask */ 0, /* dst_mask */ FALSE), - /* GNU extension to record C++ vtable member usage */ + /* GNU extension to record C++ vtable member usage. */ HOWTO (R_68K_GNU_VTENTRY, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -179,7 +181,6 @@ reloc_type_lookup (abfd, code) #define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup #define ELF_ARCH bfd_arch_m68k -/* end code generated by elf.el */ /* Functions for the m68k ELF linker. */ @@ -272,6 +273,8 @@ struct elf_m68k_link_hash_entry struct elf_m68k_pcrel_relocs_copied *pcrel_relocs_copied; }; +#define elf_m68k_hash_entry(ent) ((struct elf_m68k_link_hash_entry *) (ent)) + /* m68k ELF linker hash table. */ struct elf_m68k_link_hash_table @@ -282,19 +285,6 @@ struct elf_m68k_link_hash_table struct sym_sec_cache sym_sec; }; -/* Declare this now that the above structures are defined. */ - -static bfd_boolean elf_m68k_discard_copies - PARAMS ((struct elf_m68k_link_hash_entry *, PTR)); - -/* Traverse an m68k ELF linker hash table. */ - -#define elf_m68k_link_hash_traverse(table, func, info) \ - (elf_link_hash_traverse \ - (&(table)->root, \ - (bfd_boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ - (info))) - /* Get the m68k ELF linker hash table from a link_info structure. */ #define elf_m68k_hash_table(p) \ @@ -308,28 +298,22 @@ elf_m68k_link_hash_newfunc (entry, table, string) struct bfd_hash_table *table; const char *string; { - struct elf_m68k_link_hash_entry *ret = - (struct elf_m68k_link_hash_entry *) entry; + struct bfd_hash_entry *ret = entry; /* Allocate the structure if it has not already been allocated by a subclass. */ - if (ret == (struct elf_m68k_link_hash_entry *) NULL) - ret = ((struct elf_m68k_link_hash_entry *) - bfd_hash_allocate (table, - sizeof (struct elf_m68k_link_hash_entry))); - if (ret == (struct elf_m68k_link_hash_entry *) NULL) - return (struct bfd_hash_entry *) ret; + if (ret == NULL) + ret = bfd_hash_allocate (table, + sizeof (struct elf_m68k_link_hash_entry)); + if (ret == NULL) + return ret; /* Call the allocation method of the superclass. */ - ret = ((struct elf_m68k_link_hash_entry *) - _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, - table, string)); - if (ret != (struct elf_m68k_link_hash_entry *) NULL) - { - ret->pcrel_relocs_copied = NULL; - } + ret = _bfd_elf_link_hash_newfunc (ret, table, string); + if (ret != NULL) + elf_m68k_hash_entry (ret)->pcrel_relocs_copied = NULL; - return (struct bfd_hash_entry *) ret; + return ret; } /* Create an m68k ELF linker hash table. */ @@ -357,7 +341,7 @@ elf_m68k_link_hash_table_create (abfd) return &ret->root.root; } -/* Keep m68k-specific flags in the ELF header */ +/* Keep m68k-specific flags in the ELF header. */ static bfd_boolean elf32_m68k_set_private_flags (abfd, flags) bfd *abfd; @@ -394,7 +378,7 @@ elf32_m68k_merge_private_bfd_data (ibfd, obfd) return TRUE; } -/* Display the flags field */ +/* Display the flags field. */ static bfd_boolean elf32_m68k_print_private_bfd_data (abfd, ptr) bfd *abfd; @@ -719,7 +703,7 @@ elf_m68k_check_relocs (abfd, info, sec, relocs) if (h != NULL) { struct elf_m68k_link_hash_entry *eh - = (struct elf_m68k_link_hash_entry *) h; + = elf_m68k_hash_entry (h); head = &eh->pcrel_relocs_copied; } else @@ -1023,13 +1007,11 @@ elf_m68k_adjust_dynamic_symbol (info, h) /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - s = bfd_get_section_by_name (dynobj, ".got.plt"); BFD_ASSERT (s != NULL); s->_raw_size += 4; /* We also need to make an entry in the .rela.plt section. */ - s = bfd_get_section_by_name (dynobj, ".rela.plt"); BFD_ASSERT (s != NULL); s->_raw_size += sizeof (Elf32_External_Rela); @@ -1160,9 +1142,9 @@ elf_m68k_size_dynamic_sections (output_bfd, info) We allocated space for them in the check_relocs routine, but we will not fill them in in the relocate_section routine. */ if (info->shared) - elf_m68k_link_hash_traverse (elf_m68k_hash_table (info), - elf_m68k_discard_copies, - (PTR) info); + elf_link_hash_traverse (elf_hash_table (info), + elf_m68k_discard_copies, + (PTR) info); /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate @@ -1288,7 +1270,7 @@ elf_m68k_size_dynamic_sections (output_bfd, info) return TRUE; } -/* This function is called via elf_m68k_link_hash_traverse if we are +/* This function is called via elf_link_hash_traverse if we are creating a shared object. In the -Bsymbolic case it discards the space allocated to copy PC relative relocs against symbols which are defined in regular objects. For the normal shared case, it @@ -1303,33 +1285,38 @@ elf_m68k_size_dynamic_sections (output_bfd, info) static bfd_boolean elf_m68k_discard_copies (h, inf) - struct elf_m68k_link_hash_entry *h; + struct elf_link_hash_entry *h; PTR inf; { struct bfd_link_info *info = (struct bfd_link_info *) inf; struct elf_m68k_pcrel_relocs_copied *s; - if (h->root.root.type == bfd_link_hash_warning) - h = (struct elf_m68k_link_hash_entry *) h->root.root.u.i.link; + if (h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; - if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0 || (!info->symbolic - && (h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)) + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)) { if ((info->flags & DF_TEXTREL) == 0) { /* Look for relocations against read-only sections. */ - for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) + for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) if ((s->section->flags & SEC_READONLY) != 0) { info->flags |= DF_TEXTREL; break; } } + return TRUE; } - for (s = h->pcrel_relocs_copied; s != NULL; s = s->next) + for (s = elf_m68k_hash_entry (h)->pcrel_relocs_copied; + s != NULL; + s = s->next) s->section->_raw_size -= s->count * sizeof (Elf32_External_Rela); return TRUE; @@ -1466,7 +1453,6 @@ elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 1399f00..cf705d5 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -261,9 +261,11 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -1401,7 +1403,7 @@ static const struct elf_reloc_map mips_reloc_map[] = { BFD_RELOC_GPREL16, R_MIPS_GPREL16 }, { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL }, { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 }, - { BFD_RELOC_16_PCREL, R_MIPS_PC16 }, + { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 }, { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 }, { BFD_RELOC_GPREL32, R_MIPS_GPREL32 }, { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 }, @@ -1458,7 +1460,7 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code) return &elf_mips_gnu_rel_hi16; case BFD_RELOC_PCREL_LO16: return &elf_mips_gnu_rel_lo16; - case BFD_RELOC_16_PCREL_S2: + case BFD_RELOC_MIPSEMB_16_PCREL_S2: return &elf_mips_gnu_rel16_s2; case BFD_RELOC_64_PCREL: return &elf_mips_gnu_pcrel64; diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index acd9d84..9947af8 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -3,21 +3,21 @@ Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file is based on a preliminary PowerPC ELF ABI. The information may not match the final PowerPC ELF ABI. It includes @@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "libbfd.h" #include "elf-bfd.h" #include "elf/ppc.h" +#include "elf32-ppc.h" /* RELA relocations are used here. */ @@ -53,6 +54,8 @@ static bfd_boolean ppc_elf_relax_section PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *)); static bfd_reloc_status_type ppc_elf_addr16_ha_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +static bfd_reloc_status_type ppc_elf_unhandled_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_boolean ppc_elf_object_p PARAMS ((bfd *)); static bfd_boolean ppc_elf_set_private_flags @@ -63,7 +66,7 @@ static int ppc_elf_additional_program_headers PARAMS ((bfd *)); static bfd_boolean ppc_elf_modify_segment_map PARAMS ((bfd *)); -static asection *ppc_elf_create_got +static bfd_boolean ppc_elf_create_got PARAMS ((bfd *, struct bfd_link_info *)); static bfd_boolean ppc_elf_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); @@ -74,10 +77,14 @@ static bfd_boolean ppc_elf_fake_sections static elf_linker_section_t *ppc_elf_create_linker_section PARAMS ((bfd *abfd, struct bfd_link_info *info, enum elf_linker_section_enum)); +static bfd_boolean update_local_sym_info + PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned long, int)); +static void bad_shared_reloc + PARAMS ((bfd *, enum elf_ppc_reloc_type)); static bfd_boolean ppc_elf_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); -static asection * ppc_elf_gc_mark_hook +static asection *ppc_elf_gc_mark_hook PARAMS ((asection *sec, struct bfd_link_info *info, Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, Elf_Internal_Sym *sym)); static bfd_boolean ppc_elf_gc_sweep_hook @@ -110,13 +117,15 @@ static bfd_boolean ppc_elf_grok_prstatus static bfd_boolean ppc_elf_grok_psinfo PARAMS ((bfd *abfd, Elf_Internal_Note *note)); -#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */ -#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */ -#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */ +/* Branch prediction bit for branch taken relocs. */ +#define BRANCH_PREDICT_BIT 0x200000 +/* Mask to set RA in memory instructions. */ +#define RA_REGISTER_MASK 0x001f0000 +/* Value to shift register by to insert RA. */ +#define RA_REGISTER_SHIFT 16 /* The name of the dynamic interpreter. This is put in the .interp section. */ - #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" /* The size in bytes of an entry in the procedure linkage table. */ @@ -128,6 +137,15 @@ static bfd_boolean ppc_elf_grok_psinfo /* The number of single-slot PLT entries (the rest use two slots). */ #define PLT_NUM_SINGLE_ENTRIES 8192 +/* Some nop instructions. */ +#define NOP 0x60000000 +#define CROR_151515 0x4def7b82 +#define CROR_313131 0x4ffffb82 + +/* Offset of tp and dtp pointers from start of TLS block. */ +#define TP_OFFSET 0x7000 +#define DTP_OFFSET 0x8000 + /* Will references to this symbol always reference the symbol in this object? */ #define SYMBOL_REFERENCES_LOCAL(INFO, H) \ @@ -161,16 +179,32 @@ struct ppc_elf_dyn_relocs /* Total number of relocs copied for the input section. */ bfd_size_type count; + + /* Number of pc-relative relocs copied for the input section. */ + bfd_size_type pc_count; }; /* PPC ELF linker hash entry. */ struct ppc_elf_link_hash_entry { - struct elf_link_hash_entry root; + struct elf_link_hash_entry elf; /* Track dynamic relocs copied for this symbol. */ struct ppc_elf_dyn_relocs *dyn_relocs; + + /* Contexts in which symbol is used in the GOT (or TOC). + TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the + corresponding relocs are encountered during check_relocs. + tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to + indicate the corresponding GOT entry type is not needed. */ +#define TLS_GD 1 /* GD reloc. */ +#define TLS_LD 2 /* LD reloc. */ +#define TLS_TPREL 4 /* TPREL reloc, => IE. */ +#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ +#define TLS_TLS 16 /* Any TLS reloc. */ +#define TLS_TPRELGD 32 /* TPREL reloc resulting from GD->IE. */ + char tls_mask; }; #define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent)) @@ -179,7 +213,31 @@ struct ppc_elf_link_hash_entry struct ppc_elf_link_hash_table { - struct elf_link_hash_table root; + struct elf_link_hash_table elf; + + /* Short-cuts to get to dynamic linker sections. */ + asection *got; + asection *relgot; + asection *plt; + asection *relplt; + asection *dynbss; + asection *relbss; + asection *dynsbss; + asection *relsbss; + elf_linker_section_t *sdata; + elf_linker_section_t *sdata2; + + /* Short-cut to first output tls section. */ + asection *tls_sec; + + /* Shortcut to .__tls_get_addr. */ + struct elf_link_hash_entry *tls_get_addr; + + /* TLS local dynamic got entry handling. */ + union { + bfd_signed_vma refcount; + bfd_vma offset; + } tlsld_got; /* Small local sym to section mapping cache. */ struct sym_sec_cache sym_sec; @@ -211,7 +269,10 @@ ppc_elf_link_hash_newfunc (entry, table, string) /* Call the allocation method of the superclass. */ entry = _bfd_elf_link_hash_newfunc (entry, table, string); if (entry != NULL) - ppc_elf_hash_entry (entry)->dyn_relocs = NULL; + { + ppc_elf_hash_entry (entry)->dyn_relocs = NULL; + ppc_elf_hash_entry (entry)->tls_mask = 0; + } return entry; } @@ -229,16 +290,29 @@ ppc_elf_link_hash_table_create (abfd) if (ret == NULL) return NULL; - if (! _bfd_elf_link_hash_table_init (&ret->root, abfd, + if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, ppc_elf_link_hash_newfunc)) { free (ret); return NULL; } + ret->got = NULL; + ret->relgot = NULL; + ret->plt = NULL; + ret->relplt = NULL; + ret->dynbss = NULL; + ret->relbss = NULL; + ret->dynsbss = NULL; + ret->relsbss = NULL; + ret->sdata = NULL; + ret->sdata2 = NULL; + ret->tls_sec = NULL; + ret->tls_get_addr = NULL; + ret->tlsld_got.refcount = 0; ret->sym_sec.abfd = NULL; - return &ret->root.root; + return &ret->elf.root; } /* Copy the extra info we tack onto an elf_link_hash_entry. */ @@ -272,6 +346,7 @@ ppc_elf_copy_indirect_symbol (bed, dir, ind) for (q = edir->dyn_relocs; q != NULL; q = q->next) if (q->sec == p->sec) { + q->pc_count += p->pc_count; q->count += p->count; *pp = p->next; break; @@ -286,6 +361,8 @@ ppc_elf_copy_indirect_symbol (bed, dir, ind) eind->dyn_relocs = NULL; } + edir->tls_mask |= eind->tls_mask; + _bfd_elf_link_hash_copy_indirect (bed, dir, ind); } @@ -878,10 +955,440 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* Marker reloc for TLS. */ + HOWTO (R_PPC_TLS, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC_TLS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes the load module index of the load module that contains the + definition of its TLS sym. */ + HOWTO (R_PPC_DTPMOD32, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPMOD32", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes a dtv-relative displacement, the difference between the value + of sym+add and the base address of the thread-local storage block that + contains the definition of sym, minus 0x8000. */ + HOWTO (R_PPC_DTPREL32, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPREL32", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit dtprel reloc. */ + HOWTO (R_PPC_DTPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16, but no overflow. */ + HOWTO (R_PPC_DTPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_DTPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_DTPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_DTPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes a tp-relative displacement, the difference between the value of + sym+add and the value of the thread pointer (r13). */ + HOWTO (R_PPC_TPREL32, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_TPREL32", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit tprel reloc. */ + HOWTO (R_PPC_TPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_TPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16, but no overflow. */ + HOWTO (R_PPC_TPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_TPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_TPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_TPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_TPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_TPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates two contiguous entries in the GOT to hold a tls_index structure, + with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset + to the first entry. */ + HOWTO (R_PPC_GOT_TLSGD16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSGD16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16, but no overflow. */ + HOWTO (R_PPC_GOT_TLSGD16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSGD16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_GOT_TLSGD16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSGD16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_GOT_TLSGD16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSGD16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates two contiguous entries in the GOT to hold a tls_index structure, + with values (sym+add)@dtpmod and zero, and computes the offset to the + first entry. */ + HOWTO (R_PPC_GOT_TLSLD16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSLD16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16, but no overflow. */ + HOWTO (R_PPC_GOT_TLSLD16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSLD16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_GOT_TLSLD16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSLD16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_GOT_TLSLD16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TLSLD16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes + the offset to the entry. */ + HOWTO (R_PPC_GOT_DTPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_DTPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16, but no overflow. */ + HOWTO (R_PPC_GOT_DTPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_DTPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_GOT_DTPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_DTPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_GOT_DTPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_DTPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the + offset to the entry. */ + HOWTO (R_PPC_GOT_TPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16, but no overflow. */ + HOWTO (R_PPC_GOT_TPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC_GOT_TPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC_GOT_TPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc_elf_unhandled_reloc, /* special_function */ + "R_PPC_GOT_TPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* The remaining relocs are from the Embedded ELF ABI, and are not in the SVR4 ELF ABI. */ - /* 32 bit value resulting from the addend minus the symbol */ + /* 32 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -896,7 +1403,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0xffffffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit value resulting from the addend minus the symbol */ + /* 16 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -911,7 +1418,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit value resulting from the addend minus the symbol */ + /* 16 bit value resulting from the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16_LO, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -926,7 +1433,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* The high order 16 bits of the addend minus the symbol */ + /* The high order 16 bits of the addend minus the symbol. */ HOWTO (R_PPC_EMB_NADDR16_HI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -960,7 +1467,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { /* 16 bit value resulting from allocating a 4 byte word to hold an address in the .sdata section, and returning the offset from - _SDA_BASE_ for that relocation */ + _SDA_BASE_ for that relocation. */ HOWTO (R_PPC_EMB_SDAI16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -977,7 +1484,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { /* 16 bit value resulting from allocating a 4 byte word to hold an address in the .sdata2 section, and returning the offset from - _SDA2_BASE_ for that relocation */ + _SDA2_BASE_ for that relocation. */ HOWTO (R_PPC_EMB_SDA2I16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1049,7 +1556,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* GNU extension to record C++ vtable hierarchy */ + /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_PPC_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1064,7 +1571,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0, /* dst_mask */ FALSE), /* pcrel_offset */ - /* GNU extension to record C++ vtable member usage */ + /* GNU extension to record C++ vtable member usage. */ HOWTO (R_PPC_GNU_VTENTRY, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1079,7 +1586,7 @@ static reloc_howto_type ppc_elf_howto_raw[] = { 0, /* dst_mask */ FALSE), /* pcrel_offset */ - /* Phony reloc to handle AIX style TOC entries */ + /* Phony reloc to handle AIX style TOC entries. */ HOWTO (R_PPC_TOC16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1129,8 +1636,7 @@ ppc_elf_howto_init () 3/ Conditional forward branches - Ensure that the "inverse prediction bit" is set (ensure it is predicted taken). 4/ Conditional register branches - Ensure that the "y bit" is set - (ensure it is predicted taken). -*/ + (ensure it is predicted taken). */ /* Sort sections by address. */ @@ -1167,7 +1673,7 @@ ppc_elf_relax_section (abfd, isec, link_info, again) /* If needed, initialize this section's cooked size. */ if (isec->_cooked_size == 0) - isec->_cooked_size = isec->_raw_size; + isec->_cooked_size = isec->_raw_size; /* We're only interested in text sections which overlap the troublesome area at the end of a page. */ @@ -1179,7 +1685,7 @@ ppc_elf_relax_section (abfd, isec, link_info, again) /* Get the section contents. */ /* Get cached copy if it exists. */ if (elf_section_data (isec)->this_hdr.contents != NULL) - contents = elf_section_data (isec)->this_hdr.contents; + contents = elf_section_data (isec)->this_hdr.contents; else { /* Go get them off disk. */ @@ -1197,55 +1703,58 @@ ppc_elf_relax_section (abfd, isec, link_info, again) comb_count = 0; if (isec->reloc_count) { - unsigned n; + unsigned n; bfd_size_type amt; - /* Get a copy of the native relocations. */ - internal_relocs = _bfd_elf32_link_read_relocs ( - abfd, isec, (PTR) NULL, (Elf_Internal_Rela *) NULL, - link_info->keep_memory); - if (internal_relocs == NULL) - goto error_return; - if (! link_info->keep_memory) - free_relocs = internal_relocs; + /* Get a copy of the native relocations. */ + internal_relocs + = _bfd_elf32_link_read_relocs (abfd, isec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + link_info->keep_memory); + if (internal_relocs == NULL) + goto error_return; + if (! link_info->keep_memory) + free_relocs = internal_relocs; - /* Setup a faster access method for the reloc info we need. */ + /* Setup a faster access method for the reloc info we need. */ amt = isec->reloc_count; amt *= sizeof (Elf_Internal_Rela*); - rela_comb = (Elf_Internal_Rela**) bfd_malloc (amt); - if (rela_comb == NULL) - goto error_return; - for (n = 0; n < isec->reloc_count; ++n) - { - long r_type; - - r_type = ELF32_R_TYPE (internal_relocs[n].r_info); - if (r_type < 0 || r_type >= (int) R_PPC_max) - goto error_return; - - /* Prologue constants are sometimes present in the ".text" - sections and they can be identified by their associated relocation. - We don't want to process those words and some others which - can also be identified by their relocations. However, not all - conditional branches will have a relocation so we will - only ignore words that 1) have a reloc, and 2) the reloc - is not applicable to a conditional branch. - The array rela_comb is built here for use in the EOP scan loop. */ - switch (r_type) - { - case R_PPC_ADDR14_BRNTAKEN: /* absolute, predicted not taken */ - case R_PPC_REL14: /* relative cond. br. */ - case R_PPC_REL14_BRNTAKEN: /* rel. cond. br., predicted not taken */ - /* We should check the instruction. */ - break; - default: - /* The word is not a conditional branch - ignore it. */ - rela_comb[comb_count++] = &internal_relocs[n]; - break; - } - } - if (comb_count > 1) - qsort (rela_comb, (size_t) comb_count, sizeof (int), ppc_elf_sort_rela); + rela_comb = (Elf_Internal_Rela**) bfd_malloc (amt); + if (rela_comb == NULL) + goto error_return; + for (n = 0; n < isec->reloc_count; ++n) + { + long r_type; + + r_type = ELF32_R_TYPE (internal_relocs[n].r_info); + if (r_type < 0 || r_type >= (int) R_PPC_max) + goto error_return; + + /* Prologue constants are sometimes present in the ".text" + sections and they can be identified by their associated + relocation. We don't want to process those words and + some others which can also be identified by their + relocations. However, not all conditional branches will + have a relocation so we will only ignore words that + 1) have a reloc, and 2) the reloc is not applicable to a + conditional branch. The array rela_comb is built here + for use in the EOP scan loop. */ + switch (r_type) + { + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_REL14: + case R_PPC_REL14_BRNTAKEN: + /* We should check the instruction. */ + break; + default: + /* The word is not a conditional branch - ignore it. */ + rela_comb[comb_count++] = &internal_relocs[n]; + break; + } + } + if (comb_count > 1) + qsort (rela_comb, (size_t) comb_count, sizeof (int), + ppc_elf_sort_rela); } /* Enumerate each EOP region that overlaps this section. */ @@ -1253,99 +1762,104 @@ ppc_elf_relax_section (abfd, isec, link_info, again) dot = end_page = (isec->vma | (PAGESIZE - 1)) + 1; dot -= link_info->mpc860c0; section_modified = FALSE; - if (dot < isec->vma) /* Increment the start position if this section */ - dot = isec->vma; /* begins in the middle of its first EOP region. */ + /* Increment the start position if this section begins in the + middle of its first EOP region. */ + if (dot < isec->vma) + dot = isec->vma; for (; - dot < end_section; - dot += PAGESIZE, end_page += PAGESIZE) - { - - /* Check each word in this EOP region. */ - for (; dot < end_page; dot += 4) - { - bfd_vma isec_offset; - unsigned long insn; - bfd_boolean skip, modified; - - /* Don't process this word if there is a relocation for it and - the relocation indicates the word is not a conditional branch. */ - skip = FALSE; - isec_offset = dot - isec->vma; - for (; comb_curr<comb_count; ++comb_curr) - { - bfd_vma r_offset; - - r_offset = rela_comb[comb_curr]->r_offset; - if (r_offset >= isec_offset) - { - if (r_offset == isec_offset) skip = TRUE; - break; - } - } - if (skip) continue; - - /* Check the current word for a problematic conditional branch. */ + dot < end_section; + dot += PAGESIZE, end_page += PAGESIZE) + { + /* Check each word in this EOP region. */ + for (; dot < end_page; dot += 4) + { + bfd_vma isec_offset; + unsigned long insn; + bfd_boolean skip, modified; + + /* Don't process this word if there is a relocation for it + and the relocation indicates the word is not a + conditional branch. */ + skip = FALSE; + isec_offset = dot - isec->vma; + for (; comb_curr<comb_count; ++comb_curr) + { + bfd_vma r_offset; + + r_offset = rela_comb[comb_curr]->r_offset; + if (r_offset >= isec_offset) + { + if (r_offset == isec_offset) skip = TRUE; + break; + } + } + if (skip) continue; + + /* Check the current word for a problematic conditional + branch. */ #define BO0(insn) ((insn) & 0x02000000) #define BO2(insn) ((insn) & 0x00800000) #define BO4(insn) ((insn) & 0x00200000) - insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset); - modified = FALSE; - if ((insn & 0xFc000000) == 0x40000000) - { - /* Instruction is BCx */ - if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) - { - bfd_vma target; - /* This branch is predicted as "normal". - If this is a forward branch, it is problematic. */ - - target = insn & 0x0000Fffc; /*extract*/ - target = (target ^ 0x8000) - 0x8000; /*sign extend*/ - if ((insn & 0x00000002) == 0) - target += dot; /*convert to abs*/ - if (target > dot) - { - insn |= 0x00200000; /* set the prediction bit */ - modified = TRUE; - } - } - } - else if ((insn & 0xFc00Fffe) == 0x4c000420) - { - /* Instruction is BCCTRx */ - if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) + insn = (unsigned long) bfd_get_32 (abfd, contents + isec_offset); + modified = FALSE; + if ((insn & 0xFc000000) == 0x40000000) + { + /* Instruction is BCx */ + if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) + { + bfd_vma target; + + /* This branch is predicted as "normal". + If this is a forward branch, it is problematic. */ + target = insn & 0x0000Fffc; + target = (target ^ 0x8000) - 0x8000; + if ((insn & 0x00000002) == 0) + /* Convert to abs. */ + target += dot; + if (target > dot) + { + /* Set the prediction bit. */ + insn |= 0x00200000; + modified = TRUE; + } + } + } + else if ((insn & 0xFc00Fffe) == 0x4c000420) + { + /* Instruction is BCCTRx. */ + if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) { /* This branch is predicted as not-taken. - If this is a forward branch, it is problematic. - Since we can't tell statically if it will branch forward, - always set the prediction bit. */ - insn |= 0x00200000; /* set the prediction bit */ - modified = TRUE; + If this is a forward branch, it is problematic. + Since we can't tell statically if it will branch + forward, always set the prediction bit. */ + insn |= 0x00200000; + modified = TRUE; } - } - else if ((insn & 0xFc00Fffe) == 0x4c000020) - { - /* Instruction is BCLRx */ - if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) + } + else if ((insn & 0xFc00Fffe) == 0x4c000020) + { + /* Instruction is BCLRx */ + if ((!BO0(insn) || !BO2(insn)) && !BO4(insn)) { /* This branch is predicted as not-taken. - If this is a forward branch, it is problematic. - Since we can't tell statically if it will branch forward, - always set the prediction bit. */ - insn |= 0x00200000; /* set the prediction bit */ - modified = TRUE; + If this is a forward branch, it is problematic. + Since we can't tell statically if it will branch + forward, always set the prediction bit. */ + insn |= 0x00200000; + modified = TRUE; } - } + } #undef BO0 #undef BO2 #undef BO4 - if (modified) - { - bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset); + if (modified) + { + bfd_put_32 (abfd, (bfd_vma) insn, contents + isec_offset); section_modified = TRUE; - } - } - } + } + } + } if (section_modified) { elf_section_data (isec)->this_hdr.contents = contents; @@ -1379,7 +1893,7 @@ ppc_elf_relax_section (abfd, isec, link_info, again) return TRUE; -error_return: + error_return: if (rela_comb != NULL) free (rela_comb); if (free_relocs != NULL) @@ -1394,7 +1908,7 @@ ppc_elf_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { - enum elf_ppc_reloc_type ppc_reloc = R_PPC_NONE; + enum elf_ppc_reloc_type r; if (!ppc_elf_howto_table[R_PPC_ADDR32]) /* Initialize howto table if needed. */ @@ -1405,62 +1919,90 @@ ppc_elf_reloc_type_lookup (abfd, code) default: return (reloc_howto_type *) NULL; - case BFD_RELOC_NONE: ppc_reloc = R_PPC_NONE; break; - case BFD_RELOC_32: ppc_reloc = R_PPC_ADDR32; break; - case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC_ADDR24; break; - case BFD_RELOC_16: ppc_reloc = R_PPC_ADDR16; break; - case BFD_RELOC_LO16: ppc_reloc = R_PPC_ADDR16_LO; break; - case BFD_RELOC_HI16: ppc_reloc = R_PPC_ADDR16_HI; break; - case BFD_RELOC_HI16_S: ppc_reloc = R_PPC_ADDR16_HA; break; - case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC_ADDR14; break; - case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC_ADDR14_BRTAKEN; break; - case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC_ADDR14_BRNTAKEN; break; - case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC_REL24; break; - case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC_REL14; break; - case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC_REL14_BRTAKEN; break; - case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC_REL14_BRNTAKEN; break; - case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC_GOT16; break; - case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC_GOT16_LO; break; - case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC_GOT16_HI; break; - case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC_GOT16_HA; break; - case BFD_RELOC_24_PLT_PCREL: ppc_reloc = R_PPC_PLTREL24; break; - case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC_COPY; break; - case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC_GLOB_DAT; break; - case BFD_RELOC_PPC_LOCAL24PC: ppc_reloc = R_PPC_LOCAL24PC; break; - case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC_REL32; break; - case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC_PLT32; break; - case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC_PLTREL32; break; - case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC_PLT16_LO; break; - case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break; - case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break; - case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break; - case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC_SECTOFF; break; - case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break; - case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break; - case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break; - case BFD_RELOC_CTOR: ppc_reloc = R_PPC_ADDR32; break; - case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC_TOC16; break; - case BFD_RELOC_PPC_EMB_NADDR32: ppc_reloc = R_PPC_EMB_NADDR32; break; - case BFD_RELOC_PPC_EMB_NADDR16: ppc_reloc = R_PPC_EMB_NADDR16; break; - case BFD_RELOC_PPC_EMB_NADDR16_LO: ppc_reloc = R_PPC_EMB_NADDR16_LO; break; - case BFD_RELOC_PPC_EMB_NADDR16_HI: ppc_reloc = R_PPC_EMB_NADDR16_HI; break; - case BFD_RELOC_PPC_EMB_NADDR16_HA: ppc_reloc = R_PPC_EMB_NADDR16_HA; break; - case BFD_RELOC_PPC_EMB_SDAI16: ppc_reloc = R_PPC_EMB_SDAI16; break; - case BFD_RELOC_PPC_EMB_SDA2I16: ppc_reloc = R_PPC_EMB_SDA2I16; break; - case BFD_RELOC_PPC_EMB_SDA2REL: ppc_reloc = R_PPC_EMB_SDA2REL; break; - case BFD_RELOC_PPC_EMB_SDA21: ppc_reloc = R_PPC_EMB_SDA21; break; - case BFD_RELOC_PPC_EMB_MRKREF: ppc_reloc = R_PPC_EMB_MRKREF; break; - case BFD_RELOC_PPC_EMB_RELSEC16: ppc_reloc = R_PPC_EMB_RELSEC16; break; - case BFD_RELOC_PPC_EMB_RELST_LO: ppc_reloc = R_PPC_EMB_RELST_LO; break; - case BFD_RELOC_PPC_EMB_RELST_HI: ppc_reloc = R_PPC_EMB_RELST_HI; break; - case BFD_RELOC_PPC_EMB_RELST_HA: ppc_reloc = R_PPC_EMB_RELST_HA; break; - case BFD_RELOC_PPC_EMB_BIT_FLD: ppc_reloc = R_PPC_EMB_BIT_FLD; break; - case BFD_RELOC_PPC_EMB_RELSDA: ppc_reloc = R_PPC_EMB_RELSDA; break; - case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC_GNU_VTINHERIT; break; - case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC_GNU_VTENTRY; break; + case BFD_RELOC_NONE: r = R_PPC_NONE; break; + case BFD_RELOC_32: r = R_PPC_ADDR32; break; + case BFD_RELOC_PPC_BA26: r = R_PPC_ADDR24; break; + case BFD_RELOC_16: r = R_PPC_ADDR16; break; + case BFD_RELOC_LO16: r = R_PPC_ADDR16_LO; break; + case BFD_RELOC_HI16: r = R_PPC_ADDR16_HI; break; + case BFD_RELOC_HI16_S: r = R_PPC_ADDR16_HA; break; + case BFD_RELOC_PPC_BA16: r = R_PPC_ADDR14; break; + case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC_ADDR14_BRTAKEN; break; + case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC_ADDR14_BRNTAKEN; break; + case BFD_RELOC_PPC_B26: r = R_PPC_REL24; break; + case BFD_RELOC_PPC_B16: r = R_PPC_REL14; break; + case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC_REL14_BRTAKEN; break; + case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC_REL14_BRNTAKEN; break; + case BFD_RELOC_16_GOTOFF: r = R_PPC_GOT16; break; + case BFD_RELOC_LO16_GOTOFF: r = R_PPC_GOT16_LO; break; + case BFD_RELOC_HI16_GOTOFF: r = R_PPC_GOT16_HI; break; + case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC_GOT16_HA; break; + case BFD_RELOC_24_PLT_PCREL: r = R_PPC_PLTREL24; break; + case BFD_RELOC_PPC_COPY: r = R_PPC_COPY; break; + case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC_GLOB_DAT; break; + case BFD_RELOC_PPC_LOCAL24PC: r = R_PPC_LOCAL24PC; break; + case BFD_RELOC_32_PCREL: r = R_PPC_REL32; break; + case BFD_RELOC_32_PLTOFF: r = R_PPC_PLT32; break; + case BFD_RELOC_32_PLT_PCREL: r = R_PPC_PLTREL32; break; + case BFD_RELOC_LO16_PLTOFF: r = R_PPC_PLT16_LO; break; + case BFD_RELOC_HI16_PLTOFF: r = R_PPC_PLT16_HI; break; + case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC_PLT16_HA; break; + case BFD_RELOC_GPREL16: r = R_PPC_SDAREL16; break; + case BFD_RELOC_16_BASEREL: r = R_PPC_SECTOFF; break; + case BFD_RELOC_LO16_BASEREL: r = R_PPC_SECTOFF_LO; break; + case BFD_RELOC_HI16_BASEREL: r = R_PPC_SECTOFF_HI; break; + case BFD_RELOC_HI16_S_BASEREL: r = R_PPC_SECTOFF_HA; break; + case BFD_RELOC_CTOR: r = R_PPC_ADDR32; break; + case BFD_RELOC_PPC_TOC16: r = R_PPC_TOC16; break; + case BFD_RELOC_PPC_TLS: r = R_PPC_TLS; break; + case BFD_RELOC_PPC_DTPMOD: r = R_PPC_DTPMOD32; break; + case BFD_RELOC_PPC_TPREL16: r = R_PPC_TPREL16; break; + case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC_TPREL16_LO; break; + case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC_TPREL16_HI; break; + case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC_TPREL16_HA; break; + case BFD_RELOC_PPC_TPREL: r = R_PPC_TPREL32; break; + case BFD_RELOC_PPC_DTPREL16: r = R_PPC_DTPREL16; break; + case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC_DTPREL16_LO; break; + case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC_DTPREL16_HI; break; + case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC_DTPREL16_HA; break; + case BFD_RELOC_PPC_DTPREL: r = R_PPC_DTPREL32; break; + case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC_GOT_TLSGD16; break; + case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC_GOT_TLSGD16_LO; break; + case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC_GOT_TLSGD16_HI; break; + case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC_GOT_TLSGD16_HA; break; + case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC_GOT_TLSLD16; break; + case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC_GOT_TLSLD16_LO; break; + case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC_GOT_TLSLD16_HI; break; + case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC_GOT_TLSLD16_HA; break; + case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC_GOT_TPREL16; break; + case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC_GOT_TPREL16_LO; break; + case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC_GOT_TPREL16_HI; break; + case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC_GOT_TPREL16_HA; break; + case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC_GOT_DTPREL16; break; + case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC_GOT_DTPREL16_LO; break; + case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC_GOT_DTPREL16_HI; break; + case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC_GOT_DTPREL16_HA; break; + case BFD_RELOC_PPC_EMB_NADDR32: r = R_PPC_EMB_NADDR32; break; + case BFD_RELOC_PPC_EMB_NADDR16: r = R_PPC_EMB_NADDR16; break; + case BFD_RELOC_PPC_EMB_NADDR16_LO: r = R_PPC_EMB_NADDR16_LO; break; + case BFD_RELOC_PPC_EMB_NADDR16_HI: r = R_PPC_EMB_NADDR16_HI; break; + case BFD_RELOC_PPC_EMB_NADDR16_HA: r = R_PPC_EMB_NADDR16_HA; break; + case BFD_RELOC_PPC_EMB_SDAI16: r = R_PPC_EMB_SDAI16; break; + case BFD_RELOC_PPC_EMB_SDA2I16: r = R_PPC_EMB_SDA2I16; break; + case BFD_RELOC_PPC_EMB_SDA2REL: r = R_PPC_EMB_SDA2REL; break; + case BFD_RELOC_PPC_EMB_SDA21: r = R_PPC_EMB_SDA21; break; + case BFD_RELOC_PPC_EMB_MRKREF: r = R_PPC_EMB_MRKREF; break; + case BFD_RELOC_PPC_EMB_RELSEC16: r = R_PPC_EMB_RELSEC16; break; + case BFD_RELOC_PPC_EMB_RELST_LO: r = R_PPC_EMB_RELST_LO; break; + case BFD_RELOC_PPC_EMB_RELST_HI: r = R_PPC_EMB_RELST_HI; break; + case BFD_RELOC_PPC_EMB_RELST_HA: r = R_PPC_EMB_RELST_HA; break; + case BFD_RELOC_PPC_EMB_BIT_FLD: r = R_PPC_EMB_BIT_FLD; break; + case BFD_RELOC_PPC_EMB_RELSDA: r = R_PPC_EMB_RELSDA; break; + case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break; + case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break; } - return ppc_elf_howto_table[(int) ppc_reloc]; + return ppc_elf_howto_table[(int) r]; }; /* Set the howto pointer for a PowerPC ELF reloc. */ @@ -1517,6 +2059,34 @@ ppc_elf_addr16_ha_reloc (abfd, reloc_entry, symbol, data, input_section, return bfd_reloc_continue; } +static bfd_reloc_status_type +ppc_elf_unhandled_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) + bfd *abfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + /* If this is a relocatable link (output_bfd test tells us), just + call the generic function. Any adjustment will be done at final + link time. */ + if (output_bfd != NULL) + return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); + + if (error_message != NULL) + { + static char buf[60]; + sprintf (buf, "generic linker can't handle %s", + reloc_entry->howto->name); + *error_message = buf; + } + return bfd_reloc_dangerous; +} + /* Fix bad default arch selected for a 32 bit input bfd when the default is 64 bit. */ @@ -1554,7 +2124,8 @@ ppc_elf_set_private_flags (abfd, flags) } /* Merge backend specific data from an object file to the output - object file when linking */ + object file when linking. */ + static bfd_boolean ppc_elf_merge_private_bfd_data (ibfd, obfd) bfd *ibfd; @@ -1564,7 +2135,7 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd) flagword new_flags; bfd_boolean error; - /* Check if we have the same endianess */ + /* Check if we have the same endianess. */ if (! _bfd_generic_verify_endian_match (ibfd, obfd)) return FALSE; @@ -1574,19 +2145,22 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd) new_flags = elf_elfheader (ibfd)->e_flags; old_flags = elf_elfheader (obfd)->e_flags; - if (!elf_flags_init (obfd)) /* First call, no flags set */ + if (!elf_flags_init (obfd)) { + /* First call, no flags set. */ elf_flags_init (obfd) = TRUE; elf_elfheader (obfd)->e_flags = new_flags; } - else if (new_flags == old_flags) /* Compatible flags are ok */ + /* Compatible flags are ok. */ + else if (new_flags == old_flags) ; - else /* Incompatible flags */ + /* Incompatible flags. */ + else { - /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked - with either. */ + /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib + to be linked with either. */ error = FALSE; if ((new_flags & EF_PPC_RELOCATABLE) != 0 && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0) @@ -1610,19 +2184,20 @@ ppc_elf_merge_private_bfd_data (ibfd, obfd) elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB; /* The output is -mrelocatable iff it can't be -mrelocatable-lib, - but each input file is either -mrelocatable or -mrelocatable-lib. */ + but each input file is either -mrelocatable or -mrelocatable-lib. */ if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB) && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)) && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))) elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE; - /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */ + /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if + any module uses it. */ elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB); - new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); - old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); + new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); + old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB); - /* Warn about any other mismatches */ + /* Warn about any other mismatches. */ if (new_flags != old_flags) { error = TRUE; @@ -1695,11 +2270,11 @@ ppc_elf_create_linker_section (abfd, info, which) bfd *dynobj = elf_hash_table (info)->dynobj; elf_linker_section_t *lsect; - /* Record the first bfd section that needs the special section */ + /* Record the first bfd section that needs the special section. */ if (!dynobj) dynobj = elf_hash_table (info)->dynobj = abfd; - /* If this is the first time, create the section */ + /* If this is the first time, create the section. */ lsect = elf_linker_section (dynobj, which); if (!lsect) { @@ -1794,26 +2369,38 @@ ppc_elf_modify_segment_map (abfd) /* The powerpc .got has a blrl instruction in it. Mark it executable. */ -static asection * +static bfd_boolean ppc_elf_create_got (abfd, info) bfd *abfd; struct bfd_link_info *info; { - register asection *s; + struct ppc_elf_link_hash_table *htab; + asection *s; flagword flags; if (!_bfd_elf_create_got_section (abfd, info)) - return NULL; + return FALSE; - s = bfd_get_section_by_name (abfd, ".got"); + htab = ppc_elf_hash_table (info); + htab->got = s = bfd_get_section_by_name (abfd, ".got"); if (s == NULL) abort (); flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); if (!bfd_set_section_flags (abfd, s, flags)) - return NULL; - return s; + return FALSE; + + htab->relgot = bfd_make_section (abfd, ".rela.got"); + if (!htab->relgot + || ! bfd_set_section_flags (abfd, htab->relgot, + (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED + | SEC_READONLY)) + || ! bfd_set_section_alignment (abfd, htab->relgot, 2)) + return FALSE; + + return TRUE; } /* We have to create .dynsbss and .rela.sbss here so that they get mapped @@ -1825,7 +2412,8 @@ ppc_elf_create_dynamic_sections (abfd, info) bfd *abfd; struct bfd_link_info *info; { - register asection *s; + struct ppc_elf_link_hash_table *htab; + asection *s; flagword flags; if (!ppc_elf_create_got (abfd, info)) @@ -1837,21 +2425,25 @@ ppc_elf_create_dynamic_sections (abfd, info) flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); - s = bfd_make_section (abfd, ".dynsbss"); + htab = ppc_elf_hash_table (info); + htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss"); + htab->dynsbss = s = bfd_make_section (abfd, ".dynsbss"); if (s == NULL || ! bfd_set_section_flags (abfd, s, SEC_ALLOC)) return FALSE; if (! info->shared) { - s = bfd_make_section (abfd, ".rela.sbss"); + htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss"); + htab->relsbss = s = bfd_make_section (abfd, ".rela.sbss"); if (s == NULL || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY) || ! bfd_set_section_alignment (abfd, s, 2)) return FALSE; } - s = bfd_get_section_by_name (abfd, ".plt"); + htab->relplt = bfd_get_section_by_name (abfd, ".rela.plt"); + htab->plt = s = bfd_get_section_by_name (abfd, ".plt"); if (s == NULL) abort (); @@ -1859,6 +2451,12 @@ ppc_elf_create_dynamic_sections (abfd, info) return bfd_set_section_flags (abfd, s, flags); } +/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid + copying dynamic variables from a shared lib into an app's dynbss + section, and instead use a dynamic relocation to point into the + shared lib. */ +#define ELIMINATE_COPY_RELOCS 1 + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -1870,17 +2468,18 @@ ppc_elf_adjust_dynamic_symbol (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h; { - bfd *dynobj = elf_hash_table (info)->dynobj; + struct ppc_elf_link_hash_table *htab; asection *s; unsigned int power_of_two; - bfd_vma plt_offset; #ifdef DEBUG - fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", h->root.root.string); + fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called for %s\n", + h->root.root.string); #endif /* Make sure we know what is going on here. */ - BFD_ASSERT (dynobj != NULL + htab = ppc_elf_hash_table (info); + BFD_ASSERT (htab->elf.dynobj != NULL && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) || h->weakdef != NULL || ((h->elf_link_hash_flags @@ -1890,85 +2489,28 @@ ppc_elf_adjust_dynamic_symbol (info, h) && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))); - /* If this is a function, put it in the procedure linkage table. We - will fill in the contents of the procedure linkage table later, - when we know the address of the .got section. */ + /* Deal with function syms. */ if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { - if (! elf_hash_table (info)->dynamic_sections_created + /* Clear procedure linkage table information for any symbol that + won't need a .plt entry. */ + if (! htab->elf.dynamic_sections_created || SYMBOL_CALLS_LOCAL (info, h) - || (info->shared && h->plt.refcount <= 0)) + || h->plt.refcount <= 0) { /* A PLT entry is not required/allowed when: - 1. We are not using ld.so; because then the PLT entry - can't be set up, so we can't use one. + 1. We are not using ld.so; because then the PLT entry + can't be set up, so we can't use one. - 2. We know for certain that a call to this symbol - will go to this object. + 2. We know for certain that a call to this symbol + will go to this object. - 3. GC has rendered the entry unused. - Note, however, that in an executable all references to the - symbol go to the PLT, so we can't turn it off in that case. - ??? The correct thing to do here is to reference count - all uses of the symbol, not just those to the GOT or PLT. */ + 3. GC has rendered the entry unused. */ h->plt.offset = (bfd_vma) -1; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - return TRUE; } - - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return FALSE; - } - BFD_ASSERT (h->dynindx != -1); - - s = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (s != NULL); - - /* If this is the first .plt entry, make room for the special - first entry. */ - if (s->_raw_size == 0) - s->_raw_size += PLT_INITIAL_ENTRY_SIZE; - - /* The PowerPC PLT is actually composed of two parts, the first part - is 2 words (for a load and a jump), and then there is a remaining - word available at the end. */ - plt_offset = (PLT_INITIAL_ENTRY_SIZE - + (PLT_SLOT_SIZE - * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) - / PLT_ENTRY_SIZE))); - - /* If this symbol is not defined in a regular file, and we are - not generating a shared library, then set the symbol to this - location in the .plt. This is required to make function - pointers compare as equal between the normal executable and - the shared library. */ - if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - { - h->root.u.def.section = s; - h->root.u.def.value = plt_offset; - } - - h->plt.offset = plt_offset; - - /* Make room for this entry. After the 8192nd entry, room - for two entries is allocated. */ - if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE - >= PLT_NUM_SINGLE_ENTRIES) - s->_raw_size += 2 * PLT_ENTRY_SIZE; - else - s->_raw_size += PLT_ENTRY_SIZE; - - /* We also need to make an entry in the .rela.plt section. */ - s = bfd_get_section_by_name (dynobj, ".rela.plt"); - BFD_ASSERT (s != NULL); - s->_raw_size += sizeof (Elf32_External_Rela); - return TRUE; } else @@ -1996,6 +2538,30 @@ ppc_elf_adjust_dynamic_symbol (info, h) if (info->shared) return TRUE; + /* If there are no references to this symbol that do not use the + GOT, we don't need to generate a copy reloc. */ + if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) + return TRUE; + + if (ELIMINATE_COPY_RELOCS) + { + struct ppc_elf_dyn_relocs *p; + for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + { + s = p->sec->output_section; + if (s != NULL && (s->flags & SEC_READONLY) != 0) + break; + } + + /* If we didn't find any dynamic relocs in read-only sections, then + we'll be keeping the dynamic relocs and avoiding the copy reloc. */ + if (p == NULL) + { + h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + return TRUE; + } + } + /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be an entry for this symbol in the .dynsym section. The dynamic @@ -2010,10 +2576,10 @@ ppc_elf_adjust_dynamic_symbol (info, h) allocate it in .sbss. FIXME: It would be better to do this if and only if there were actually SDAREL relocs for that symbol. */ - if (h->size <= elf_gp_size (dynobj)) - s = bfd_get_section_by_name (dynobj, ".dynsbss"); + if (h->size <= elf_gp_size (htab->elf.dynobj)) + s = htab->dynsbss; else - s = bfd_get_section_by_name (dynobj, ".dynbss"); + s = htab->dynbss; BFD_ASSERT (s != NULL); /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to @@ -2024,10 +2590,10 @@ ppc_elf_adjust_dynamic_symbol (info, h) { asection *srel; - if (h->size <= elf_gp_size (dynobj)) - srel = bfd_get_section_by_name (dynobj, ".rela.sbss"); + if (h->size <= elf_gp_size (htab->elf.dynobj)) + srel = htab->relsbss; else - srel = bfd_get_section_by_name (dynobj, ".rela.bss"); + srel = htab->relbss; BFD_ASSERT (srel != NULL); srel->_raw_size += sizeof (Elf32_External_Rela); h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; @@ -2042,9 +2608,9 @@ ppc_elf_adjust_dynamic_symbol (info, h) /* Apply the required alignment. */ s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); - if (power_of_two > bfd_get_section_alignment (dynobj, s)) + if (power_of_two > bfd_get_section_alignment (htab->elf.dynobj, s)) { - if (! bfd_set_section_alignment (dynobj, s, power_of_two)) + if (! bfd_set_section_alignment (htab->elf.dynobj, s, power_of_two)) return FALSE; } @@ -2058,13 +2624,38 @@ ppc_elf_adjust_dynamic_symbol (info, h) return TRUE; } +/* This is the condition under which finish_dynamic_symbol will be + called from elflink.h. If elflink.h doesn't call our + finish_dynamic_symbol routine, we'll need to do something about + initializing any .plt and .got entries in relocate_section. */ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \ + ((DYN) \ + && ((SHARED) \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ + && ((H)->dynindx != -1 \ + || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) + +/* Of those relocs that might be copied as dynamic relocs, this macro + selects those that must be copied when linking a shared library, + even when the symbol is local. */ + +#define MUST_BE_DYN_RELOC(RTYPE) \ + ((RTYPE) != R_PPC_REL24 \ + && (RTYPE) != R_PPC_REL14 \ + && (RTYPE) != R_PPC_REL14_BRTAKEN \ + && (RTYPE) != R_PPC_REL14_BRNTAKEN \ + && (RTYPE) != R_PPC_REL32) + /* Allocate space in associated reloc sections for dynamic relocs. */ static bfd_boolean -allocate_dynrelocs (h, info) +allocate_dynrelocs (h, inf) struct elf_link_hash_entry *h; - PTR info ATTRIBUTE_UNUSED; + PTR inf; { + struct bfd_link_info *info = (struct bfd_link_info *) inf; + struct ppc_elf_link_hash_entry *eh; + struct ppc_elf_link_hash_table *htab; struct ppc_elf_dyn_relocs *p; if (h->root.type == bfd_link_hash_indirect) @@ -2076,7 +2667,178 @@ allocate_dynrelocs (h, info) symbol in a hash traversal. So look at it now. */ h = (struct elf_link_hash_entry *) h->root.u.i.link; - for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) + htab = ppc_elf_hash_table (info); + if (htab->elf.dynamic_sections_created + && h->plt.refcount > 0) + { + /* Make sure this symbol is output as a dynamic symbol. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf32_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + if (info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) + { + asection *s = htab->plt; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (s->_raw_size == 0) + s->_raw_size += PLT_INITIAL_ENTRY_SIZE; + + /* The PowerPC PLT is actually composed of two parts, the + first part is 2 words (for a load and a jump), and then + there is a remaining word available at the end. */ + h->plt.offset = (PLT_INITIAL_ENTRY_SIZE + + (PLT_SLOT_SIZE + * ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) + / PLT_ENTRY_SIZE))); + + /* If this symbol is not defined in a regular file, and we + are not generating a shared library, then set the symbol + to this location in the .plt. This is required to make + function pointers compare as equal between the normal + executable and the shared library. */ + if (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + { + h->root.u.def.section = s; + h->root.u.def.value = h->plt.offset; + } + + /* Make room for this entry. After the 8192nd entry, room + for two entries is allocated. */ + s->_raw_size += PLT_ENTRY_SIZE; + if ((s->_raw_size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE + >= PLT_NUM_SINGLE_ENTRIES) + s->_raw_size += PLT_ENTRY_SIZE; + + /* We also need to make an entry in the .rela.plt section. */ + htab->relplt->_raw_size += sizeof (Elf32_External_Rela); + } + else + { + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + } + } + else + { + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; + } + + eh = (struct ppc_elf_link_hash_entry *) h; + if (eh->elf.got.refcount > 0) + { + /* Make sure this symbol is output as a dynamic symbol. */ + if (eh->elf.dynindx == -1 + && (eh->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (!bfd_elf32_link_record_dynamic_symbol (info, &eh->elf)) + return FALSE; + } + + if (eh->tls_mask == (TLS_TLS | TLS_LD) + && !(eh->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) + /* If just an LD reloc, we'll just use htab->tlsld_got.offset. */ + eh->elf.got.offset = (bfd_vma) -1; + else + { + bfd_boolean dyn; + eh->elf.got.offset = htab->got->_raw_size; + if ((eh->tls_mask & TLS_TLS) != 0) + { + if ((eh->tls_mask & TLS_LD) != 0) + htab->got->_raw_size += 8; + if ((eh->tls_mask & TLS_GD) != 0) + htab->got->_raw_size += 8; + if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0) + htab->got->_raw_size += 4; + if ((eh->tls_mask & TLS_DTPREL) != 0) + htab->got->_raw_size += 4; + } + else + htab->got->_raw_size += 4; + dyn = htab->elf.dynamic_sections_created; + if (info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf)) + { + /* All the entries we allocated need relocs. */ + htab->relgot->_raw_size + += ((htab->got->_raw_size - eh->elf.got.offset) / 4 + * sizeof (Elf32_External_Rela)); + /* Except LD only needs one. */ + if ((eh->tls_mask & TLS_LD) != 0) + htab->relgot->_raw_size -= sizeof (Elf32_External_Rela); + } + } + } + else + eh->elf.got.offset = (bfd_vma) -1; + + if (eh->dyn_relocs == NULL) + return TRUE; + + /* In the shared -Bsymbolic case, discard space allocated for + dynamic pc-relative relocs against symbols which turn out to be + defined in regular objects. For the normal shared case, discard + space for relocs that have become local due to symbol visibility + changes. */ + if (info->shared) + { + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 + && ((h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 + || info->symbolic)) + { + struct ppc_elf_dyn_relocs **pp; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + p->count -= p->pc_count; + p->pc_count = 0; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + } + } + else if (ELIMINATE_COPY_RELOCS) + { + /* For the non-shared case, discard space for relocs against + symbols which turn out to need copy relocs or are not + dynamic. */ + + if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) + { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf64_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + /* If that succeeded, we know we'll be keeping all the + relocs. */ + if (h->dynindx != -1) + goto keep; + } + + eh->dyn_relocs = NULL; + + keep: ; + } + + /* Finally, allocate space. */ + for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela); @@ -2124,9 +2886,8 @@ ppc_elf_size_dynamic_sections (output_bfd, info) bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; { - bfd *dynobj; + struct ppc_elf_link_hash_table *htab; asection *s; - bfd_boolean plt; bfd_boolean relocs; bfd *ibfd; @@ -2134,43 +2895,42 @@ ppc_elf_size_dynamic_sections (output_bfd, info) fprintf (stderr, "ppc_elf_size_dynamic_sections called\n"); #endif - dynobj = elf_hash_table (info)->dynobj; - BFD_ASSERT (dynobj != NULL); + htab = ppc_elf_hash_table (info); + BFD_ASSERT (htab->elf.dynobj != NULL); if (elf_hash_table (info)->dynamic_sections_created) { /* Set the contents of the .interp section to the interpreter. */ if (! info->shared) { - s = bfd_get_section_by_name (dynobj, ".interp"); + s = bfd_get_section_by_name (htab->elf.dynobj, ".interp"); BFD_ASSERT (s != NULL); s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER; s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; } } - else + + if (htab->tlsld_got.refcount > 0) { - /* We may have created entries in the .rela.got, .rela.sdata, and - .rela.sdata2 sections. However, if we are not creating the - dynamic sections, we will not actually use these entries. Reset - the size of .rela.got, et al, which will cause it to get - stripped from the output file below. */ - static char *rela_sections[] = { ".rela.got", ".rela.sdata", - ".rela.sdata2", ".rela.sbss", - (char *) 0 }; - char **p; - - for (p = rela_sections; *p != (char *) 0; p++) - { - s = bfd_get_section_by_name (dynobj, *p); - if (s != NULL) - s->_raw_size = 0; - } + htab->tlsld_got.offset = htab->got->_raw_size; + htab->got->_raw_size += 8; + if (info->shared) + htab->relgot->_raw_size += sizeof (Elf32_External_Rela); } + else + htab->tlsld_got.offset = (bfd_vma) -1; - /* Allocate space for local sym dynamic relocs. */ + /* Set up .got offsets for local syms, and space for local dynamic + relocs. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { + bfd_signed_vma *local_got; + bfd_signed_vma *end_local_got; + char *lgot_masks; + bfd_size_type locsymcount; + Elf_Internal_Shdr *symtab_hdr; + asection *srel; + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) continue; @@ -2179,9 +2939,9 @@ ppc_elf_size_dynamic_sections (output_bfd, info) struct ppc_elf_dyn_relocs *p; for (p = ((struct ppc_elf_dyn_relocs *) - elf_section_data (s)->local_dynrel); - p != NULL; - p = p->next) + elf_section_data (s)->local_dynrel); + p != NULL; + p = p->next) { if (!bfd_is_abs_section (p->sec) && bfd_is_abs_section (p->sec->output_section)) @@ -2202,45 +2962,76 @@ ppc_elf_size_dynamic_sections (output_bfd, info) } } } + + local_got = elf_local_got_refcounts (ibfd); + if (!local_got) + continue; + + symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + locsymcount = symtab_hdr->sh_info; + end_local_got = local_got + locsymcount; + lgot_masks = (char *) end_local_got; + s = htab->got; + srel = htab->relgot; + for (; local_got < end_local_got; ++local_got, ++lgot_masks) + if (*local_got > 0) + { + if (*lgot_masks == (TLS_TLS | TLS_LD)) + { + /* If just an LD reloc, we'll just use + htab->tlsld_got.offset. */ + if (htab->tlsld_got.offset == (bfd_vma) -1) + { + htab->tlsld_got.offset = s->_raw_size; + s->_raw_size += 8; + if (info->shared) + srel->_raw_size += sizeof (Elf32_External_Rela); + } + *local_got = (bfd_vma) -1; + } + else + { + *local_got = s->_raw_size; + if ((*lgot_masks & TLS_TLS) != 0) + { + if ((*lgot_masks & TLS_GD) != 0) + s->_raw_size += 8; + if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0) + s->_raw_size += 4; + if ((*lgot_masks & TLS_DTPREL) != 0) + s->_raw_size += 4; + } + else + s->_raw_size += 4; + if (info->shared) + srel->_raw_size += ((s->_raw_size - *local_got) / 4 + * sizeof (Elf32_External_Rela)); + } + } + else + *local_got = (bfd_vma) -1; } /* Allocate space for global sym dynamic relocs. */ - elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, NULL); + elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info); - /* The check_relocs and adjust_dynamic_symbol entry points have - determined the sizes of the various dynamic sections. Allocate - memory for them. */ - plt = FALSE; + /* We've now determined the sizes of the various dynamic sections. + Allocate memory for them. */ relocs = FALSE; - for (s = dynobj->sections; s != NULL; s = s->next) + for (s = htab->elf.dynobj->sections; s != NULL; s = s->next) { - const char *name; - bfd_boolean strip; - if ((s->flags & SEC_LINKER_CREATED) == 0) continue; - /* It's OK to base decisions on the section name, because none - of the dynobj section names depend upon the input files. */ - name = bfd_get_section_name (dynobj, s); - - strip = FALSE; - - if (strcmp (name, ".plt") == 0) + if (s == htab->plt + || s == htab->got + || (htab->sdata != NULL && s == htab->sdata->section) + || (htab->sdata2 != NULL && s == htab->sdata2->section)) { - if (s->_raw_size == 0) - { - /* Strip this section if we don't need it; see the - comment below. */ - strip = TRUE; - } - else - { - /* Remember whether there is a PLT. */ - plt = TRUE; - } + /* Strip this section if we don't need it; see the + comment below. */ } - else if (strncmp (name, ".rela", 5) == 0) + else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) { if (s->_raw_size == 0) { @@ -2253,7 +3044,6 @@ ppc_elf_size_dynamic_sections (output_bfd, info) adjust_dynamic_symbol is called, and it is that function which decides whether anything needs to go into these sections. */ - strip = TRUE; } else { @@ -2265,27 +3055,25 @@ ppc_elf_size_dynamic_sections (output_bfd, info) s->reloc_count = 0; } } - else if (strcmp (name, ".got") != 0 - && strcmp (name, ".sdata") != 0 - && strcmp (name, ".sdata2") != 0) + else { /* It's not one of our sections, so don't allocate space. */ continue; } - if (strip) + if (s->_raw_size == 0) { _bfd_strip_section_from_output (info, s); continue; } /* Allocate memory for the section contents. */ - s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); - if (s->contents == NULL && s->_raw_size != 0) + s->contents = (bfd_byte *) bfd_zalloc (htab->elf.dynobj, s->_raw_size); + if (s->contents == NULL) return FALSE; } - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the values later, in ppc_elf_finish_dynamic_sections, but we @@ -2301,7 +3089,7 @@ ppc_elf_size_dynamic_sections (output_bfd, info) return FALSE; } - if (plt) + if (htab->plt != NULL && htab->plt->_raw_size != 0) { if (!add_dynamic_entry (DT_PLTGOT, 0) || !add_dynamic_entry (DT_PLTRELSZ, 0) @@ -2335,6 +3123,45 @@ ppc_elf_size_dynamic_sections (output_bfd, info) return TRUE; } +static bfd_boolean +update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type) + bfd *abfd; + Elf_Internal_Shdr *symtab_hdr; + unsigned long r_symndx; + int tls_type; +{ + bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd); + char *local_got_tls_masks; + + if (local_got_refcounts == NULL) + { + bfd_size_type size = symtab_hdr->sh_info; + + size *= sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks); + local_got_refcounts = (bfd_signed_vma *) bfd_zalloc (abfd, size); + if (local_got_refcounts == NULL) + return FALSE; + elf_local_got_refcounts (abfd) = local_got_refcounts; + } + + local_got_refcounts[r_symndx] += 1; + local_got_tls_masks = (char *) (local_got_refcounts + symtab_hdr->sh_info); + local_got_tls_masks[r_symndx] |= tls_type; + return TRUE; +} + +static void +bad_shared_reloc (abfd, r_type) + bfd *abfd; + enum elf_ppc_reloc_type r_type; +{ + (*_bfd_error_handler) + (_("%s: relocation %s cannot be used when making a shared object"), + bfd_archive_filename (abfd), + ppc_elf_howto_table[(int) r_type]->name); + bfd_set_error (bfd_error_bad_value); +} + /* Look through the relocs for a section during the first phase, and allocate space in the global offset table or procedure linkage table. */ @@ -2346,17 +3173,12 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) asection *sec; const Elf_Internal_Rela *relocs; { - bfd *dynobj; + struct ppc_elf_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; - struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; + struct elf_link_hash_entry **sym_hashes; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; - bfd_signed_vma *local_got_refcounts; - elf_linker_section_t *sdata; - elf_linker_section_t *sdata2; asection *sreloc; - asection *sgot = NULL; - asection *srelgot = NULL; if (info->relocateable) return TRUE; @@ -2370,36 +3192,38 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) /* Create the linker generated sections all the time so that the special symbols are created. */ - if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL) + htab = ppc_elf_hash_table (info); + if (htab->sdata == NULL) { - sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA); - if (!sdata) + htab->sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA); + if (htab->sdata == NULL) + htab->sdata = ppc_elf_create_linker_section (abfd, info, + LINKER_SECTION_SDATA); + if (htab->sdata == NULL) return FALSE; } - if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL) + if (htab->sdata2 == NULL) { - sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2); - if (!sdata2) + htab->sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2); + if (htab->sdata2 == NULL) + htab->sdata2 = ppc_elf_create_linker_section (abfd, info, + LINKER_SECTION_SDATA2); + if (htab->sdata2 == NULL) return FALSE; } - dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; - local_got_refcounts = elf_local_got_refcounts (abfd); - sym_hashes = elf_sym_hashes (abfd); - sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); - if (!elf_bad_symtab (abfd)) - sym_hashes_end -= symtab_hdr->sh_info; - sreloc = NULL; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { unsigned long r_symndx; + enum elf_ppc_reloc_type r_type; struct elf_link_hash_entry *h; + int tls_type = 0; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) @@ -2412,182 +3236,118 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) startup code. */ if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) { - if (sgot == NULL) + if (htab->got == NULL) { - if (dynobj == NULL) - elf_hash_table (info)->dynobj = dynobj = abfd; - sgot = ppc_elf_create_got (dynobj, info); - if (sgot == NULL) + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + if (!ppc_elf_create_got (htab->elf.dynobj, info)) return FALSE; } } - switch (ELF32_R_TYPE (rel->r_info)) + r_type = (enum elf_ppc_reloc_type) ELF32_R_TYPE (rel->r_info); + switch (r_type) { - /* GOT16 relocations */ + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + htab->tlsld_got.refcount += 1; + tls_type = TLS_TLS | TLS_LD; + goto dogottls; + + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + tls_type = TLS_TLS | TLS_GD; + goto dogottls; + + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + case R_PPC_GOT_TPREL16_HI: + case R_PPC_GOT_TPREL16_HA: + if (info->shared) + info->flags |= DF_STATIC_TLS; + tls_type = TLS_TLS | TLS_TPREL; + goto dogottls; + + case R_PPC_GOT_DTPREL16: + case R_PPC_GOT_DTPREL16_LO: + case R_PPC_GOT_DTPREL16_HI: + case R_PPC_GOT_DTPREL16_HA: + tls_type = TLS_TLS | TLS_DTPREL; + dogottls: + sec->has_tls_reloc = 1; + /* Fall thru */ + + /* GOT16 relocations */ case R_PPC_GOT16: case R_PPC_GOT16_LO: case R_PPC_GOT16_HI: case R_PPC_GOT16_HA: /* This symbol requires a global offset table entry. */ - - if (sgot == NULL) + if (htab->got == NULL) { - if (dynobj == NULL) - elf_hash_table (info)->dynobj = dynobj = abfd; - sgot = ppc_elf_create_got (dynobj, info); - if (sgot == NULL) + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + if (!ppc_elf_create_got (htab->elf.dynobj, info)) return FALSE; } - - if (srelgot == NULL - && (h != NULL || info->shared)) - { - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - if (srelgot == NULL) - { - srelgot = bfd_make_section (dynobj, ".rela.got"); - if (srelgot == NULL - || ! bfd_set_section_flags (dynobj, srelgot, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) - || ! bfd_set_section_alignment (dynobj, srelgot, 2)) - return FALSE; - } - } - if (h != NULL) { - if (h->got.refcount == 0) - { - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - if (!bfd_elf32_link_record_dynamic_symbol (info, h)) - return FALSE; - - /* Allocate space in the .got. */ - sgot->_raw_size += 4; - /* Allocate relocation space. */ - srelgot->_raw_size += sizeof (Elf32_External_Rela); - } - h->got.refcount++; + h->got.refcount += 1; + ppc_elf_hash_entry (h)->tls_mask |= tls_type; } else - { - /* This is a global offset table entry for a local symbol. */ - if (local_got_refcounts == NULL) - { - bfd_size_type size; - - size = symtab_hdr->sh_info; - size *= sizeof (bfd_signed_vma); - local_got_refcounts - = (bfd_signed_vma *) bfd_zalloc (abfd, size); - if (local_got_refcounts == NULL) - return FALSE; - elf_local_got_refcounts (abfd) = local_got_refcounts; - } - if (local_got_refcounts[r_symndx] == 0) - { - sgot->_raw_size += 4; - - /* If we are generating a shared object, we need to - output a R_PPC_RELATIVE reloc so that the - dynamic linker can adjust this GOT entry. */ - if (info->shared) - srelgot->_raw_size += sizeof (Elf32_External_Rela); - } - local_got_refcounts[r_symndx]++; - } + /* This is a global offset table entry for a local symbol. */ + if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type)) + return FALSE; break; - /* Indirect .sdata relocation */ + /* Indirect .sdata relocation. */ case R_PPC_EMB_SDAI16: if (info->shared) { - ((*_bfd_error_handler) - (_("%s: relocation %s cannot be used when making a shared object"), - bfd_archive_filename (abfd), "R_PPC_EMB_SDAI16")); + bad_shared_reloc (abfd, r_type); return FALSE; } - - if (srelgot == NULL && (h != NULL || info->shared)) - { - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - if (srelgot == NULL) - { - srelgot = bfd_make_section (dynobj, ".rela.got"); - if (srelgot == NULL - || ! bfd_set_section_flags (dynobj, srelgot, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) - || ! bfd_set_section_alignment (dynobj, srelgot, 2)) - return FALSE; - } - } - - if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel)) + if (!bfd_elf32_create_pointer_linker_section (abfd, info, + htab->sdata, h, rel)) return FALSE; - break; - /* Indirect .sdata2 relocation */ + /* Indirect .sdata2 relocation. */ case R_PPC_EMB_SDA2I16: if (info->shared) { - ((*_bfd_error_handler) - (_("%s: relocation %s cannot be used when making a shared object"), - bfd_archive_filename (abfd), "R_PPC_EMB_SDA2I16")); + bad_shared_reloc (abfd, r_type); return FALSE; } - - if (srelgot == NULL && (h != NULL || info->shared)) - { - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - if (srelgot == NULL) - { - srelgot = bfd_make_section (dynobj, ".rela.got"); - if (srelgot == NULL - || ! bfd_set_section_flags (dynobj, srelgot, - (SEC_ALLOC - | SEC_LOAD - | SEC_HAS_CONTENTS - | SEC_IN_MEMORY - | SEC_LINKER_CREATED - | SEC_READONLY)) - || ! bfd_set_section_alignment (dynobj, srelgot, 2)) - return FALSE; - } - } - - if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel)) + if (!bfd_elf32_create_pointer_linker_section (abfd, info, + htab->sdata2, h, rel)) return FALSE; - break; case R_PPC_SDAREL16: case R_PPC_EMB_SDA2REL: case R_PPC_EMB_SDA21: + case R_PPC_EMB_RELSDA: + case R_PPC_EMB_NADDR32: + case R_PPC_EMB_NADDR16: + case R_PPC_EMB_NADDR16_LO: + case R_PPC_EMB_NADDR16_HI: + case R_PPC_EMB_NADDR16_HA: if (info->shared) { - ((*_bfd_error_handler) - (_("%s: relocation %s cannot be used when making a shared object"), - bfd_archive_filename (abfd), - ppc_elf_howto_table[(int) ELF32_R_TYPE (rel->r_info)]->name)); + bad_shared_reloc (abfd, r_type); return FALSE; } break; case R_PPC_PLT32: case R_PPC_PLTREL24: + case R_PPC_PLTREL32: case R_PPC_PLT16_LO: case R_PPC_PLT16_HI: case R_PPC_PLT16_HA: @@ -2595,25 +3355,19 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) fprintf (stderr, "Reloc requires a PLT entry\n"); #endif /* This symbol requires a procedure linkage table entry. We - actually build the entry in adjust_dynamic_symbol, - because this might be a case of linking PIC code without - linking in any dynamic objects, in which case we don't - need to generate a procedure linkage table after all. */ + actually build the entry in finish_dynamic_symbol, + because this might be a case of linking PIC code without + linking in any dynamic objects, in which case we don't + need to generate a procedure linkage table after all. */ if (h == NULL) { /* It does not make sense to have a procedure linkage - table entry for a local symbol. */ + table entry for a local symbol. */ bfd_set_error (bfd_error_bad_value); return FALSE; } - /* Make sure this symbol is output as a dynamic symbol. */ - if (h->dynindx == -1) - { - if (! bfd_elf32_link_record_dynamic_symbol (info, h)) - return FALSE; - } h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; h->plt.refcount++; break; @@ -2625,9 +3379,37 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) case R_PPC_SECTOFF_LO: case R_PPC_SECTOFF_HI: case R_PPC_SECTOFF_HA: + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_DTPREL16_HA: + case R_PPC_TOC16: + break; + + /* This are just markers. */ + case R_PPC_TLS: + case R_PPC_EMB_MRKREF: + case R_PPC_NONE: + case R_PPC_max: break; - /* This refers only to functions defined in the shared library */ + /* These should only appear in dynamic objects. */ + case R_PPC_COPY: + case R_PPC_GLOB_DAT: + case R_PPC_JMP_SLOT: + case R_PPC_RELATIVE: + break; + + /* These aren't handled yet. We'll report an error later. */ + case R_PPC_ADDR30: + case R_PPC_EMB_RELSEC16: + case R_PPC_EMB_RELST_LO: + case R_PPC_EMB_RELST_HI: + case R_PPC_EMB_RELST_HA: + case R_PPC_EMB_BIT_FLD: + break; + + /* This refers only to functions defined in the shared library. */ case R_PPC_LOCAL24PC: break; @@ -2645,6 +3427,25 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) return FALSE; break; + /* We shouldn't really be seeing these. */ + case R_PPC_TPREL32: + if (info->shared) + info->flags |= DF_STATIC_TLS; + goto dodyn; + + /* Nor these. */ + case R_PPC_DTPMOD32: + case R_PPC_DTPREL32: + goto dodyn; + + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + if (info->shared) + info->flags |= DF_STATIC_TLS; + goto dodyn; + /* When creating a shared object, we must copy these relocs into the output file. We create a reloc section in dynobj and make room for the reloc. */ @@ -2659,15 +3460,71 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) break; /* fall through */ - default: - if (info->shared) + case R_PPC_ADDR32: + case R_PPC_ADDR24: + case R_PPC_ADDR16: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_UADDR32: + case R_PPC_UADDR16: + if (h != NULL && !info->shared) + { + /* We may need a plt entry if the symbol turns out to be + a function defined in a dynamic object. */ + h->plt.refcount++; + + /* We may need a copy reloc too. */ + h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF; + } + + dodyn: + /* If we are creating a shared library, and this is a reloc + against a global symbol, or a non PC relative reloc + against a local symbol, then we need to copy the reloc + into the shared library. However, if we are linking with + -Bsymbolic, we do not need to copy a reloc against a + global symbol which is defined in an object we are + including in the link (i.e., DEF_REGULAR is set). At + this point we have not seen all the input files, so it is + possible that DEF_REGULAR is not set now but will be set + later (it is never cleared). In case of a weak definition, + DEF_REGULAR may be cleared later by a strong definition in + a shared library. We account for that possibility below by + storing information in the dyn_relocs field of the hash + table entry. A similar situation occurs when creating + shared libraries and symbol visibility changes render the + symbol local. + + If on the other hand, we are creating an executable, we + may need to keep relocations for symbols satisfied by a + dynamic library if we manage to avoid copy relocs for the + symbol. */ + if ((info->shared + && (MUST_BE_DYN_RELOC (r_type) + || (h != NULL + && (! info->symbolic + || h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (ELIMINATE_COPY_RELOCS + && !info->shared + && (sec->flags & SEC_ALLOC) != 0 + && h != NULL + && (h->root.type == bfd_link_hash_defweak + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0))) { struct ppc_elf_dyn_relocs *p; struct ppc_elf_dyn_relocs **head; #ifdef DEBUG fprintf (stderr, "ppc_elf_check_relocs need to create relocation for %s\n", - (h && h->root.root.string) ? h->root.root.string : "<unknown>"); + (h && h->root.root.string + ? h->root.root.string : "<unknown>")); #endif if (sreloc == NULL) { @@ -2684,19 +3541,21 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) && strcmp (bfd_get_section_name (abfd, sec), name + 5) == 0); - sreloc = bfd_get_section_by_name (dynobj, name); + sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); if (sreloc == NULL) { flagword flags; - sreloc = bfd_make_section (dynobj, name); + sreloc = bfd_make_section (htab->elf.dynobj, name); flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED); if ((sec->flags & SEC_ALLOC) != 0) flags |= SEC_ALLOC | SEC_LOAD; if (sreloc == NULL - || ! bfd_set_section_flags (dynobj, sreloc, flags) - || ! bfd_set_section_alignment (dynobj, sreloc, 2)) + || ! bfd_set_section_flags (htab->elf.dynobj, + sreloc, flags) + || ! bfd_set_section_alignment (htab->elf.dynobj, + sreloc, 2)) return FALSE; } elf_section_data (sec)->sreloc = sreloc; @@ -2715,9 +3574,8 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) easily. Oh well. */ asection *s; - s = (bfd_section_from_r_symndx - (abfd, &ppc_elf_hash_table (info)->sym_sec, - sec, r_symndx)); + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, + sec, r_symndx); if (s == NULL) return FALSE; @@ -2729,16 +3587,19 @@ ppc_elf_check_relocs (abfd, info, sec, relocs) if (p == NULL || p->sec != sec) { p = ((struct ppc_elf_dyn_relocs *) - bfd_alloc (elf_hash_table (info)->dynobj, sizeof *p)); + bfd_alloc (htab->elf.dynobj, sizeof *p)); if (p == NULL) return FALSE; p->next = *head; *head = p; p->sec = sec; p->count = 0; + p->pc_count = 0; } - p->count++; + p->count += 1; + if (!MUST_BE_DYN_RELOC (r_type)) + p->pc_count += 1; } break; @@ -2788,85 +3649,348 @@ ppc_elf_gc_mark_hook (sec, info, rel, h, sym) return NULL; } -/* Update the got entry reference counts for the section being removed. */ +/* Update the got, plt and dynamic reloc reference counts for the + section being removed. */ static bfd_boolean ppc_elf_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd; - struct bfd_link_info *info ATTRIBUTE_UNUSED; + struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs; { + struct ppc_elf_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - struct elf_link_hash_entry *h; elf_section_data (sec)->local_dynrel = NULL; + htab = ppc_elf_hash_table (info); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); local_got_refcounts = elf_local_got_refcounts (abfd); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch (ELF32_R_TYPE (rel->r_info)) - { - case R_PPC_GOT16: - case R_PPC_GOT16_LO: - case R_PPC_GOT16_HI: - case R_PPC_GOT16_HA: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount--; - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; - } - break; - - case R_PPC_PLT32: - case R_PPC_PLTREL24: - case R_PPC_PLT16_LO: - case R_PPC_PLT16_HI: - case R_PPC_PLT16_HA: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount--; - } - /* Fall through */ + { + unsigned long r_symndx; + enum elf_ppc_reloc_type r_type; + struct elf_link_hash_entry *h = NULL; - default: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct ppc_elf_dyn_relocs **pp, *p; + struct ppc_elf_link_hash_entry *eh; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct ppc_elf_link_hash_entry *) h; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } + + r_type = (enum elf_ppc_reloc_type) ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + htab->tlsld_got.refcount -= 1; + /* Fall thru */ + + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + case R_PPC_GOT_TPREL16_HI: + case R_PPC_GOT_TPREL16_HA: + case R_PPC_GOT_DTPREL16: + case R_PPC_GOT_DTPREL16_LO: + case R_PPC_GOT_DTPREL16_HI: + case R_PPC_GOT_DTPREL16_HA: + case R_PPC_GOT16: + case R_PPC_GOT16_LO: + case R_PPC_GOT16_HI: + case R_PPC_GOT16_HA: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount--; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx]--; + } + break; + + case R_PPC_REL24: + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + case R_PPC_REL32: + if (h == NULL + || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 + || SYMBOL_REFERENCES_LOCAL (info, h)) + break; + /* Fall thru */ + + case R_PPC_ADDR32: + case R_PPC_ADDR24: + case R_PPC_ADDR16: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_UADDR32: + case R_PPC_UADDR16: + case R_PPC_PLT32: + case R_PPC_PLTREL24: + case R_PPC_PLT16_LO: + case R_PPC_PLT16_HI: + case R_PPC_PLT16_HA: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount--; + } + break; + + default: + break; + } + } + return TRUE; +} + +/* Set htab->tls_sec and htab->tls_get_addr. */ + +bfd_boolean +ppc_elf_tls_setup (obfd, info) + bfd *obfd; + struct bfd_link_info *info; +{ + asection *tls; + struct ppc_elf_link_hash_table *htab; + + htab = ppc_elf_hash_table (info); + htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr", + FALSE, FALSE, TRUE); + + for (tls = obfd->sections; tls != NULL; tls = tls->next) + if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) + == (SEC_THREAD_LOCAL | SEC_LOAD)) + break; + htab->tls_sec = tls; + + return tls != NULL; +} + +/* Run through all the TLS relocs looking for optimization + opportunities. */ + +bfd_boolean +ppc_elf_tls_optimize (obfd, info) + bfd *obfd ATTRIBUTE_UNUSED; + struct bfd_link_info *info; +{ + bfd *ibfd; + asection *sec; + struct ppc_elf_link_hash_table *htab; + + if (info->relocateable || info->shared) + return TRUE; + + htab = ppc_elf_hash_table (info); + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + Elf_Internal_Sym *locsyms = NULL; + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + + for (sec = ibfd->sections; sec != NULL; sec = sec->next) + if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) { - struct ppc_elf_dyn_relocs **pp, *p; + Elf_Internal_Rela *relstart, *rel, *relend; + int expecting_tls_get_addr; + + /* Read the relocations. */ + relstart = _bfd_elf32_link_read_relocs (ibfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory); + if (relstart == NULL) + return FALSE; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + expecting_tls_get_addr = 0; + relend = relstart + sec->reloc_count; + for (rel = relstart; rel < relend; rel++) + { + enum elf_ppc_reloc_type r_type; + unsigned long r_symndx; + struct elf_link_hash_entry *h = NULL; + char *tls_mask; + char tls_set, tls_clear; + bfd_boolean is_local; + + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_link_hash_entry **sym_hashes; - for (pp = &ppc_elf_hash_entry (h)->dyn_relocs; - (p = *pp) != NULL; - pp = &p->next) - if (p->sec == sec) - { - if (--p->count == 0) - *pp = p->next; - break; - } + sym_hashes = elf_sym_hashes (ibfd); + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + + is_local = FALSE; + if (h == NULL + || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) + is_local = TRUE; + + r_type = (enum elf_ppc_reloc_type) ELF32_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + /* These relocs should never be against a symbol + defined in a shared lib. Leave them alone if + that turns out to be the case. */ + expecting_tls_get_addr = 0; + htab->tlsld_got.refcount -= 1; + if (!is_local) + continue; + + /* LD -> LE */ + tls_set = 0; + tls_clear = TLS_LD; + expecting_tls_get_addr = 1; + break; + + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + if (is_local) + /* GD -> LE */ + tls_set = 0; + else + /* GD -> IE */ + tls_set = TLS_TLS | TLS_TPRELGD; + tls_clear = TLS_GD; + expecting_tls_get_addr = 1; + break; + + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + case R_PPC_GOT_TPREL16_HI: + case R_PPC_GOT_TPREL16_HA: + expecting_tls_get_addr = 0; + if (is_local) + { + /* IE -> LE */ + tls_set = 0; + tls_clear = TLS_TPREL; + break; + } + else + continue; + + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: + case R_PPC_REL24: + if (expecting_tls_get_addr + && h != NULL + && h == htab->tls_get_addr) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + expecting_tls_get_addr = 0; + continue; + + default: + expecting_tls_get_addr = 0; + continue; + } + + if (h != NULL) + { + if (tls_set == 0) + { + /* We managed to get rid of a got entry. */ + if (h->got.refcount > 0) + h->got.refcount -= 1; + } + tls_mask = &ppc_elf_hash_entry (h)->tls_mask; + } + else + { + Elf_Internal_Sym *sym; + bfd_signed_vma *lgot_refs; + char *lgot_masks; + + if (locsyms == NULL) + { + locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (locsyms == NULL) + locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, + 0, NULL, NULL, NULL); + if (locsyms == NULL) + { + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + return FALSE; + } + } + sym = locsyms + r_symndx; + lgot_refs = elf_local_got_refcounts (ibfd); + if (lgot_refs == NULL) + abort (); + if (tls_set == 0) + { + /* We managed to get rid of a got entry. */ + if (lgot_refs[r_symndx] > 0) + lgot_refs[r_symndx] -= 1; + } + lgot_masks = (char *) (lgot_refs + symtab_hdr->sh_info); + tls_mask = &lgot_masks[r_symndx]; + } + + *tls_mask |= tls_set; + *tls_mask &= ~tls_clear; + } + + if (elf_section_data (sec)->relocs != relstart) + free (relstart); } - break; - } + if (locsyms != NULL + && (symtab_hdr->contents != (unsigned char *) locsyms)) + { + if (!info->keep_memory) + free (locsyms); + else + symtab_hdr->contents = (unsigned char *) locsyms; + } + } return TRUE; } @@ -2898,9 +4022,9 @@ ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) bfd_size_type amt; /* We don't go through bfd_make_section, because we don't - want to attach this common section to DYNOBJ. The linker - will move the symbols to the appropriate output section - when it defines common symbols. */ + want to attach this common section to DYNOBJ. The linker + will move the symbols to the appropriate output section + when it defines common symbols. */ amt = sizeof (asection); sdata->bss_section = (asection *) bfd_zalloc (abfd, amt); if (sdata->bss_section == NULL) @@ -2939,20 +4063,18 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; { - bfd *dynobj; + struct ppc_elf_link_hash_table *htab; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s", h->root.root.string); #endif - dynobj = elf_hash_table (info)->dynobj; - BFD_ASSERT (dynobj != NULL); + htab = ppc_elf_hash_table (info); + BFD_ASSERT (htab->elf.dynobj != NULL); if (h->plt.offset != (bfd_vma) -1) { - asection *splt; - asection *srela; Elf_Internal_Rela rela; bfd_byte *loc; bfd_vma reloc_index; @@ -2962,20 +4084,17 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) #endif /* This symbol has an entry in the procedure linkage table. Set - it up. */ + it up. */ BFD_ASSERT (h->dynindx != -1); - - splt = bfd_get_section_by_name (dynobj, ".plt"); - srela = bfd_get_section_by_name (dynobj, ".rela.plt"); - BFD_ASSERT (splt != NULL && srela != NULL); + BFD_ASSERT (htab->plt != NULL && htab->relplt != NULL); /* We don't need to fill in the .plt. The ppc dynamic linker will fill it in. */ /* Fill in the entry in the .rela.plt section. */ - rela.r_offset = (splt->output_section->vma - + splt->output_offset + rela.r_offset = (htab->plt->output_section->vma + + htab->plt->output_offset + h->plt.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT); rela.r_addend = 0; @@ -2983,7 +4102,8 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) reloc_index = (h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_SLOT_SIZE; if (reloc_index > PLT_NUM_SINGLE_ENTRIES) reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2; - loc = srela->contents + reloc_index * sizeof (Elf32_External_Rela); + loc = (htab->relplt->contents + + reloc_index * sizeof (Elf32_External_Rela)); bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) @@ -3001,49 +4121,6 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) } } - if (h->got.offset != (bfd_vma) -1) - { - asection *sgot; - asection *srela; - Elf_Internal_Rela rela; - bfd_byte *loc; - - /* This symbol has an entry in the global offset table. Set it - up. */ - - sgot = bfd_get_section_by_name (dynobj, ".got"); - srela = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (sgot != NULL && srela != NULL); - - rela.r_offset = (sgot->output_section->vma - + sgot->output_offset - + (h->got.offset &~ (bfd_vma) 1)); - - /* If this is a -Bsymbolic link, and the symbol is defined - locally, we just want to emit a RELATIVE reloc. The entry in - the global offset table will already have been initialized in - the relocate_section function. */ - if (info->shared - && SYMBOL_REFERENCES_LOCAL (info, h)) - { - rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); - rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } - else - { - BFD_ASSERT ((h->got.offset & 1) == 0); - rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_GLOB_DAT); - rela.r_addend = 0; - } - - bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset); - loc = srela->contents; - loc += srela->reloc_count++ * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &rela, loc); - } - if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; @@ -3058,12 +4135,10 @@ ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym) BFD_ASSERT (h->dynindx != -1); - if (h->size <= elf_gp_size (dynobj)) - s = bfd_get_section_by_name (h->root.u.def.section->owner, - ".rela.sbss"); + if (h->size <= elf_gp_size (htab->elf.dynobj)) + s = htab->relsbss; else - s = bfd_get_section_by_name (h->root.u.def.section->owner, - ".rela.bss"); + s = htab->relbss; BFD_ASSERT (s != NULL); rela.r_offset = (h->root.u.def.value @@ -3096,80 +4171,69 @@ ppc_elf_finish_dynamic_sections (output_bfd, info) struct bfd_link_info *info; { asection *sdyn; - bfd *dynobj = elf_hash_table (info)->dynobj; - asection *sgot = bfd_get_section_by_name (dynobj, ".got"); + struct ppc_elf_link_hash_table *htab; #ifdef DEBUG fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n"); #endif - sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + htab = ppc_elf_hash_table (info); + sdyn = bfd_get_section_by_name (htab->elf.dynobj, ".dynamic"); - if (elf_hash_table (info)->dynamic_sections_created) + if (htab->elf.dynamic_sections_created) { - asection *splt; Elf32_External_Dyn *dyncon, *dynconend; - splt = bfd_get_section_by_name (dynobj, ".plt"); - BFD_ASSERT (splt != NULL && sdyn != NULL); + BFD_ASSERT (htab->plt != NULL && sdyn != NULL); dyncon = (Elf32_External_Dyn *) sdyn->contents; dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn dyn; - const char *name; - bfd_boolean size; + asection *s; - bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn); + bfd_elf32_swap_dyn_in (htab->elf.dynobj, dyncon, &dyn); switch (dyn.d_tag) { - case DT_PLTGOT: name = ".plt"; size = FALSE; break; - case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break; - case DT_JMPREL: name = ".rela.plt"; size = FALSE; break; - default: name = NULL; size = FALSE; break; - } + case DT_PLTGOT: + s = htab->plt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + break; - if (name != NULL) - { - asection *s; + case DT_PLTRELSZ: + dyn.d_un.d_val = htab->relplt->_raw_size; + break; - s = bfd_get_section_by_name (output_bfd, name); - if (s == NULL) - dyn.d_un.d_val = 0; - else - { - if (! size) - dyn.d_un.d_ptr = s->vma; - else - { - if (s->_cooked_size != 0) - dyn.d_un.d_val = s->_cooked_size; - else - dyn.d_un.d_val = s->_raw_size; - } - } - bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); + case DT_JMPREL: + s = htab->relplt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + break; + + default: + continue; } + + bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon); } } /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can easily find the address of the _GLOBAL_OFFSET_TABLE_. */ - if (sgot) + if (htab->got) { - unsigned char *contents = sgot->contents; + unsigned char *contents = htab->got->contents; bfd_put_32 (output_bfd, (bfd_vma) 0x4e800021 /* blrl */, contents); if (sdyn == NULL) - bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4); + bfd_put_32 (output_bfd, (bfd_vma) 0, contents + 4); else bfd_put_32 (output_bfd, sdyn->output_section->vma + sdyn->output_offset, - contents+4); + contents + 4); - elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4; + elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4; } return TRUE; @@ -3216,25 +4280,16 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, Elf_Internal_Sym *local_syms; asection **local_sections; { - Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); - bfd *dynobj = elf_hash_table (info)->dynobj; - elf_linker_section_t *sdata = NULL; - elf_linker_section_t *sdata2 = NULL; - Elf_Internal_Rela *rel = relocs; - Elf_Internal_Rela *relend = relocs + input_section->reloc_count; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + struct ppc_elf_link_hash_table *htab; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + Elf_Internal_Rela outrel; + bfd_byte *loc; asection *sreloc = NULL; - asection *splt; - asection *sgot; bfd_vma *local_got_offsets; bfd_boolean ret = TRUE; - long insn; - - if (dynobj) - { - sdata = elf_linker_section (dynobj, LINKER_SECTION_SDATA); - sdata2 = elf_linker_section (dynobj, LINKER_SECTION_SDATA2); - } #ifdef DEBUG fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n", @@ -3251,56 +4306,43 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Initialize howto table if needed. */ ppc_elf_howto_init (); + htab = ppc_elf_hash_table (info); local_got_offsets = elf_local_got_offsets (input_bfd); - - splt = sgot = NULL; - if (dynobj != NULL) - { - splt = bfd_get_section_by_name (dynobj, ".plt"); - sgot = bfd_get_section_by_name (dynobj, ".got"); - } - + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (input_bfd); + rel = relocs; + relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { - enum elf_ppc_reloc_type r_type = (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info); - bfd_vma offset = rel->r_offset; - bfd_vma addend = rel->r_addend; - bfd_reloc_status_type r = bfd_reloc_other; - Elf_Internal_Sym *sym = (Elf_Internal_Sym *) 0; - asection *sec = (asection *) 0; - struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) 0; - const char *sym_name = (const char *) 0; + enum elf_ppc_reloc_type r_type; + bfd_vma addend; + bfd_reloc_status_type r; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h; + const char *sym_name; reloc_howto_type *howto; unsigned long r_symndx; bfd_vma relocation; - int will_become_local; - - /* Unknown relocation handling */ - if ((unsigned) r_type >= (unsigned) R_PPC_max - || !ppc_elf_howto_table[(int) r_type]) - { - (*_bfd_error_handler) (_("%s: unknown relocation type %d"), - bfd_archive_filename (input_bfd), - (int) r_type); - - bfd_set_error (bfd_error_bad_value); - ret = FALSE; - continue; - } - - howto = ppc_elf_howto_table[(int) r_type]; + bfd_vma branch_bit, insn, from; + bfd_boolean unresolved_reloc; + bfd_boolean warned; + unsigned int tls_type, tls_mask, tls_gd; + + r_type = (enum elf_ppc_reloc_type)ELF32_R_TYPE (rel->r_info); + sym = (Elf_Internal_Sym *) 0; + sec = (asection *) 0; + h = (struct elf_link_hash_entry *) 0; + unresolved_reloc = FALSE; + warned = FALSE; r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; - sym_name = "<local symbol>"; + sym_name = bfd_elf_local_sym_name (input_bfd, sym); relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); - addend = rel->r_addend; - /* Relocs to local symbols are always resolved. */ - will_become_local = 1; } else { @@ -3310,127 +4352,551 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, h = (struct elf_link_hash_entry *) h->root.u.i.link; sym_name = h->root.root.string; - /* Can this relocation be resolved immediately? */ - will_become_local = SYMBOL_REFERENCES_LOCAL (info, h); - + relocation = 0; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; - if (((r_type == R_PPC_PLT32 - || r_type == R_PPC_PLTREL24) - && splt != NULL - && h->plt.offset != (bfd_vma) -1) - || (r_type == R_PPC_LOCAL24PC - && sec->output_section == NULL) - || ((r_type == R_PPC_GOT16 - || r_type == R_PPC_GOT16_LO - || r_type == R_PPC_GOT16_HI - || r_type == R_PPC_GOT16_HA) - && elf_hash_table (info)->dynamic_sections_created - && (! info->shared || ! will_become_local)) - || (info->shared - && ! will_become_local - && ((input_section->flags & SEC_ALLOC) != 0 - /* Testing SEC_DEBUGGING here may be wrong. - It's here to avoid a crash when - generating a shared library with DWARF - debugging information. */ - || ((input_section->flags & SEC_DEBUGGING) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) - && (r_type == R_PPC_ADDR32 - || r_type == R_PPC_ADDR24 - || r_type == R_PPC_ADDR16 - || r_type == R_PPC_ADDR16_LO - || r_type == R_PPC_ADDR16_HI - || r_type == R_PPC_ADDR16_HA - || r_type == R_PPC_ADDR14 - || r_type == R_PPC_ADDR14_BRTAKEN - || r_type == R_PPC_ADDR14_BRNTAKEN - || r_type == R_PPC_COPY - || r_type == R_PPC_GLOB_DAT - || r_type == R_PPC_JMP_SLOT - || r_type == R_PPC_UADDR32 - || r_type == R_PPC_UADDR16 - || r_type == R_PPC_SDAREL16 - || r_type == R_PPC_EMB_NADDR32 - || r_type == R_PPC_EMB_NADDR16 - || r_type == R_PPC_EMB_NADDR16_LO - || r_type == R_PPC_EMB_NADDR16_HI - || r_type == R_PPC_EMB_NADDR16_HA - || r_type == R_PPC_EMB_SDAI16 - || r_type == R_PPC_EMB_SDA2I16 - || r_type == R_PPC_EMB_SDA2REL - || r_type == R_PPC_EMB_SDA21 - || r_type == R_PPC_EMB_MRKREF - || r_type == R_PPC_EMB_BIT_FLD - || r_type == R_PPC_EMB_RELSDA - || ((r_type == R_PPC_REL24 - || r_type == R_PPC_REL32 - || r_type == R_PPC_REL14 - || r_type == R_PPC_REL14_BRTAKEN - || r_type == R_PPC_REL14_BRNTAKEN - || r_type == R_PPC_RELATIVE) - && strcmp (h->root.root.string, - "_GLOBAL_OFFSET_TABLE_") != 0)))) - { - /* In these cases, we don't need the relocation - value. We check specially because in some - obscure cases sec->output_section will be NULL. */ - relocation = 0; - } - else if (sec->output_section == NULL) - { - (*_bfd_error_handler) - (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), - bfd_archive_filename (input_bfd), h->root.root.string, - bfd_get_section_name (input_bfd, input_section)); - relocation = 0; - } + /* Set a flag that will be cleared later if we find a + relocation value for this symbol. output_section + is typically NULL for symbols satisfied by a shared + library. */ + if (sec->output_section == NULL) + unresolved_reloc = TRUE; else relocation = (h->root.u.def.value + sec->output_section->vma + sec->output_offset); } else if (h->root.type == bfd_link_hash_undefweak) - relocation = 0; + ; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) - relocation = 0; + ; else { - if (! (*info->callbacks->undefined_symbol) (info, - h->root.root.string, - input_bfd, - input_section, - rel->r_offset, - (!info->shared - || info->no_undefined - || ELF_ST_VISIBILITY (h->other)))) + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, input_bfd, input_section, + rel->r_offset, (!info->shared + || info->no_undefined + || ELF_ST_VISIBILITY (h->other))))) return FALSE; - relocation = 0; + warned = TRUE; + } + } + + /* TLS optimizations. Replace instruction sequences and relocs + based on information we collected in tls_optimize. We edit + RELOCS so that --emit-relocs will output something sensible + for the final instruction stream. */ + tls_mask = 0; + tls_gd = 0; + if (IS_PPC_TLS_RELOC (r_type)) + { + if (h != NULL) + tls_mask = ((struct ppc_elf_link_hash_entry *) h)->tls_mask; + else if (local_got_offsets != NULL) + { + char *lgot_masks; + lgot_masks = (char *) (local_got_offsets + symtab_hdr->sh_info); + tls_mask = lgot_masks[r_symndx]; } } - switch ((int) r_type) + /* Ensure reloc mapping code below stays sane. */ + if ((R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TLSGD16 & 3) + || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TLSGD16_LO & 3) + || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TLSGD16_HI & 3) + || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TLSGD16_HA & 3) + || (R_PPC_GOT_TLSLD16 & 3) != (R_PPC_GOT_TPREL16 & 3) + || (R_PPC_GOT_TLSLD16_LO & 3) != (R_PPC_GOT_TPREL16_LO & 3) + || (R_PPC_GOT_TLSLD16_HI & 3) != (R_PPC_GOT_TPREL16_HI & 3) + || (R_PPC_GOT_TLSLD16_HA & 3) != (R_PPC_GOT_TPREL16_HA & 3)) + abort (); + switch (r_type) { default: - (*_bfd_error_handler) (_("%s: unknown relocation type %d for symbol %s"), - bfd_archive_filename (input_bfd), - (int) r_type, sym_name); + break; + + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + if (tls_mask != 0 + && (tls_mask & TLS_TPREL) == 0) + { + bfd_vma insn; + insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2); + insn &= 31 << 21; + insn |= 0x3c020000; /* addis 0,2,0 */ + bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2); + r_type = R_PPC_TPREL16_HA; + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + } + break; + + case R_PPC_TLS: + if (tls_mask != 0 + && (tls_mask & TLS_TPREL) == 0) + { + bfd_vma insn, rtra; + insn = bfd_get_32 (output_bfd, contents + rel->r_offset); + if ((insn & ((31 << 26) | (31 << 11))) + == ((31 << 26) | (2 << 11))) + rtra = insn & ((1 << 26) - (1 << 16)); + else if ((insn & ((31 << 26) | (31 << 16))) + == ((31 << 26) | (2 << 16))) + rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); + else + abort (); + if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) + /* add -> addi. */ + insn = 14 << 26; + else if ((insn & (31 << 1)) == 23 << 1 + && ((insn & (31 << 6)) < 14 << 6 + || ((insn & (31 << 6)) >= 16 << 6 + && (insn & (31 << 6)) < 24 << 6))) + /* load and store indexed -> dform. */ + insn = (32 | ((insn >> 6) & 31)) << 26; + else if ((insn & (31 << 1)) == 21 << 1 + && (insn & (0x1a << 6)) == 0) + /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ + insn = (((58 | ((insn >> 6) & 4)) << 26) + | ((insn >> 6) & 1)); + else if ((insn & (31 << 1)) == 21 << 1 + && (insn & ((1 << 11) - (1 << 1))) == 341 << 1) + /* lwax -> lwa. */ + insn = (58 << 26) | 2; + else + abort (); + insn |= rtra; + bfd_put_32 (output_bfd, insn, contents + rel->r_offset); + r_type = R_PPC_TPREL16_LO; + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + /* Was PPC_TLS which sits on insn boundary, now + PPC_TPREL16_LO which is at insn+2. */ + rel->r_offset += 2; + } + break; + + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + tls_gd = TLS_TPRELGD; + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + goto tls_gdld_hi; + break; + + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + tls_gdld_hi: + if ((tls_mask & tls_gd) != 0) + r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) + + R_PPC_GOT_TPREL16); + else + { + bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); + rel->r_offset -= 2; + r_type = R_PPC_NONE; + } + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + } + break; + + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + tls_gd = TLS_TPRELGD; + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + goto tls_get_addr_check; + break; + + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + tls_get_addr_check: + if (rel + 1 < relend) + { + enum elf_ppc_reloc_type r_type2; + unsigned long r_symndx2; + struct elf_link_hash_entry *h2; + bfd_vma insn1, insn2, insn3; + bfd_vma offset; + + /* The next instruction should be a call to + __tls_get_addr. Peek at the reloc to be sure. */ + r_type2 + = (enum elf_ppc_reloc_type) ELF32_R_TYPE (rel[1].r_info); + r_symndx2 = ELF32_R_SYM (rel[1].r_info); + if (r_symndx2 < symtab_hdr->sh_info + || (r_type2 != R_PPC_REL14 + && r_type2 != R_PPC_REL14_BRTAKEN + && r_type2 != R_PPC_REL14_BRNTAKEN + && r_type2 != R_PPC_REL24 + && r_type2 != R_PPC_PLTREL24)) + break; + + h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; + while (h2->root.type == bfd_link_hash_indirect + || h2->root.type == bfd_link_hash_warning) + h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; + if (h2 == NULL || h2 != htab->tls_get_addr) + break; + + /* OK, it checks out. Replace the call. */ + offset = rel[1].r_offset; + insn1 = bfd_get_32 (output_bfd, + contents + rel->r_offset - 2); + insn3 = bfd_get_32 (output_bfd, + contents + offset + 4); + if ((tls_mask & tls_gd) != 0) + { + /* IE */ + insn1 &= (1 << 26) - 1; + insn1 |= 32 << 26; /* lwz */ + insn2 = 0x7c631214; /* add 3,3,2 */ + rel[1].r_info = ELF32_R_INFO (r_symndx2, R_PPC_NONE); + r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3) + + R_PPC_GOT_TPREL16); + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + } + else + { + /* LE */ + insn1 = 0x3c620000; /* addis 3,2,0 */ + insn2 = 0x38630000; /* addi 3,3,0 */ + if (tls_gd == 0) + { + /* Was an LD reloc. */ + r_symndx = 0; + rel->r_addend = htab->tls_sec->vma + DTP_OFFSET; + rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET; + } + r_type = R_PPC_TPREL16_HA; + rel->r_info = ELF32_R_INFO (r_symndx, r_type); + rel[1].r_info = ELF32_R_INFO (r_symndx, + R_PPC_TPREL16_LO); + rel[1].r_offset += 2; + } + if (insn3 == NOP + || insn3 == CROR_151515 || insn3 == CROR_313131) + { + insn3 = insn2; + insn2 = NOP; + rel[1].r_offset += 4; + } + bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2); + bfd_put_32 (output_bfd, insn2, contents + offset); + bfd_put_32 (output_bfd, insn3, contents + offset + 4); + if (tls_gd == 0) + { + /* We changed the symbol on an LD reloc. Start over + in order to get h, sym, sec etc. right. */ + rel--; + continue; + } + } + } + break; + } + + /* Handle other relocations that tweak non-addend part of insn. */ + branch_bit = 0; + switch (r_type) + { + default: + break; + + /* Branch taken prediction relocations. */ + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_REL14_BRTAKEN: + branch_bit = BRANCH_PREDICT_BIT; + /* Fall thru */ + + /* Branch not taken predicition relocations. */ + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_REL14_BRNTAKEN: + insn = bfd_get_32 (output_bfd, contents + rel->r_offset); + insn &= ~BRANCH_PREDICT_BIT; + insn |= branch_bit; + + from = (rel->r_offset + + input_section->output_offset + + input_section->output_section->vma); + + /* Invert 'y' bit if not the default. */ + if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) + insn ^= BRANCH_PREDICT_BIT; + + bfd_put_32 (output_bfd, insn, contents + rel->r_offset); + break; + } + + addend = rel->r_addend; + tls_type = 0; + howto = NULL; + if ((unsigned) r_type < (unsigned) R_PPC_max) + howto = ppc_elf_howto_table[(int) r_type]; + switch (r_type) + { + default: + (*_bfd_error_handler) + (_("%s: unknown relocation type %d for symbol %s"), + bfd_archive_filename (input_bfd), (int) r_type, sym_name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; - case (int) R_PPC_NONE: + case R_PPC_NONE: + case R_PPC_TLS: + case R_PPC_EMB_MRKREF: + case R_PPC_GNU_VTINHERIT: + case R_PPC_GNU_VTENTRY: continue; + /* GOT16 relocations. Like an ADDR16 using the symbol's + address in the GOT as relocation value instead of the + symbol's value itself. Also, create a GOT entry for the + symbol and put the symbol value there. */ + case R_PPC_GOT_TLSGD16: + case R_PPC_GOT_TLSGD16_LO: + case R_PPC_GOT_TLSGD16_HI: + case R_PPC_GOT_TLSGD16_HA: + tls_type = TLS_TLS | TLS_GD; + goto dogot; + + case R_PPC_GOT_TLSLD16: + case R_PPC_GOT_TLSLD16_LO: + case R_PPC_GOT_TLSLD16_HI: + case R_PPC_GOT_TLSLD16_HA: + tls_type = TLS_TLS | TLS_LD; + goto dogot; + + case R_PPC_GOT_TPREL16: + case R_PPC_GOT_TPREL16_LO: + case R_PPC_GOT_TPREL16_HI: + case R_PPC_GOT_TPREL16_HA: + tls_type = TLS_TLS | TLS_TPREL; + goto dogot; + + case R_PPC_GOT_DTPREL16: + case R_PPC_GOT_DTPREL16_LO: + case R_PPC_GOT_DTPREL16_HI: + case R_PPC_GOT_DTPREL16_HA: + tls_type = TLS_TLS | TLS_DTPREL; + goto dogot; + + case R_PPC_GOT16: + case R_PPC_GOT16_LO: + case R_PPC_GOT16_HI: + case R_PPC_GOT16_HA: + dogot: + { + /* Relocation is to the entry for this symbol in the global + offset table. */ + bfd_vma off; + bfd_vma *offp; + unsigned long indx; + + if (htab->got == NULL) + abort (); + + indx = 0; + if (tls_type == (TLS_TLS | TLS_LD) + && (h == NULL + || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))) + offp = &htab->tlsld_got.offset; + else if (h != NULL) + { + bfd_boolean dyn; + dyn = htab->elf.dynamic_sections_created; + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) + || (info->shared + && SYMBOL_REFERENCES_LOCAL (info, h))) + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. */ + ; + else + { + indx = h->dynindx; + unresolved_reloc = FALSE; + } + offp = &h->got.offset; + } + else + { + if (local_got_offsets == NULL) + abort (); + offp = &local_got_offsets[r_symndx]; + } + + /* The offset must always be a multiple of 4. We use the + least significant bit to record whether we have already + processed this entry. */ + off = *offp; + if ((off & 1) != 0) + off &= ~1; + else + { + unsigned int tls_m = (tls_mask + & (TLS_LD | TLS_GD | TLS_DTPREL + | TLS_TPREL | TLS_TPRELGD)); + + if (offp == &htab->tlsld_got.offset) + tls_m = TLS_LD; + else if (h == NULL + || !(h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_DYNAMIC)) + tls_m &= ~TLS_LD; + + /* We might have multiple got entries for this sym. + Initialize them all. */ + do + { + int tls_ty = 0; + + if ((tls_m & TLS_LD) != 0) + { + tls_ty = TLS_TLS | TLS_LD; + tls_m &= ~TLS_LD; + } + else if ((tls_m & TLS_GD) != 0) + { + tls_ty = TLS_TLS | TLS_GD; + tls_m &= ~TLS_GD; + } + else if ((tls_m & TLS_DTPREL) != 0) + { + tls_ty = TLS_TLS | TLS_DTPREL; + tls_m &= ~TLS_DTPREL; + } + else if ((tls_m & (TLS_TPREL | TLS_TPRELGD)) != 0) + { + tls_ty = TLS_TLS | TLS_TPREL; + tls_m = 0; + } + + /* Generate relocs for the dynamic linker. */ + if (info->shared || indx != 0) + { + outrel.r_offset = (htab->got->output_section->vma + + htab->got->output_offset + + off); + if (tls_ty & (TLS_LD | TLS_GD)) + { + outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32); + outrel.r_addend = 0; + if (tls_ty == (TLS_TLS | TLS_GD)) + { + loc = htab->relgot->contents; + loc += (htab->relgot->reloc_count++ + * sizeof (Elf32_External_Rela)); + bfd_elf32_swap_reloca_out (output_bfd, + &outrel, loc); + outrel.r_info + = ELF32_R_INFO (indx, R_PPC_DTPREL32); + outrel.r_offset += 4; + } + } + else if (tls_ty == (TLS_TLS | TLS_DTPREL)) + outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32); + else if (tls_ty == (TLS_TLS | TLS_TPREL)) + outrel.r_info = ELF32_R_INFO (indx, R_PPC_TPREL32); + else if (indx == 0) + outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE); + else + outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT); + outrel.r_addend = 0; + if (indx == 0) + outrel.r_addend += relocation; + loc = htab->relgot->contents; + loc += (htab->relgot->reloc_count++ + * sizeof (Elf32_External_Rela)); + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } + + /* Init the .got section contents if we're not + emitting a reloc. */ + else + { + bfd_vma value = relocation; + + if ((tls_ty & (TLS_GD | TLS_TPREL | TLS_DTPREL + | TLS_TPRELGD)) != 0) + { + value -= htab->tls_sec->vma + DTP_OFFSET; + if ((tls_ty & TLS_TPREL) != 0) + value += DTP_OFFSET - TP_OFFSET; + } + + if (tls_ty == (TLS_TLS | TLS_GD)) + { + bfd_put_32 (output_bfd, value, + htab->got->contents + off + 4); + value = 1; + } + else if (tls_ty == (TLS_TLS | TLS_LD)) + value = 1; + bfd_put_32 (output_bfd, value, + htab->got->contents + off); + } + + off += 4; + if (tls_ty & (TLS_LD | TLS_GD)) + off += 4; + } + while (tls_m != 0); + + off = *offp; + *offp = off | 1; + } + + if (off >= (bfd_vma) -2) + abort (); + + if ((tls_type & TLS_TLS) != 0) + { + if (tls_type != (TLS_TLS | TLS_LD)) + { + if ((tls_mask & TLS_LD) != 0 + && !(h == NULL + || !(h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_DYNAMIC))) + off += 8; + if (tls_type != (TLS_TLS | TLS_GD)) + { + if ((tls_mask & TLS_GD) != 0) + off += 8; + if (tls_type != (TLS_TLS | TLS_DTPREL)) + { + if ((tls_mask & TLS_DTPREL) != 0) + off += 4; + } + } + } + } + + relocation = htab->got->output_offset + off - 4; + + /* Addends on got relocations don't make much sense. + x+off@got is actually x@got+off, and since the got is + generated by a hash table traversal, the value in the + got at entry m+n bears little relation to the entry m. */ + if (addend != 0) + (*_bfd_error_handler) + (_("%s(%s+0x%lx): non-zero addend on got reloc against `%s'"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, + sym_name); + } + break; + /* Relocations that need no special processing. */ - case (int) R_PPC_LOCAL24PC: + case R_PPC_LOCAL24PC: /* It makes no sense to point a local relocation at a symbol not in this object. */ if (h != NULL @@ -3449,45 +4915,95 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, } break; - /* Relocations that may need to be propagated if this is a shared - object. */ - case (int) R_PPC_REL24: - case (int) R_PPC_REL32: - case (int) R_PPC_REL14: + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_DTPREL16_HA: + addend -= htab->tls_sec->vma + DTP_OFFSET; + break; + + /* Relocations that may need to be propagated if this is a shared + object. */ + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + addend -= htab->tls_sec->vma + TP_OFFSET; + /* The TPREL16 relocs shouldn't really be used in shared + libs as they will result in DT_TEXTREL being set, but + support them anyway. */ + goto dodyn; + + case R_PPC_TPREL32: + addend -= htab->tls_sec->vma + TP_OFFSET; + goto dodyn; + + case R_PPC_DTPREL32: + addend -= htab->tls_sec->vma + DTP_OFFSET; + goto dodyn; + + case R_PPC_REL24: + case R_PPC_REL32: + case R_PPC_REL14: + case R_PPC_REL14_BRTAKEN: + case R_PPC_REL14_BRNTAKEN: /* If these relocations are not to a named symbol, they can be handled right here, no need to bother the dynamic linker. */ if (h == NULL || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0 || SYMBOL_REFERENCES_LOCAL (info, h)) break; - /* fall through */ - - /* Relocations that always need to be propagated if this is a shared - object. */ - case (int) R_PPC_ADDR32: - case (int) R_PPC_ADDR24: - case (int) R_PPC_ADDR16: - case (int) R_PPC_ADDR16_LO: - case (int) R_PPC_ADDR16_HI: - case (int) R_PPC_ADDR16_HA: - case (int) R_PPC_ADDR14: - case (int) R_PPC_UADDR32: - case (int) R_PPC_UADDR16: - if (info->shared && r_symndx != 0) + /* fall through */ + + /* Relocations that always need to be propagated if this is a shared + object. */ + case R_PPC_ADDR32: + case R_PPC_ADDR24: + case R_PPC_ADDR16: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_ADDR14: + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + case R_PPC_UADDR32: + case R_PPC_UADDR16: + case R_PPC_DTPMOD32: + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + dodyn: + if (r_symndx == 0) + break; + /* Fall thru. */ + + if ((info->shared + && (MUST_BE_DYN_RELOC (r_type) + || (h != NULL + && h->dynindx != -1 + && (!info->symbolic + || (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR) == 0)))) + || (ELIMINATE_COPY_RELOCS + && !info->shared + && (input_section->flags & SEC_ALLOC) != 0 + && h != NULL + && h->dynindx != -1 + && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) { - Elf_Internal_Rela outrel; - bfd_byte *loc; int skip; #ifdef DEBUG fprintf (stderr, "ppc_elf_relocate_section need to create relocation for %s\n", - (h && h->root.root.string) ? h->root.root.string : "<unknown>"); + (h && h->root.root.string + ? h->root.root.string : "<unknown>")); #endif /* When generating a shared object, these relocations - are copied into the output file to be resolved at run - time. */ - + are copied into the output file to be resolved at run + time. */ if (sreloc == NULL) { const char *name; @@ -3504,7 +5020,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, input_section), name + 5) == 0); - sreloc = bfd_get_section_by_name (dynobj, name); + sreloc = bfd_get_section_by_name (htab->elf.dynobj, name); BFD_ASSERT (sreloc != NULL); } @@ -3522,9 +5038,11 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (skip) memset (&outrel, 0, sizeof outrel); /* h->dynindx may be -1 if this symbol was marked to - become local. */ - else if (! will_become_local) + become local. */ + else if (h != NULL + && !SYMBOL_REFERENCES_LOCAL (info, h)) { + unresolved_reloc = FALSE; outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; } @@ -3538,16 +5056,6 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, { long indx; - if (h == NULL) - sec = local_sections[r_symndx]; - else - { - BFD_ASSERT (h->root.type == bfd_link_hash_defined - || (h->root.type - == bfd_link_hash_defweak)); - sec = h->root.u.def.section; - } - if (bfd_is_abs_section (sec)) indx = 0; else if (sec == NULL || sec->owner == NULL) @@ -3571,8 +5079,8 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (indx <= 0) { printf ("indx=%d section=%s flags=%08x name=%s\n", - indx, osec->name, osec->flags, - h->root.root.string); + indx, osec->name, osec->flags, + h->root.root.string); } #endif } @@ -3599,186 +5107,66 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, break; } } - - /* Arithmetic adjust relocations that aren't going into a - shared object. */ - if (r_type == R_PPC_ADDR16_HA - /* It's just possible that this symbol is a weak symbol - that's not actually defined anywhere. In that case, - 'sec' would be NULL, and we should leave the symbol - alone (it will be set to zero elsewhere in the link). */ - && sec != NULL) - { - addend += ((relocation + addend) & 0x8000) << 1; - } - break; - - /* branch taken prediction relocations */ - case (int) R_PPC_ADDR14_BRTAKEN: - case (int) R_PPC_REL14_BRTAKEN: - insn = bfd_get_32 (output_bfd, contents + offset); - if ((relocation - offset) & 0x8000) - insn &= ~BRANCH_PREDICT_BIT; - else - insn |= BRANCH_PREDICT_BIT; - bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); - break; - - /* branch not taken predicition relocations */ - case (int) R_PPC_ADDR14_BRNTAKEN: - case (int) R_PPC_REL14_BRNTAKEN: - insn = bfd_get_32 (output_bfd, contents + offset); - if ((relocation - offset) & 0x8000) - insn |= BRANCH_PREDICT_BIT; - else - insn &= ~BRANCH_PREDICT_BIT; - bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); - break; - - /* GOT16 relocations */ - case (int) R_PPC_GOT16: - case (int) R_PPC_GOT16_LO: - case (int) R_PPC_GOT16_HI: - case (int) R_PPC_GOT16_HA: - /* Relocation is to the entry for this symbol in the global - offset table. */ - BFD_ASSERT (sgot != NULL); - - if (h != NULL) - { - bfd_vma off; - - off = h->got.offset; - BFD_ASSERT (off != (bfd_vma) -1); - - if (! elf_hash_table (info)->dynamic_sections_created - || (info->shared - && SYMBOL_REFERENCES_LOCAL (info, h))) - { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally. We must initialize this entry in the - global offset table. Since the offset must - always be a multiple of 4, we use the least - significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rela.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; - else - { - bfd_put_32 (output_bfd, relocation, - sgot->contents + off); - h->got.offset |= 1; - } - } - - relocation = sgot->output_offset + off - 4; - } - else - { - bfd_vma off; - - BFD_ASSERT (local_got_offsets != NULL - && local_got_offsets[r_symndx] != (bfd_vma) -1); - - off = local_got_offsets[r_symndx]; - - /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already processed this entry. */ - if ((off & 1) != 0) - off &= ~1; - else - { - - if (info->shared) - { - asection *srelgot; - Elf_Internal_Rela outrel; - bfd_byte *loc; - - /* We need to generate a R_PPC_RELATIVE reloc - for the dynamic linker. */ - srelgot = bfd_get_section_by_name (dynobj, ".rela.got"); - BFD_ASSERT (srelgot != NULL); - - outrel.r_offset = (sgot->output_section->vma - + sgot->output_offset - + off); - outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE); - outrel.r_addend = relocation; - loc = srelgot->contents; - loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - relocation = 0; - } - - bfd_put_32 (output_bfd, relocation, sgot->contents + off); - local_got_offsets[r_symndx] |= 1; - } - - relocation = sgot->output_offset + off - 4; - } - if (r_type == R_PPC_GOT16_HA) - addend += ((relocation + addend) & 0x8000) << 1; break; - /* Indirect .sdata relocation */ - case (int) R_PPC_EMB_SDAI16: - BFD_ASSERT (sdata != NULL); - relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, - sdata, h, relocation, rel, - R_PPC_RELATIVE); + /* Indirect .sdata relocation. */ + case R_PPC_EMB_SDAI16: + BFD_ASSERT (htab->sdata != NULL); + relocation + = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, + info, htab->sdata, h, + relocation, rel, + R_PPC_RELATIVE); break; - /* Indirect .sdata2 relocation */ - case (int) R_PPC_EMB_SDA2I16: - BFD_ASSERT (sdata2 != NULL); - relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info, - sdata2, h, relocation, rel, - R_PPC_RELATIVE); + /* Indirect .sdata2 relocation. */ + case R_PPC_EMB_SDA2I16: + BFD_ASSERT (htab->sdata2 != NULL); + relocation + = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, + info, htab->sdata2, h, + relocation, rel, + R_PPC_RELATIVE); break; - /* Handle the TOC16 reloc. We want to use the offset within the .got - section, not the actual VMA. This is appropriate when generating - an embedded ELF object, for which the .got section acts like the - AIX .toc section. */ - case (int) R_PPC_TOC16: /* phony GOT16 relocations */ + /* Handle the TOC16 reloc. We want to use the offset within the .got + section, not the actual VMA. This is appropriate when generating + an embedded ELF object, for which the .got section acts like the + AIX .toc section. */ + case R_PPC_TOC16: /* phony GOT16 relocations */ BFD_ASSERT (sec != (asection *) 0); BFD_ASSERT (bfd_is_und_section (sec) || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0 || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0) - addend -= sec->output_section->vma + sec->output_offset + 0x8000; + addend -= sec->output_section->vma + sec->output_offset + 0x8000; break; - case (int) R_PPC_PLTREL24: + case R_PPC_PLTREL24: /* Relocation is to the entry for this symbol in the - procedure linkage table. */ + procedure linkage table. */ BFD_ASSERT (h != NULL); if (h->plt.offset == (bfd_vma) -1 - || splt == NULL) + || htab->plt == NULL) { /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ + happens when statically linking PIC code, or when + using -Bsymbolic. */ break; } - relocation = (splt->output_section->vma - + splt->output_offset + unresolved_reloc = FALSE; + relocation = (htab->plt->output_section->vma + + htab->plt->output_offset + h->plt.offset); break; - /* relocate against _SDA_BASE_ */ - case (int) R_PPC_SDAREL16: + /* Relocate against _SDA_BASE_. */ + case R_PPC_SDAREL16: { const char *name; + const struct elf_link_hash_entry *sh; BFD_ASSERT (sec != (asection *) 0); name = bfd_get_section_name (abfd, sec->output_section); @@ -3790,19 +5178,21 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), bfd_archive_filename (input_bfd), sym_name, - ppc_elf_howto_table[(int) r_type]->name, + howto->name, name); } - addend -= (sdata->sym_hash->root.u.def.value - + sdata->sym_hash->root.u.def.section->output_section->vma - + sdata->sym_hash->root.u.def.section->output_offset); + sh = htab->sdata->sym_hash; + addend -= (sh->root.u.def.value + + sh->root.u.def.section->output_section->vma + + sh->root.u.def.section->output_offset); } break; - /* relocate against _SDA2_BASE_ */ - case (int) R_PPC_EMB_SDA2REL: + /* Relocate against _SDA2_BASE_. */ + case R_PPC_EMB_SDA2REL: { const char *name; + const struct elf_link_hash_entry *sh; BFD_ASSERT (sec != (asection *) 0); name = bfd_get_section_name (abfd, sec->output_section); @@ -3812,24 +5202,26 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), bfd_archive_filename (input_bfd), sym_name, - ppc_elf_howto_table[(int) r_type]->name, + howto->name, name); bfd_set_error (bfd_error_bad_value); ret = FALSE; continue; } - addend -= (sdata2->sym_hash->root.u.def.value - + sdata2->sym_hash->root.u.def.section->output_section->vma - + sdata2->sym_hash->root.u.def.section->output_offset); + sh = htab->sdata2->sym_hash; + addend -= (sh->root.u.def.value + + sh->root.u.def.section->output_section->vma + + sh->root.u.def.section->output_offset); } break; - /* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */ - case (int) R_PPC_EMB_SDA21: - case (int) R_PPC_EMB_RELSDA: + /* Relocate against either _SDA_BASE_, _SDA2_BASE_, or 0. */ + case R_PPC_EMB_SDA21: + case R_PPC_EMB_RELSDA: { const char *name; + const struct elf_link_hash_entry *sh; int reg; BFD_ASSERT (sec != (asection *) 0); @@ -3840,18 +5232,20 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, && (name[5] == 0 || name[5] == '.')))) { reg = 13; - addend -= (sdata->sym_hash->root.u.def.value - + sdata->sym_hash->root.u.def.section->output_section->vma - + sdata->sym_hash->root.u.def.section->output_offset); + sh = htab->sdata->sym_hash; + addend -= (sh->root.u.def.value + + sh->root.u.def.section->output_section->vma + + sh->root.u.def.section->output_offset); } else if (strncmp (name, ".sdata2", 7) == 0 || strncmp (name, ".sbss2", 6) == 0) { reg = 2; - addend -= (sdata2->sym_hash->root.u.def.value - + sdata2->sym_hash->root.u.def.section->output_section->vma - + sdata2->sym_hash->root.u.def.section->output_offset); + sh = htab->sdata2->sym_hash; + addend -= (sh->root.u.def.value + + sh->root.u.def.section->output_section->vma + + sh->root.u.def.section->output_offset); } else if (strcmp (name, ".PPC.EMB.sdata0") == 0 @@ -3865,7 +5259,7 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, (*_bfd_error_handler) (_("%s: The target (%s) of a %s relocation is in the wrong output section (%s)"), bfd_archive_filename (input_bfd), sym_name, - ppc_elf_howto_table[(int) r_type]->name, + howto->name, name); bfd_set_error (bfd_error_bad_value); @@ -3875,72 +5269,83 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (r_type == R_PPC_EMB_SDA21) { /* fill in register field */ - insn = bfd_get_32 (output_bfd, contents + offset); + insn = bfd_get_32 (output_bfd, contents + rel->r_offset); insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT); - bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); + bfd_put_32 (output_bfd, insn, contents + rel->r_offset); } } break; - /* Relocate against the beginning of the section */ - case (int) R_PPC_SECTOFF: - case (int) R_PPC_SECTOFF_LO: - case (int) R_PPC_SECTOFF_HI: - BFD_ASSERT (sec != (asection *) 0); - addend -= sec->output_section->vma; - break; - - case (int) R_PPC_SECTOFF_HA: + /* Relocate against the beginning of the section. */ + case R_PPC_SECTOFF: + case R_PPC_SECTOFF_LO: + case R_PPC_SECTOFF_HI: + case R_PPC_SECTOFF_HA: BFD_ASSERT (sec != (asection *) 0); addend -= sec->output_section->vma; - addend += ((relocation + addend) & 0x8000) << 1; break; - /* Negative relocations */ - case (int) R_PPC_EMB_NADDR32: - case (int) R_PPC_EMB_NADDR16: - case (int) R_PPC_EMB_NADDR16_LO: - case (int) R_PPC_EMB_NADDR16_HI: + /* Negative relocations. */ + case R_PPC_EMB_NADDR32: + case R_PPC_EMB_NADDR16: + case R_PPC_EMB_NADDR16_LO: + case R_PPC_EMB_NADDR16_HI: + case R_PPC_EMB_NADDR16_HA: addend -= 2 * relocation; break; - case (int) R_PPC_EMB_NADDR16_HA: - addend -= 2 * relocation; - addend += ((relocation + addend) & 0x8000) << 1; - break; - - /* NOP relocation that prevents garbage collecting linkers from omitting a - reference. */ - case (int) R_PPC_EMB_MRKREF: - continue; - - case (int) R_PPC_COPY: - case (int) R_PPC_GLOB_DAT: - case (int) R_PPC_JMP_SLOT: - case (int) R_PPC_RELATIVE: - case (int) R_PPC_PLT32: - case (int) R_PPC_PLTREL32: - case (int) R_PPC_PLT16_LO: - case (int) R_PPC_PLT16_HI: - case (int) R_PPC_PLT16_HA: - case (int) R_PPC_EMB_RELSEC16: - case (int) R_PPC_EMB_RELST_LO: - case (int) R_PPC_EMB_RELST_HI: - case (int) R_PPC_EMB_RELST_HA: - case (int) R_PPC_EMB_BIT_FLD: - (*_bfd_error_handler) (_("%s: Relocation %s is not yet supported for symbol %s."), - bfd_archive_filename (input_bfd), - ppc_elf_howto_table[(int) r_type]->name, - sym_name); + case R_PPC_COPY: + case R_PPC_GLOB_DAT: + case R_PPC_JMP_SLOT: + case R_PPC_RELATIVE: + case R_PPC_PLT32: + case R_PPC_PLTREL32: + case R_PPC_PLT16_LO: + case R_PPC_PLT16_HI: + case R_PPC_PLT16_HA: + case R_PPC_ADDR30: + case R_PPC_EMB_RELSEC16: + case R_PPC_EMB_RELST_LO: + case R_PPC_EMB_RELST_HI: + case R_PPC_EMB_RELST_HA: + case R_PPC_EMB_BIT_FLD: + (*_bfd_error_handler) + (_("%s: Relocation %s is not yet supported for symbol %s."), + bfd_archive_filename (input_bfd), + howto->name, + sym_name); bfd_set_error (bfd_error_invalid_operation); ret = FALSE; continue; + } - case (int) R_PPC_GNU_VTINHERIT: - case (int) R_PPC_GNU_VTENTRY: - /* These are no-ops in the end. */ - continue; + /* Do any further special processing. */ + switch (r_type) + { + default: + break; + + case R_PPC_ADDR16_HA: + case R_PPC_GOT16_HA: + case R_PPC_PLT16_HA: + case R_PPC_SECTOFF_HA: + case R_PPC_TPREL16_HA: + case R_PPC_DTPREL16_HA: + case R_PPC_GOT_TLSGD16_HA: + case R_PPC_GOT_TLSLD16_HA: + case R_PPC_GOT_TPREL16_HA: + case R_PPC_GOT_DTPREL16_HA: + case R_PPC_EMB_NADDR16_HA: + case R_PPC_EMB_RELST_HA: + /* It's just possible that this symbol is a weak symbol + that's not actually defined anywhere. In that case, + 'sec' would be NULL, and we should leave the symbol + alone (it will be set to zero elsewhere in the link). */ + if (sec != NULL) + /* Add 0x10000 if sign bit in 0:15 is set. */ + addend += ((relocation + addend) & 0x8000) << 1; + break; } #ifdef DEBUG @@ -3949,27 +5354,41 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, (int) r_type, sym_name, r_symndx, - (long) offset, + (long) rel->r_offset, (long) addend); #endif + if (unresolved_reloc + && !((input_section->flags & SEC_DEBUGGING) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)) + { + (*_bfd_error_handler) + (_("%s(%s+0x%lx): unresolvable relocation against symbol `%s'"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, + sym_name); + ret = FALSE; + } + r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, - offset, + rel->r_offset, relocation, addend); - if (r == bfd_reloc_ok) - ; - else if (r == bfd_reloc_overflow) + if (r != bfd_reloc_ok) { - const char *name; - - if (h != NULL) + if (sym_name == NULL) + sym_name = "(null)"; + if (r == bfd_reloc_overflow) { - if (h->root.type == bfd_link_hash_undefweak + if (warned) + continue; + if (h != NULL + && h->root.type == bfd_link_hash_undefweak && howto->pc_relative) { /* Assume this is a call protected by other code that @@ -3981,30 +5400,25 @@ ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section, continue; } - name = h->root.root.string; + if (! (*info->callbacks->reloc_overflow) (info, + sym_name, + howto->name, + rel->r_addend, + input_bfd, + input_section, + rel->r_offset)) + return FALSE; } else { - name = bfd_elf_string_from_elf_section (input_bfd, - symtab_hdr->sh_link, - sym->st_name); - if (name == NULL) - continue; - if (*name == '\0') - name = bfd_section_name (input_bfd, sec); + (*_bfd_error_handler) + (_("%s(%s+0x%lx): reloc against `%s': error %d"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, sym_name, (int) r); + ret = FALSE; } - - if (! (*info->callbacks->reloc_overflow) (info, - name, - howto->name, - (bfd_vma) 0, - input_bfd, - input_section, - offset)) - return FALSE; } - else - ret = FALSE; } #ifdef DEBUG @@ -4033,7 +5447,8 @@ ppc_elf_reloc_type_class (rela) } } -/* Support for core dump NOTE sections */ +/* Support for core dump NOTE sections. */ + static bfd_boolean ppc_elf_grok_prstatus (abfd, note) bfd *abfd; @@ -4044,21 +5459,21 @@ ppc_elf_grok_prstatus (abfd, note) switch (note->descsz) { - default: - return FALSE; + default: + return FALSE; - case 268: /* Linux/PPC */ - /* pr_cursig */ - elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + case 268: /* Linux/PPC. */ + /* pr_cursig */ + elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); - /* pr_pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + /* pr_pid */ + elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); - /* pr_reg */ - offset = 72; - raw_size = 192; + /* pr_reg */ + offset = 72; + raw_size = 192; - break; + break; } /* Make a ".reg/999" section. */ @@ -4073,14 +5488,14 @@ ppc_elf_grok_psinfo (abfd, note) { switch (note->descsz) { - default: - return FALSE; + default: + return FALSE; - case 128: /* Linux/PPC elf_prpsinfo */ - elf_tdata (abfd)->core_program - = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); - elf_tdata (abfd)->core_command - = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); + case 128: /* Linux/PPC elf_prpsinfo. */ + elf_tdata (abfd)->core_program + = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); + elf_tdata (abfd)->core_command + = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); } /* Note that for some reason, a spurious space is tacked @@ -4101,28 +5516,27 @@ ppc_elf_grok_psinfo (abfd, note) /* Very simple linked list structure for recording apuinfo values. */ typedef struct apuinfo_list { - struct apuinfo_list * next; - unsigned long value; + struct apuinfo_list *next; + unsigned long value; } apuinfo_list; static apuinfo_list * head; -static void apuinfo_list_init PARAMS ((void)); -static void apuinfo_list_add PARAMS ((unsigned long)); -static unsigned apuinfo_list_length PARAMS ((void)); +static void apuinfo_list_init PARAMS ((void)); +static void apuinfo_list_add PARAMS ((unsigned long)); +static unsigned apuinfo_list_length PARAMS ((void)); static unsigned long apuinfo_list_element PARAMS ((unsigned long)); -static void apuinfo_list_finish PARAMS ((void)); +static void apuinfo_list_finish PARAMS ((void)); -extern void ppc_elf_begin_write_processing +extern void ppc_elf_begin_write_processing PARAMS ((bfd *, struct bfd_link_info *)); -extern void ppc_elf_final_write_processing +extern void ppc_elf_final_write_processing PARAMS ((bfd *, bfd_boolean)); -extern bfd_boolean ppc_elf_write_section +extern bfd_boolean ppc_elf_write_section PARAMS ((bfd *, asection *, bfd_byte *)); - static void apuinfo_list_init PARAMS ((void)) { @@ -4133,7 +5547,7 @@ static void apuinfo_list_add (value) unsigned long value; { - apuinfo_list * entry = head; + apuinfo_list *entry = head; while (entry != NULL) { @@ -4154,7 +5568,7 @@ apuinfo_list_add (value) static unsigned apuinfo_list_length PARAMS ((void)) { - apuinfo_list * entry; + apuinfo_list *entry; unsigned long count; for (entry = head, count = 0; @@ -4182,11 +5596,11 @@ apuinfo_list_element (number) static void apuinfo_list_finish PARAMS ((void)) { - apuinfo_list * entry; + apuinfo_list *entry; for (entry = head; entry;) { - apuinfo_list * next = entry->next; + apuinfo_list *next = entry->next; free (entry); entry = next; } @@ -4194,8 +5608,8 @@ apuinfo_list_finish PARAMS ((void)) head = NULL; } -#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo" -#define APUINFO_LABEL "APUinfo" +#define APUINFO_SECTION_NAME ".PPC.EMB.apuinfo" +#define APUINFO_LABEL "APUinfo" /* Scan the input BFDs and create a linked list of the APUinfo values that will need to be emitted. */ @@ -4205,16 +5619,16 @@ ppc_elf_begin_write_processing (abfd, link_info) bfd *abfd; struct bfd_link_info *link_info; { - bfd * ibfd; - asection * asec; - char * buffer; - unsigned num_input_sections; + bfd *ibfd; + asection *asec; + char *buffer; + unsigned num_input_sections; bfd_size_type output_section_size; - unsigned i; - unsigned num_entries; + unsigned i; + unsigned num_entries; unsigned long offset; unsigned long length; - const char * error_message = NULL; + const char *error_message = NULL; if (link_info == NULL) return; @@ -4254,9 +5668,8 @@ ppc_elf_begin_write_processing (abfd, link_info) /* Read in the input sections contents. */ for (ibfd = link_info->input_bfds; ibfd; ibfd = ibfd->link_next) { - unsigned long datum; - char * ptr; - + unsigned long datum; + char *ptr; asec = bfd_get_section_by_name (ibfd, APUINFO_SECTION_NAME); if (asec == NULL) @@ -4319,7 +5732,7 @@ ppc_elf_begin_write_processing (abfd, link_info) asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); - if (! bfd_set_section_size (abfd, asec, output_section_size)) + if (! bfd_set_section_size (abfd, asec, output_section_size)) ibfd = abfd, error_message = _("warning: unable to set size of %s section in %s"); @@ -4327,8 +5740,8 @@ ppc_elf_begin_write_processing (abfd, link_info) free (buffer); if (error_message) - _bfd_error_handler (error_message, APUINFO_SECTION_NAME, - bfd_archive_filename (ibfd)); + (*_bfd_error_handler) (error_message, APUINFO_SECTION_NAME, + bfd_archive_filename (ibfd)); } @@ -4337,11 +5750,12 @@ ppc_elf_begin_write_processing (abfd, link_info) bfd_boolean ppc_elf_write_section (abfd, asec, contents) - bfd * abfd ATTRIBUTE_UNUSED; - asection * asec; - bfd_byte * contents ATTRIBUTE_UNUSED; + bfd *abfd ATTRIBUTE_UNUSED; + asection *asec; + bfd_byte *contents ATTRIBUTE_UNUSED; { - return apuinfo_list_length () && strcmp (asec->name, APUINFO_SECTION_NAME) == 0; + return (apuinfo_list_length () + && strcmp (asec->name, APUINFO_SECTION_NAME) == 0); } @@ -4349,13 +5763,13 @@ ppc_elf_write_section (abfd, asec, contents) void ppc_elf_final_write_processing (abfd, linker) - bfd * abfd; + bfd *abfd; bfd_boolean linker ATTRIBUTE_UNUSED; { - bfd_byte * buffer; - asection * asec; - unsigned i; - unsigned num_entries; + bfd_byte *buffer; + asection *asec; + unsigned i; + unsigned num_entries; bfd_size_type length; asec = bfd_get_section_by_name (abfd, APUINFO_SECTION_NAME); @@ -4372,7 +5786,8 @@ ppc_elf_final_write_processing (abfd, linker) buffer = bfd_malloc (length); if (buffer == NULL) { - _bfd_error_handler (_("failed to allocate space for new APUinfo section.")); + (*_bfd_error_handler) + (_("failed to allocate space for new APUinfo section.")); return; } @@ -4391,10 +5806,10 @@ ppc_elf_final_write_processing (abfd, linker) } if (length != asec->_raw_size) - _bfd_error_handler (_("failed to compute new APUinfo section.")); + (*_bfd_error_handler) (_("failed to compute new APUinfo section.")); if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length)) - _bfd_error_handler (_("failed to install new APUinfo section.")); + (*_bfd_error_handler) (_("failed to install new APUinfo section.")); free (buffer); @@ -4427,11 +5842,10 @@ ppc_elf_final_write_processing (abfd, linker) #define elf_backend_rela_normal 1 #define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data -#define bfd_elf32_bfd_relax_section ppc_elf_relax_section +#define bfd_elf32_bfd_relax_section ppc_elf_relax_section #define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup #define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags -#define bfd_elf32_bfd_final_link _bfd_elf32_gc_common_final_link -#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create +#define bfd_elf32_bfd_link_hash_table_create ppc_elf_link_hash_table_create #define elf_backend_object_p ppc_elf_object_p #define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook @@ -4452,8 +5866,8 @@ ppc_elf_final_write_processing (abfd, linker) #define elf_backend_grok_prstatus ppc_elf_grok_prstatus #define elf_backend_grok_psinfo ppc_elf_grok_psinfo #define elf_backend_reloc_type_class ppc_elf_reloc_type_class -#define elf_backend_begin_write_processing ppc_elf_begin_write_processing -#define elf_backend_final_write_processing ppc_elf_final_write_processing -#define elf_backend_write_section ppc_elf_write_section +#define elf_backend_begin_write_processing ppc_elf_begin_write_processing +#define elf_backend_final_write_processing ppc_elf_final_write_processing +#define elf_backend_write_section ppc_elf_write_section #include "elf32-target.h" diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h new file mode 100644 index 0000000..ead9c94 --- /dev/null +++ b/bfd/elf32-ppc.h @@ -0,0 +1,23 @@ +/* PowerPC-specific support for 64-bit ELF. + Copyright 2003 Free Software Foundation, Inc. + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +bfd_boolean ppc_elf_tls_setup + PARAMS ((bfd *, struct bfd_link_info *)); +bfd_boolean ppc_elf_tls_optimize + PARAMS ((bfd *, struct bfd_link_info *)); diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c index e8d94af..857b7a0 100644 --- a/bfd/elf32-s390.c +++ b/bfd/elf32-s390.c @@ -1,5 +1,5 @@ /* IBM S/390-specific support for 32-bit ELF - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Carl B. Pedersen and Martin Schwidefsky. This file is part of BFD, the Binary File Descriptor library. @@ -351,7 +351,7 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst) /* A relocation function which doesn't do anything. */ static bfd_reloc_status_type s390_tls_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd, error_message) + output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry; asymbol *symbol ATTRIBUTE_UNUSED; @@ -935,7 +935,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) && local_got_refcounts == NULL) { bfd_size_type size; - + size = symtab_hdr->sh_info; size *= (sizeof (bfd_signed_vma) + sizeof(char)); local_got_refcounts = ((bfd_signed_vma *) @@ -969,20 +969,20 @@ elf_s390_check_relocs (abfd, info, sec, relocs) /* Got is created, nothing to be done. */ break; - case R_390_PLT16DBL: - case R_390_PLT32DBL: + case R_390_PLT16DBL: + case R_390_PLT32DBL: case R_390_PLT32: case R_390_PLTOFF16: case R_390_PLTOFF32: /* This symbol requires a procedure linkage table entry. We - actually build the entry in adjust_dynamic_symbol, - because this might be a case of linking PIC code which is - never referenced by a dynamic object, in which case we - don't need to generate a procedure linkage table entry - after all. */ + actually build the entry in adjust_dynamic_symbol, + because this might be a case of linking PIC code which is + never referenced by a dynamic object, in which case we + don't need to generate a procedure linkage table entry + after all. */ /* If this is a local symbol, we resolve it directly without - creating a procedure linkage table entry. */ + creating a procedure linkage table entry. */ if (h != NULL) { h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; @@ -1022,10 +1022,10 @@ elf_s390_check_relocs (abfd, info, sec, relocs) case R_390_TLS_IEENT: if (info->shared) info->flags |= DF_STATIC_TLS; - /* Fall through */ + /* Fall through. */ case R_390_GOT12: - case R_390_GOT16: + case R_390_GOT16: case R_390_GOT32: case R_390_GOTENT: case R_390_TLS_GD32: @@ -1087,19 +1087,19 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (r_type != R_390_TLS_IE32) break; - /* Fall through */ + /* Fall through. */ case R_390_TLS_LE32: if (!info->shared) break; info->flags |= DF_STATIC_TLS; - /* Fall through */ + /* Fall through. */ - case R_390_8: - case R_390_16: + case R_390_8: + case R_390_16: case R_390_32: - case R_390_PC16: - case R_390_PC16DBL: + case R_390_PC16: + case R_390_PC16DBL: case R_390_PC32DBL: case R_390_PC32: if (h != NULL && !info->shared) @@ -1216,8 +1216,8 @@ elf_s390_check_relocs (abfd, info, sec, relocs) /* Track dynamic relocs needed for local syms too. We really need local syms available to do this easily. Oh well. */ - asection *s; + s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec, r_symndx); if (s == NULL) @@ -1231,6 +1231,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) if (p == NULL || p->sec != sec) { bfd_size_type amt = sizeof *p; + p = ((struct elf_s390_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt)); if (p == NULL) @@ -1253,17 +1254,17 @@ elf_s390_check_relocs (abfd, info, sec, relocs) /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ - case R_390_GNU_VTINHERIT: - if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) - return FALSE; - break; + case R_390_GNU_VTINHERIT: + if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; + break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ - case R_390_GNU_VTENTRY: - if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return FALSE; - break; + case R_390_GNU_VTENTRY: + if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; + break; default: break; @@ -1326,9 +1327,6 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - int r_type; - struct elf_link_hash_entry *h; elf_section_data (sec)->local_dynrel = NULL; @@ -1339,16 +1337,31 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_s390_link_hash_entry *eh; + struct elf_s390_dyn_relocs **pp; + struct elf_s390_dyn_relocs *p; - if (r_symndx < symtab_hdr->sh_info) - h = NULL; - else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf_s390_link_hash_entry *) h; - r_type = elf_s390_tls_transition (info, - ELF32_R_TYPE (rel->r_info), - r_symndx >= symtab_hdr->sh_info); + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } + + r_type = ELF32_R_TYPE (rel->r_info); + r_type = elf_s390_tls_transition (info, r_type, h != NULL); switch (r_type) { case R_390_TLS_LDM32: @@ -1379,14 +1392,7 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) if (local_got_refcounts[r_symndx] > 0) local_got_refcounts[r_symndx] -= 1; } - if (r_type != R_390_TLS_IE32) - break; - /* Fall through */ - - case R_390_TLS_LE32: - if (!info->shared) - break; - /* Fall through */ + break; case R_390_8: case R_390_12: @@ -1396,33 +1402,10 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) case R_390_PC16DBL: case R_390_PC32DBL: case R_390_PC32: - if (h != NULL) - { - struct elf_s390_link_hash_entry *eh; - struct elf_s390_dyn_relocs **pp; - struct elf_s390_dyn_relocs *p; - - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; - - eh = (struct elf_s390_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF32_R_TYPE (rel->r_info) == R_390_PC16 - || ELF32_R_TYPE (rel->r_info) == R_390_PC16DBL - || ELF32_R_TYPE (rel->r_info) == R_390_PC32DBL - || ELF32_R_TYPE (rel->r_info) == R_390_PC32) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; - + if (info->shared) + break; + /* Fall through. */ + case R_390_PLT16DBL: case R_390_PLT32DBL: case R_390_PLT32: @@ -1516,8 +1499,8 @@ elf_s390_adjust_dynamic_symbol (info, h) && h->root.type != bfd_link_hash_undefined)) { /* This case can occur if we saw a PLT32 reloc in an input - file, but the symbol was never referred to by a dynamic - object, or if all references were garbage collected. In + file, but the symbol was never referred to by a dynamic + object, or if all references were garbage collected. In such a case, we don't actually need to build a procedure linkage table, and we can just do a PC32 reloc instead. */ h->plt.offset = (bfd_vma) -1; @@ -1847,6 +1830,7 @@ allocate_dynrelocs (h, inf) for (p = eh->dyn_relocs; p != NULL; p = p->next) { asection *sreloc = elf_section_data (p->sec)->sreloc; + sreloc->_raw_size += p->count * sizeof (Elf32_External_Rela); } @@ -2014,7 +1998,7 @@ elf_s390_size_dynamic_sections (output_bfd, info) } else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0) { - if (s->_raw_size != 0 && s != htab->srelplt) + if (s->_raw_size != 0) relocs = TRUE; /* We use the reloc_count field as a counter if we need @@ -2079,10 +2063,10 @@ elf_s390_size_dynamic_sections (output_bfd, info) } if (relocs) - { - if (!add_dynamic_entry (DT_RELA, 0) - || !add_dynamic_entry (DT_RELASZ, 0) - || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) + { + if (!add_dynamic_entry (DT_RELA, 0) + || !add_dynamic_entry (DT_RELASZ, 0) + || !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela))) return FALSE; /* If any dynamic relocs apply to a read-only section, @@ -2202,8 +2186,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, r_type = ELF32_R_TYPE (rel->r_info); if (r_type == (int) R_390_GNU_VTINHERIT - || r_type == (int) R_390_GNU_VTENTRY) - continue; + || r_type == (int) R_390_GNU_VTENTRY) + continue; if (r_type >= (int) R_390_max) { bfd_set_error (bfd_error_bad_value); @@ -2252,7 +2236,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; @@ -2260,7 +2243,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, - input_section, rel->r_offset, + input_section, rel->r_offset, (!info->shared || info->no_undefined || ELF_ST_VISIBILITY (h->other))))) return FALSE; @@ -2291,7 +2274,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, Current offset - size first entry / entry size. */ plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE; - + /* Offset in GOT is PLT index plus GOT headers(3) times 4, addr & GOT addr. */ relocation = (plt_index + 3) * GOT_ENTRY_SIZE; @@ -2303,164 +2286,162 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, } /* Fall through. */ - case R_390_GOT12: - case R_390_GOT16: - case R_390_GOT32: + case R_390_GOT12: + case R_390_GOT16: + case R_390_GOT32: case R_390_GOTENT: - /* Relocation is to the entry for this symbol in the global - offset table. */ + /* Relocation is to the entry for this symbol in the global + offset table. */ if (htab->sgot == NULL) abort (); - if (h != NULL) - { + if (h != NULL) + { bfd_boolean dyn; - off = h->got.offset; + off = h->got.offset; dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) - || (info->shared - && (info->symbolic + if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) + || (info->shared + && (info->symbolic || h->dynindx == -1 || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) - { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 2, we use the - least significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rel.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; - else - { + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + { + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of 2, we use the + least significant bit to record whether we have + initialized it already. + + When doing a dynamic link, we create a .rel.got + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + if ((off & 1) != 0) + off &= ~1; + else + { bfd_put_32 (output_bfd, relocation, htab->sgot->contents + off); - h->got.offset |= 1; - } - } + h->got.offset |= 1; + } + } else unresolved_reloc = FALSE; - } - else - { + } + else + { if (local_got_offsets == NULL) abort (); - off = local_got_offsets[r_symndx]; + off = local_got_offsets[r_symndx]; - /* The offset must always be a multiple of 4. We use - the least significant bit to record whether we have - already generated the necessary reloc. */ - if ((off & 1) != 0) - off &= ~1; - else - { - bfd_put_32 (output_bfd, relocation, + /* The offset must always be a multiple of 4. We use + the least significant bit to record whether we have + already generated the necessary reloc. */ + if ((off & 1) != 0) + off &= ~1; + else + { + bfd_put_32 (output_bfd, relocation, htab->sgot->contents + off); - if (info->shared) - { - asection *srelgot; - Elf_Internal_Rela outrel; + if (info->shared) + { + asection *srelgot; + Elf_Internal_Rela outrel; bfd_byte *loc; - srelgot = htab->srelgot; + srelgot = htab->srelgot; if (srelgot == NULL) abort (); - outrel.r_offset = (htab->sgot->output_section->vma - + htab->sgot->output_offset - + off); - outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE); + outrel.r_offset = (htab->sgot->output_section->vma + + htab->sgot->output_offset + + off); + outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE); outrel.r_addend = relocation; loc = srelgot->contents; loc += srelgot->reloc_count++ * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - } + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + } - local_got_offsets[r_symndx] |= 1; - } - } + local_got_offsets[r_symndx] |= 1; + } + } if (off >= (bfd_vma) -2) abort (); relocation = htab->sgot->output_offset + off; - /* - * For @GOTENT the relocation is against the offset between - * the instruction and the symbols entry in the GOT and not - * between the start of the GOT and the symbols entry. We - * add the vma of the GOT to get the correct value. - */ + /* For @GOTENT the relocation is against the offset between + the instruction and the symbols entry in the GOT and not + between the start of the GOT and the symbols entry. We + add the vma of the GOT to get the correct value. */ if ( r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT) relocation += htab->sgot->output_section->vma; - break; + break; case R_390_GOTOFF16: - case R_390_GOTOFF32: - /* Relocation is relative to the start of the global offset - table. */ - - /* Note that sgot->output_offset is not involved in this - calculation. We always want the start of .got. If we - defined _GLOBAL_OFFSET_TABLE in a different way, as is - permitted by the ABI, we might have to change this - calculation. */ - relocation -= htab->sgot->output_section->vma; - break; - - case R_390_GOTPC: + case R_390_GOTOFF32: + /* Relocation is relative to the start of the global offset + table. */ + + /* Note that sgot->output_offset is not involved in this + calculation. We always want the start of .got. If we + defined _GLOBAL_OFFSET_TABLE in a different way, as is + permitted by the ABI, we might have to change this + calculation. */ + relocation -= htab->sgot->output_section->vma; + break; + + case R_390_GOTPC: case R_390_GOTPCDBL: - /* Use global offset table as symbol value. */ - relocation = htab->sgot->output_section->vma; + /* Use global offset table as symbol value. */ + relocation = htab->sgot->output_section->vma; unresolved_reloc = FALSE; - break; + break; - case R_390_PLT16DBL: - case R_390_PLT32DBL: - case R_390_PLT32: - /* Relocation is to the entry for this symbol in the - procedure linkage table. */ + case R_390_PLT16DBL: + case R_390_PLT32DBL: + case R_390_PLT32: + /* Relocation is to the entry for this symbol in the + procedure linkage table. */ - /* Resolve a PLT32 reloc against a local symbol directly, - without using the procedure linkage table. */ - if (h == NULL) - break; + /* Resolve a PLT32 reloc against a local symbol directly, + without using the procedure linkage table. */ + if (h == NULL) + break; - if (h->plt.offset == (bfd_vma) -1 + if (h->plt.offset == (bfd_vma) -1 || htab->splt == NULL) - { - /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ - break; - } - - relocation = (htab->splt->output_section->vma - + htab->splt->output_offset - + h->plt.offset); + { + /* We didn't make a PLT entry for this symbol. This + happens when statically linking PIC code, or when + using -Bsymbolic. */ + break; + } + + relocation = (htab->splt->output_section->vma + + htab->splt->output_offset + + h->plt.offset); unresolved_reloc = FALSE; - break; + break; case R_390_PLTOFF16: case R_390_PLTOFF32: - /* Relocation is to the entry for this symbol in the - procedure linkage table relative to the start of the GOT. */ + /* Relocation is to the entry for this symbol in the + procedure linkage table relative to the start of the GOT. */ /* For local symbols or if we didn't make a PLT entry for this symbol resolve the symbol directly. */ - if ( h == NULL + if ( h == NULL || h->plt.offset == (bfd_vma) -1 || htab->splt == NULL) { @@ -2468,28 +2449,28 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, break; } - relocation = (htab->splt->output_section->vma - + htab->splt->output_offset - + h->plt.offset + relocation = (htab->splt->output_section->vma + + htab->splt->output_offset + + h->plt.offset - htab->sgot->output_section->vma); unresolved_reloc = FALSE; - break; - - case R_390_8: - case R_390_16: - case R_390_32: - case R_390_PC16: - case R_390_PC16DBL: - case R_390_PC32DBL: - case R_390_PC32: + break; + + case R_390_8: + case R_390_16: + case R_390_32: + case R_390_PC16: + case R_390_PC16DBL: + case R_390_PC32DBL: + case R_390_PC32: /* r_symndx will be zero only for relocs against symbols from removed linkonce sections, or sections discarded by a linker script. */ - if (r_symndx == 0 - || (input_section->flags & SEC_ALLOC) == 0) + if (r_symndx == 0 + || (input_section->flags & SEC_ALLOC) == 0) break; - if ((info->shared + if ((info->shared && ((r_type != R_390_PC16 && r_type != R_390_PC16DBL && r_type != R_390_PC32DBL @@ -2509,9 +2490,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, & ELF_LINK_HASH_DEF_REGULAR) == 0) || h->root.type == bfd_link_hash_undefweak || h->root.type == bfd_link_hash_undefined))) - { - Elf_Internal_Rela outrel; - bfd_boolean skip, relocate; + { + Elf_Internal_Rela outrel; + bfd_boolean skip, relocate; asection *sreloc; bfd_byte *loc; @@ -2519,8 +2500,8 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, are copied into the output file to be resolved at run time. */ - skip = FALSE; - relocate = FALSE; + skip = FALSE; + relocate = FALSE; outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, input_section, @@ -2529,12 +2510,12 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, skip = TRUE; else if (outrel.r_offset == (bfd_vma) -2) skip = TRUE, relocate = TRUE; - outrel.r_offset += (input_section->output_section->vma - + input_section->output_offset); + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); - if (skip) + if (skip) memset (&outrel, 0, sizeof outrel); - else if (h != NULL + else if (h != NULL && h->dynindx != -1 && (r_type == R_390_PC16 || r_type == R_390_PC16DBL @@ -2544,17 +2525,17 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, || !info->symbolic || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) - { - outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + { + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; - } - else - { + } + else + { /* This symbol is local, or marked to become local. */ relocate = TRUE; outrel.r_info = ELF32_R_INFO (0, R_390_RELATIVE); outrel.r_addend = relocation + rel->r_addend; - } + } sreloc = elf_section_data (input_section)->sreloc; if (sreloc == NULL) @@ -2564,13 +2545,13 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); - /* If this reloc is against an external symbol, we do - not want to fiddle with the addend. Otherwise, we - need to include the symbol value so that it becomes - an addend for the dynamic reloc. */ - if (! relocate) - continue; - } + /* If this reloc is against an external symbol, we do + not want to fiddle with the addend. Otherwise, we + need to include the symbol value so that it becomes + an addend for the dynamic reloc. */ + if (! relocate) + continue; + } break; /* Relocations for tls literal pool entries. */ @@ -2592,7 +2573,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc); } - /* Fall through */ + /* Fall through. */ case R_390_TLS_GD32: case R_390_TLS_GOTIE32: @@ -2636,7 +2617,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -2667,7 +2648,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, { if (indx == 0) { - BFD_ASSERT (! unresolved_reloc); + BFD_ASSERT (! unresolved_reloc); bfd_put_32 (output_bfd, relocation - dtpoff_base (info), htab->sgot->contents + off + GOT_ENTRY_SIZE); @@ -2771,7 +2752,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, htab->tls_ldm_got.offset |= 1; } relocation = htab->sgot->output_offset + off; - unresolved_reloc = FALSE; + unresolved_reloc = FALSE; break; case R_390_TLS_LE32: @@ -2981,8 +2962,7 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_vma relative_offset; /* This symbol has an entry in the procedure linkage table. Set - it up. */ - + it up. */ if (h->dynindx == -1 || htab->splt == NULL || htab->sgotplt == NULL @@ -2990,26 +2970,26 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) abort (); /* Calc. index no. - Current offset - size first entry / entry size. */ + Current offset - size first entry / entry size. */ plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE; /* Offset in GOT is PLT index plus GOT headers(3) times 4, - addr & GOT addr. */ + addr & GOT addr. */ got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; /* S390 uses halfwords for relative branch calc! */ relative_offset = - ((PLT_FIRST_ENTRY_SIZE + - (PLT_ENTRY_SIZE * plt_index) + 18) / 2); + (PLT_ENTRY_SIZE * plt_index) + 18) / 2); /* If offset is > 32768, branch to a previous branch - 390 can only handle +-64 K jumps. */ + 390 can only handle +-64 K jumps. */ if ( -32768 > (int) relative_offset ) - relative_offset = - -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2); + relative_offset + = -(unsigned) (((65536 / PLT_ENTRY_SIZE - 1) * PLT_ENTRY_SIZE) / 2); /* Fill in the entry in the procedure linkage table. */ if (!info->shared) { - bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0, + bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD0, htab->splt->contents + h->plt.offset); bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD1, htab->splt->contents + h->plt.offset + 4); @@ -3080,10 +3060,10 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) } /* Insert offset into reloc. table here. */ bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela), - htab->splt->contents + h->plt.offset + 28); + htab->splt->contents + h->plt.offset + 28); /* Fill in the entry in the global offset table. - Points to instruction after GOT offset. */ + Points to instruction after GOT offset. */ bfd_put_32 (output_bfd, (htab->splt->output_section->vma + htab->splt->output_offset @@ -3120,7 +3100,7 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_byte *loc; /* This symbol has an entry in the global offset table. Set it - up. */ + up. */ if (htab->sgot == NULL || htab->srelgot == NULL) abort (); @@ -3143,16 +3123,16 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) BFD_ASSERT((h->got.offset & 1) != 0); rela.r_info = ELF32_R_INFO (0, R_390_RELATIVE); rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } else { BFD_ASSERT((h->got.offset & 1) == 0); bfd_put_32 (output_bfd, (bfd_vma) 0, htab->sgot->contents + h->got.offset); rela.r_info = ELF32_R_INFO (h->dynindx, R_390_GLOB_DAT); - rela.r_addend = 0; - } + rela.r_addend = 0; + } loc = htab->srelgot->contents; loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rela); @@ -3270,39 +3250,39 @@ elf_s390_finish_dynamic_sections (output_bfd, info) /* Fill in the special first entry in the procedure linkage table. */ if (htab->splt && htab->splt->_raw_size > 0) { - memset (htab->splt->contents, 0, PLT_FIRST_ENTRY_SIZE); - if (info->shared) + memset (htab->splt->contents, 0, PLT_FIRST_ENTRY_SIZE); + if (info->shared) { bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD0, - htab->splt->contents ); + htab->splt->contents ); bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD1, - htab->splt->contents +4 ); + htab->splt->contents +4 ); bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD2, - htab->splt->contents +8 ); + htab->splt->contents +8 ); bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD3, - htab->splt->contents +12 ); + htab->splt->contents +12 ); bfd_put_32 (output_bfd, (bfd_vma) PLT_PIC_FIRST_ENTRY_WORD4, - htab->splt->contents +16 ); - } - else - { - bfd_put_32 (output_bfd, (bfd_vma)PLT_FIRST_ENTRY_WORD0, - htab->splt->contents ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1, - htab->splt->contents +4 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD2, - htab->splt->contents +8 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3, - htab->splt->contents +12 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4, - htab->splt->contents +16 ); - bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5, - htab->splt->contents +20 ); - bfd_put_32 (output_bfd, - htab->sgotplt->output_section->vma + htab->splt->contents +16 ); + } + else + { + bfd_put_32 (output_bfd, (bfd_vma)PLT_FIRST_ENTRY_WORD0, + htab->splt->contents ); + bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD1, + htab->splt->contents +4 ); + bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD2, + htab->splt->contents +8 ); + bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD3, + htab->splt->contents +12 ); + bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD4, + htab->splt->contents +16 ); + bfd_put_32 (output_bfd, (bfd_vma) PLT_FIRST_ENTRY_WORD5, + htab->splt->contents +20 ); + bfd_put_32 (output_bfd, + htab->sgotplt->output_section->vma + htab->sgotplt->output_offset, - htab->splt->contents + 24); - } + htab->splt->contents + 24); + } elf_section_data (htab->splt->output_section) ->this_hdr.sh_entsize = 4; } @@ -3377,27 +3357,27 @@ elf_s390_grok_prstatus (abfd, note) #define elf_backend_plt_header_size PLT_ENTRY_SIZE #define elf_backend_rela_normal 1 -#define elf_info_to_howto elf_s390_info_to_howto +#define elf_info_to_howto elf_s390_info_to_howto #define bfd_elf32_bfd_is_local_label_name elf_s390_is_local_label_name #define bfd_elf32_bfd_link_hash_table_create elf_s390_link_hash_table_create #define bfd_elf32_bfd_reloc_type_lookup elf_s390_reloc_type_lookup #define elf_backend_adjust_dynamic_symbol elf_s390_adjust_dynamic_symbol -#define elf_backend_check_relocs elf_s390_check_relocs +#define elf_backend_check_relocs elf_s390_check_relocs #define elf_backend_copy_indirect_symbol elf_s390_copy_indirect_symbol #define elf_backend_create_dynamic_sections elf_s390_create_dynamic_sections #define elf_backend_finish_dynamic_sections elf_s390_finish_dynamic_sections #define elf_backend_finish_dynamic_symbol elf_s390_finish_dynamic_symbol -#define elf_backend_gc_mark_hook elf_s390_gc_mark_hook -#define elf_backend_gc_sweep_hook elf_s390_gc_sweep_hook +#define elf_backend_gc_mark_hook elf_s390_gc_mark_hook +#define elf_backend_gc_sweep_hook elf_s390_gc_sweep_hook #define elf_backend_reloc_type_class elf_s390_reloc_type_class -#define elf_backend_relocate_section elf_s390_relocate_section +#define elf_backend_relocate_section elf_s390_relocate_section #define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections #define elf_backend_reloc_type_class elf_s390_reloc_type_class #define elf_backend_grok_prstatus elf_s390_grok_prstatus #define bfd_elf32_mkobject elf_s390_mkobject -#define elf_backend_object_p elf_s390_object_p +#define elf_backend_object_p elf_s390_object_p #include "elf32-target.h" diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index f0e0177..20dc7d1 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -3500,6 +3500,9 @@ struct elf_sh_dyn_relocs /* Number of pc-relative relocs copied for the input section. */ bfd_size_type pc_count; + + /* If TRUE, R_SH_TLS_TPOFF32 relocation is generated. */ + bfd_boolean tls_tpoff32; }; /* sh ELF linker hash entry. */ @@ -3524,9 +3527,6 @@ struct elf_sh_link_hash_entry enum { GOT_UNKNOWN = 0, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE } tls_type; - - /* If TRUE, R_SH_TLS_TPOFF32 relocation is generated. */ - bfd_boolean tls_tpoff32; }; #define sh_elf_hash_entry(ent) ((struct elf_sh_link_hash_entry *)(ent)) @@ -3630,7 +3630,6 @@ sh_elf_link_hash_newfunc (entry, table, string) ret->datalabel_got.refcount = ret->root.got.refcount; #endif ret->tls_type = GOT_UNKNOWN; - ret->tls_tpoff32 = FALSE; } return (struct bfd_hash_entry *) ret; @@ -4053,7 +4052,7 @@ allocate_dynrelocs (h, inf) && eh->gotplt_refcount > 0) { /* The symbol has been forced local, or we have some direct got refs, - so treat all the gotplt refs as got refs. */ + so treat all the gotplt refs as got refs. */ h->got.refcount += eh->gotplt_refcount; if (h->plt.refcount >= eh->gotplt_refcount) h->plt.refcount -= eh->gotplt_refcount; @@ -4207,8 +4206,9 @@ allocate_dynrelocs (h, inf) } else { - if (sh_elf_hash_entry (h)->tls_tpoff32) - goto keep; + for (p = eh->dyn_relocs; p; p = p->next) + if (p->tls_tpoff32) + goto keep; /* For the non-shared case, discard space for relocs against symbols which turn out to need copy relocs or are not @@ -4785,7 +4785,6 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (! info->symbolic || info->allow_shlib_undefined) && ! info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; @@ -5256,10 +5255,18 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, tls_type = sh_elf_hash_entry (h)->tls_type; if (! info->shared && (h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) - && (tls_type == GOT_TLS_IE - || sh_elf_hash_entry (h)->tls_tpoff32)) - r_type = R_SH_TLS_LE_32; + || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + { + struct elf_sh_dyn_relocs *p; + + /* If TPOFF32 relocation can be created, convert it. */ + for (p = sh_elf_hash_entry (h)->dyn_relocs; p; p = p->next) + if (p->sec == input_section && p->tls_tpoff32) + { + r_type = R_SH_TLS_LE_32; + break; + } + } } if (r_type == R_SH_TLS_GD_32 && tls_type == GOT_TLS_IE) @@ -5368,7 +5375,13 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT (sreloc != NULL); } - indx = (h && h->dynindx != -1) ? h->dynindx : 0; + if (h == NULL + || h->dynindx == -1 + || (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + indx = 0; + else + indx = h->dynindx; outrel.r_offset = (input_section->output_section->vma + input_section->output_offset + rel->r_offset); @@ -5400,7 +5413,7 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -5415,7 +5428,13 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section, outrel.r_offset = (sgot->output_section->vma + sgot->output_offset + off); - indx = (h && h->dynindx != -1) ? h->dynindx : 0; + if (h == NULL + || h->dynindx == -1 + || (! info->shared + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) + indx = 0; + else + indx = h->dynindx; dr_type = (r_type == R_SH_TLS_GD_32 ? R_SH_TLS_DTPMOD32 : R_SH_TLS_TPOFF32); if (dr_type == R_SH_TLS_TPOFF32 && indx == 0) @@ -5900,9 +5919,6 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - struct elf_link_hash_entry *h; - struct elf_sh_link_hash_entry *eh; elf_section_data (sec)->local_dynrel = NULL; @@ -5913,15 +5929,20 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; #ifdef INCLUDE_SHMEDIA int seen_stt_datalabel = 0; #endif r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx < symtab_hdr->sh_info) - h = NULL; - else + if (r_symndx >= symtab_hdr->sh_info) { + struct elf_sh_link_hash_entry *eh; + struct elf_sh_dyn_relocs **pp; + struct elf_sh_dyn_relocs *p; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; #ifdef INCLUDE_SHMEDIA while (h->root.type == bfd_link_hash_indirect @@ -5931,12 +5952,18 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) h = (struct elf_link_hash_entry *) h->root.u.i.link; } #endif + eh = (struct elf_sh_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } } - eh = (struct elf_sh_link_hash_entry *) h; - switch (sh_elf_optimized_tls_reloc (info, ELF32_R_TYPE (rel->r_info), - ELF32_R_SYM (rel->r_info) - >= symtab_hdr->sh_info)) + r_type = ELF32_R_TYPE (rel->r_info); + switch (sh_elf_optimized_tls_reloc (info, r_type, h != NULL)) { case R_SH_TLS_LD_32: if (sh_elf_hash_table (info)->tls_ldm_got.refcount > 0) @@ -5969,6 +5996,8 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) #ifdef INCLUDE_SHMEDIA if (seen_stt_datalabel) { + struct elf_sh_link_hash_entry *eh; + eh = (struct elf_sh_link_hash_entry *) h; if (eh->datalabel_got.refcount > 0) eh->datalabel_got.refcount -= 1; } @@ -5994,27 +6023,9 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) case R_SH_DIR32: case R_SH_REL32: - if (h != NULL) - { - struct elf_sh_dyn_relocs **pp; - struct elf_sh_dyn_relocs *p; - - - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF32_R_TYPE (rel->r_info) == R_SH_REL32) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + if (info->shared) + break; + /* Fall thru */ case R_SH_PLT32: #ifdef INCLUDE_SHMEDIA @@ -6041,6 +6052,8 @@ sh_elf_gc_sweep_hook (abfd, info, sec, relocs) #endif if (h != NULL) { + struct elf_sh_link_hash_entry *eh; + eh = (struct elf_sh_link_hash_entry *) h; if (eh->gotplt_refcount > 0) { eh->gotplt_refcount -= 1; @@ -6596,6 +6609,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs) p->sec = sec; p->count = 0; p->pc_count = 0; + p->tls_tpoff32 = FALSE; } p->count += 1; @@ -6693,11 +6707,11 @@ sh_elf_check_relocs (abfd, info, sec, relocs) p->sec = sec; p->count = 0; p->pc_count = 0; + p->tls_tpoff32 = FALSE; } p->count += 1; - if (h) - sh_elf_hash_entry (h)->tls_tpoff32 = TRUE; + p->tls_tpoff32 = TRUE; } break; diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c index dcdce31..e2c6544 100644 --- a/bfd/elf32-sparc.c +++ b/bfd/elf32-sparc.c @@ -2,21 +2,21 @@ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -63,8 +63,8 @@ static struct bfd_hash_entry *link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); static struct bfd_link_hash_table *elf32_sparc_link_hash_table_create PARAMS ((bfd *)); -static bfd_boolean create_got_section PARAMS ((bfd *, - struct bfd_link_info *)); +static bfd_boolean create_got_section + PARAMS ((bfd *, struct bfd_link_info *)); static bfd_boolean elf32_sparc_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); static void elf32_sparc_copy_indirect_symbol @@ -291,11 +291,14 @@ elf32_sparc_reloc_type_lookup (abfd, code) return &elf32_sparc_rev32_howto; default: - for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) - { - if (sparc_reloc_map[i].bfd_reloc_val == code) - return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; - } + for (i = 0; + i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); + i++) + { + if (sparc_reloc_map[i].bfd_reloc_val == code) + return (_bfd_sparc_elf_howto_table + + (int) sparc_reloc_map[i].elf_reloc_val); + } } bfd_set_error (bfd_error_bad_value); return NULL; @@ -633,9 +636,9 @@ link_hash_newfunc (entry, table, string) if (entry == NULL) { entry = bfd_hash_allocate (table, - sizeof (struct elf32_sparc_link_hash_entry)); + sizeof (struct elf32_sparc_link_hash_entry)); if (entry == NULL) - return entry; + return entry; } /* Call the allocation method of the superclass. */ @@ -758,32 +761,32 @@ elf32_sparc_copy_indirect_symbol (bed, dir, ind) if (eind->dyn_relocs != NULL) { if (edir->dyn_relocs != NULL) - { - struct elf32_sparc_dyn_relocs **pp; - struct elf32_sparc_dyn_relocs *p; - - if (ind->root.type == bfd_link_hash_indirect) - abort (); - - /* Add reloc counts against the weak sym to the strong sym - list. Merge any entries against the same section. */ - for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) - { - struct elf32_sparc_dyn_relocs *q; - - for (q = edir->dyn_relocs; q != NULL; q = q->next) - if (q->sec == p->sec) - { - q->pc_count += p->pc_count; - q->count += p->count; - *pp = p->next; - break; - } - if (q == NULL) - pp = &p->next; - } - *pp = edir->dyn_relocs; - } + { + struct elf32_sparc_dyn_relocs **pp; + struct elf32_sparc_dyn_relocs *p; + + if (ind->root.type == bfd_link_hash_indirect) + abort (); + + /* Add reloc counts against the weak sym to the strong sym + list. Merge any entries against the same section. */ + for (pp = &eind->dyn_relocs; (p = *pp) != NULL; ) + { + struct elf32_sparc_dyn_relocs *q; + + for (q = edir->dyn_relocs; q != NULL; q = q->next) + if (q->sec == p->sec) + { + q->pc_count += p->pc_count; + q->count += p->count; + *pp = p->next; + break; + } + if (q == NULL) + pp = &p->next; + } + *pp = edir->dyn_relocs; + } edir->dyn_relocs = eind->dyn_relocs; eind->dyn_relocs = NULL; @@ -820,15 +823,15 @@ elf32_sparc_tls_transition (info, abfd, r_type, is_local) return R_SPARC_TLS_IE_HI22; case R_SPARC_TLS_GD_LO10: if (is_local) - return R_SPARC_TLS_LE_LOX10; + return R_SPARC_TLS_LE_LOX10; return R_SPARC_TLS_IE_LO10; case R_SPARC_TLS_IE_HI22: if (is_local) - return R_SPARC_TLS_LE_HIX22; + return R_SPARC_TLS_LE_HIX22; return r_type; case R_SPARC_TLS_IE_LO10: if (is_local) - return R_SPARC_TLS_LE_LOX10; + return R_SPARC_TLS_LE_LOX10; return r_type; case R_SPARC_TLS_LDM_HI22: return R_SPARC_TLS_LE_HIX22; @@ -880,12 +883,12 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) r_type = ELF32_R_TYPE (rel->r_info); if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) - { - (*_bfd_error_handler) (_("%s: bad symbol index: %d"), - bfd_archive_filename (abfd), - r_symndx); - return FALSE; - } + { + (*_bfd_error_handler) (_("%s: bad symbol index: %d"), + bfd_archive_filename (abfd), + r_symndx); + return FALSE; + } if (r_symndx < symtab_hdr->sh_info) h = NULL; @@ -1049,17 +1052,17 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) case R_SPARC_PLT32: case R_SPARC_WPLT30: /* This symbol requires a procedure linkage table entry. We - actually build the entry in adjust_dynamic_symbol, - because this might be a case of linking PIC code without - linking in any dynamic objects, in which case we don't - need to generate a procedure linkage table after all. */ + actually build the entry in adjust_dynamic_symbol, + because this might be a case of linking PIC code without + linking in any dynamic objects, in which case we don't + need to generate a procedure linkage table after all. */ if (h == NULL) { /* The Solaris native assembler will generate a WPLT30 - reloc for a local symbol if you assemble a call from - one section to another when using -K pic. We treat - it as WDISP30. */ + reloc for a local symbol if you assemble a call from + one section to another when using -K pic. We treat + it as WDISP30. */ if (ELF32_R_TYPE (rel->r_info) == R_SPARC_PLT32) goto r_sparc_plt32; break; @@ -1149,8 +1152,8 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) struct elf32_sparc_dyn_relocs **head; /* When creating a shared object, we must copy these - relocs into the output file. We create a reloc - section in dynobj and make room for the reloc. */ + relocs into the output file. We create a reloc + section in dynobj and make room for the reloc. */ if (sreloc == NULL) { const char *name; @@ -1231,15 +1234,15 @@ elf32_sparc_check_relocs (abfd, info, sec, relocs) break; - case R_SPARC_GNU_VTINHERIT: - if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) - return FALSE; - break; + case R_SPARC_GNU_VTINHERIT: + if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; + break; - case R_SPARC_GNU_VTENTRY: - if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) - return FALSE; - break; + case R_SPARC_GNU_VTENTRY: + if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) + return FALSE; + break; default: break; @@ -1263,21 +1266,21 @@ elf32_sparc_gc_mark_hook (sec, info, rel, h, sym) { case R_SPARC_GNU_VTINHERIT: case R_SPARC_GNU_VTENTRY: - break; + break; default: - switch (h->root.type) - { - case bfd_link_hash_defined: - case bfd_link_hash_defweak: - return h->root.u.def.section; + switch (h->root.type) + { + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->root.u.def.section; - case bfd_link_hash_common: - return h->root.u.c.p->section; + case bfd_link_hash_common: + return h->root.u.c.p->section; default: break; - } + } } } else @@ -1294,14 +1297,12 @@ elf32_sparc_gc_sweep_hook (abfd, info, sec, relocs) asection *sec; const Elf_Internal_Rela *relocs; { - Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - int r_type; - struct elf_link_hash_entry *h; + + elf_section_data (sec)->local_dynrel = NULL; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); @@ -1309,116 +1310,98 @@ elf32_sparc_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch ((r_type = elf32_sparc_tls_transition (info, abfd, - ELF32_R_TYPE (rel->r_info), - ELF32_R_SYM (rel->r_info) - >= symtab_hdr->sh_info))) - { - case R_SPARC_TLS_LDM_HI22: - case R_SPARC_TLS_LDM_LO10: - if (elf32_sparc_hash_table (info)->tls_ldm_got.refcount > 0) - elf32_sparc_hash_table (info)->tls_ldm_got.refcount -= 1; - break; - - case R_SPARC_TLS_LE_HIX22: - case R_SPARC_TLS_LE_LOX10: - if (info->shared) - goto r_sparc_plt32; - break; + { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; - case R_SPARC_PC10: - case R_SPARC_PC22: - if ((r_symndx = ELF32_R_SYM (rel->r_info)) >= symtab_hdr->sh_info - && strcmp (sym_hashes[r_symndx - - symtab_hdr->sh_info]->root.root.string, - "_GLOBAL_OFFSET_TABLE_") == 0) - break; - /* Fall through. */ + r_symndx = ELF32_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf32_sparc_link_hash_entry *eh; + struct elf32_sparc_dyn_relocs **pp; + struct elf32_sparc_dyn_relocs *p; - case R_SPARC_DISP8: - case R_SPARC_DISP16: - case R_SPARC_DISP32: - case R_SPARC_WDISP30: - case R_SPARC_WDISP22: - case R_SPARC_WDISP19: - case R_SPARC_WDISP16: - case R_SPARC_8: - case R_SPARC_16: - case R_SPARC_32: - case R_SPARC_HI22: - case R_SPARC_22: - case R_SPARC_13: - case R_SPARC_LO10: - case R_SPARC_UA16: - case R_SPARC_UA32: - r_sparc_plt32: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf32_sparc_link_hash_entry *eh; - struct elf32_sparc_dyn_relocs **pp; - struct elf32_sparc_dyn_relocs *p; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf32_sparc_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + r_type = ELF32_R_TYPE (rel->r_info); + r_type = elf32_sparc_tls_transition (info, abfd, r_type, h != NULL); + switch (r_type) + { + case R_SPARC_TLS_LDM_HI22: + case R_SPARC_TLS_LDM_LO10: + if (elf32_sparc_hash_table (info)->tls_ldm_got.refcount > 0) + elf32_sparc_hash_table (info)->tls_ldm_got.refcount -= 1; + break; - if (! info->shared) - --h->plt.refcount; + case R_SPARC_TLS_GD_HI22: + case R_SPARC_TLS_GD_LO10: + case R_SPARC_TLS_IE_HI22: + case R_SPARC_TLS_IE_LO10: + case R_SPARC_GOT10: + case R_SPARC_GOT13: + case R_SPARC_GOT22: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount--; + } + else + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx]--; + } + break; - eh = (struct elf32_sparc_link_hash_entry *) h; + case R_SPARC_PC10: + case R_SPARC_PC22: + if (h != NULL + && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + break; + /* Fall through. */ - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (_bfd_sparc_elf_howto_table[r_type].pc_relative) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + case R_SPARC_DISP8: + case R_SPARC_DISP16: + case R_SPARC_DISP32: + case R_SPARC_WDISP30: + case R_SPARC_WDISP22: + case R_SPARC_WDISP19: + case R_SPARC_WDISP16: + case R_SPARC_8: + case R_SPARC_16: + case R_SPARC_32: + case R_SPARC_HI22: + case R_SPARC_22: + case R_SPARC_13: + case R_SPARC_LO10: + case R_SPARC_UA16: + case R_SPARC_UA32: + case R_SPARC_PLT32: + if (info->shared) + break; + /* Fall through. */ - case R_SPARC_TLS_GD_HI22: - case R_SPARC_TLS_GD_LO10: - case R_SPARC_TLS_IE_HI22: - case R_SPARC_TLS_IE_LO10: - case R_SPARC_GOT10: - case R_SPARC_GOT13: - case R_SPARC_GOT22: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount--; - } - else - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; - } - break; - - case R_SPARC_PLT32: - case R_SPARC_HIPLT22: - case R_SPARC_LOPLT10: - case R_SPARC_PCPLT32: - case R_SPARC_PCPLT10: - r_symndx = ELF32_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount--; - } - if (r_type == R_SPARC_PLT32) - goto r_sparc_plt32; - break; + case R_SPARC_WPLT30: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount--; + } + break; - default: - break; - } + default: + break; + } + } return TRUE; } @@ -1632,7 +1615,7 @@ allocate_dynrelocs (h, inf) /* The first four entries in .plt are reserved. */ if (s->_raw_size == 0) s->_raw_size = 4 * PLT_ENTRY_SIZE; - + /* The procedure linkage table has a maximum size. */ if (s->_raw_size >= 0x400000) { @@ -2058,7 +2041,7 @@ struct elf32_sparc_section_data }; #define sec_do_relax(sec) \ - ((struct elf32_sparc_section_data *) (sec)->used_by_bfd)->do_relax + ((struct elf32_sparc_section_data *) elf_section_data (sec))->do_relax static bfd_boolean elf32_sparc_new_section_hook (abfd, sec) @@ -2176,8 +2159,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, r_type = ELF32_R_TYPE (rel->r_info); if (r_type == R_SPARC_GNU_VTINHERIT - || r_type == R_SPARC_GNU_VTENTRY) - continue; + || r_type == R_SPARC_GNU_VTENTRY) + continue; if (r_type < 0 || r_type >= (int) R_SPARC_max_std) { @@ -2224,7 +2207,6 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) ; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -2245,7 +2227,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_GOT13: case R_SPARC_GOT22: /* Relocation is to the entry for this symbol in the global - offset table. */ + offset table. */ if (htab->sgot == NULL) abort (); @@ -2265,13 +2247,13 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))) { /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 4, we use the - least significant bit to record whether we have - initialized it already. + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. We must initialize + this entry in the global offset table. Since the + offset must always be a multiple of 4, we use the + least significant bit to record whether we have + initialized it already. When doing a dynamic link, we create a .rela.got relocation entry to initialize the value. This @@ -2343,7 +2325,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, case R_SPARC_WPLT30: r_sparc_wplt30: /* Relocation is to the entry for this symbol in the - procedure linkage table. */ + procedure linkage table. */ /* The Solaris native assembler will generate a WPLT30 reloc for a local symbol if you assemble a call from one @@ -2355,8 +2337,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, if (h->plt.offset == (bfd_vma) -1) { /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ + happens when statically linking PIC code, or when + using -Bsymbolic. */ break; } @@ -2428,8 +2410,8 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, bfd_boolean skip, relocate = FALSE; /* When generating a shared object, these relocations - are copied into the output file to be resolved at run - time. */ + are copied into the output file to be resolved at run + time. */ BFD_ASSERT (sreloc != NULL); @@ -2481,7 +2463,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, if (skip) memset (&outrel, 0, sizeof outrel); /* h->dynindx may be -1 if the symbol was marked to - become local. */ + become local. */ else if (h != NULL && ! is_plt && ((! info->symbolic && h->dynindx != -1) || (h->elf_link_hash_flags @@ -2550,7 +2532,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); /* This reloc will be computed at runtime, so there's no - need to do anything now. */ + need to do anything now. */ if (! relocate) continue; } @@ -2615,7 +2597,7 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, break; } - if (h != NULL) + if (h != NULL) { off = h->got.offset; h->got.offset |= 1; @@ -2626,14 +2608,14 @@ elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section, off = local_got_offsets[r_symndx]; local_got_offsets[r_symndx] |= 1; } - + r_sparc_tlsldm: if (htab->sgot == NULL) abort (); if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; Elf32_External_Rela *loc; @@ -3099,7 +3081,7 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) { bfd *dynobj; struct elf32_sparc_link_hash_table *htab; - + htab = elf32_sparc_hash_table (info); dynobj = htab->elf.dynobj; @@ -3111,7 +3093,7 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_byte *loc; /* This symbol has an entry in the procedure linkage table. Set - it up. */ + it up. */ BFD_ASSERT (h->dynindx != -1); @@ -3165,7 +3147,7 @@ elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_byte *loc; /* This symbol has an entry in the global offset table. Set it - up. */ + up. */ sgot = htab->sgot; srela = htab->srelgot; @@ -3245,7 +3227,7 @@ elf32_sparc_finish_dynamic_sections (output_bfd, info) bfd *dynobj; asection *sdyn; struct elf32_sparc_link_hash_table *htab; - + htab = elf32_sparc_hash_table (info); dynobj = htab->elf.dynobj; @@ -3513,7 +3495,7 @@ elf32_sparc_reloc_type_class (rela) #define elf_backend_object_p elf32_sparc_object_p #define elf_backend_final_write_processing \ elf32_sparc_final_write_processing -#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook +#define elf_backend_gc_mark_hook elf32_sparc_gc_mark_hook #define elf_backend_gc_sweep_hook elf32_sparc_gc_sweep_hook #define elf_backend_reloc_type_class elf32_sparc_reloc_type_class diff --git a/bfd/elf32-vax.c b/bfd/elf32-vax.c index a9e8b0b..1aca042 100644 --- a/bfd/elf32-vax.c +++ b/bfd/elf32-vax.c @@ -1,23 +1,23 @@ /* VAX series support for 32-bit ELF - Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Matt Thomas <matt@3am-software.com>. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -1539,7 +1539,6 @@ elf_vax_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; @@ -1699,7 +1698,6 @@ elf_vax_relocate_section (output_bfd, info, input_bfd, input_section, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - if (sreloc == NULL) { const char *name; @@ -1908,7 +1906,6 @@ elf_vax_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the procedure linkage table. Set it up. */ - BFD_ASSERT (h->dynindx != -1); splt = bfd_get_section_by_name (dynobj, ".plt"); @@ -1975,7 +1972,6 @@ elf_vax_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the global offset table. Set it up. */ - sgot = bfd_get_section_by_name (dynobj, ".got"); srela = bfd_get_section_by_name (dynobj, ".rela.got"); BFD_ASSERT (sgot != NULL && srela != NULL); @@ -2014,7 +2010,6 @@ elf_vax_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_byte *loc; /* This symbol needs a copy reloc. Set it up. */ - BFD_ASSERT (h->dynindx != -1 && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak)); diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index 9569b38..9f564ca 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -2184,7 +2184,13 @@ elf64_alpha_relax_section (abfd, sec, link_info, again) info.h = NULL; info.other = isym->st_other; - info.first_gotent = &local_got_entries[r_symndx]; + if (local_got_entries) + info.first_gotent = &local_got_entries[r_symndx]; + else + { + info.first_gotent = &info.gotent; + info.gotent = NULL; + } } else { @@ -4438,8 +4444,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, unless it has been done already. */ if ((sec->flags & SEC_MERGE) && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && (elf_section_data (sec)->sec_info_type - == ELF_INFO_TYPE_MERGE) + && sec->sec_info_type == ELF_INFO_TYPE_MERGE && gotent && !gotent->reloc_xlated) { @@ -4498,7 +4503,6 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.root.type == bfd_link_hash_undefweak) undef_weak_ref = TRUE; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) ; @@ -5171,7 +5175,7 @@ elf64_alpha_finish_dynamic_sections (output_bfd, info) bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon); } - /* Initialize the PLT0 entry */ + /* Initialize the PLT0 entry. */ if (splt->_raw_size > 0) { bfd_put_32 (output_bfd, PLT_HEADER_WORD1, splt->contents); diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c index 98f46dc..4d3b8d4 100644 --- a/bfd/elf64-hppa.c +++ b/bfd/elf64-hppa.c @@ -1,21 +1,21 @@ /* Support for HPPA 64-bit ELF - Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "alloca-conf.h" #include "bfd.h" diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c index d29f286..807ddf5 100644 --- a/bfd/elf64-mips.c +++ b/bfd/elf64-mips.c @@ -300,9 +300,11 @@ static reloc_howto_type mips_elf64_howto_table_rel[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -795,9 +797,11 @@ static reloc_howto_type mips_elf64_howto_table_rela[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -1894,7 +1898,7 @@ static const struct elf_reloc_map mips_reloc_map[] = /* There is no BFD reloc for R_MIPS_REL32. */ { BFD_RELOC_64, R_MIPS_64 }, { BFD_RELOC_CTOR, R_MIPS_64 }, - { BFD_RELOC_16_PCREL, R_MIPS_PC16 }, + { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 }, { BFD_RELOC_HI16_S, R_MIPS_HI16 }, { BFD_RELOC_LO16, R_MIPS_LO16 }, { BFD_RELOC_GPREL16, R_MIPS_GPREL16 }, diff --git a/bfd/elf64-mmix.c b/bfd/elf64-mmix.c index a7b2806..bcf9962 100644 --- a/bfd/elf64-mmix.c +++ b/bfd/elf64-mmix.c @@ -52,7 +52,7 @@ struct _mmix_elf_section_data }; #define mmix_elf_section_data(sec) \ - ((struct _mmix_elf_section_data *) (sec)->used_by_bfd) + ((struct _mmix_elf_section_data *) elf_section_data (sec)) /* For each section containing a base-plus-offset (BPO) reloc, we attach this struct as mmix_elf_section_data (section)->bpo, which is otherwise diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c index 2ca139d..23d95d5 100644 --- a/bfd/elf64-ppc.c +++ b/bfd/elf64-ppc.c @@ -3,21 +3,21 @@ Written by Linus Nordberg, Swox AB <info@swox.com>, based on elf32-ppc.c by Ian Lance Taylor. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file is based on the 64-bit PowerPC ELF ABI. It is also based on the file elf32-ppc.c. */ @@ -71,7 +71,11 @@ static bfd_boolean ppc64_elf_new_section_hook #define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE /* TOC base pointers offset from start of TOC. */ -#define TOC_BASE_OFF (0x8000) +#define TOC_BASE_OFF 0x8000 + +/* Offset of tp and dtp pointers from start of TLS block. */ +#define TP_OFFSET 0x7000 +#define DTP_OFFSET 0x8000 /* .plt call stub instructions. */ #define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */ @@ -134,8 +138,8 @@ static reloc_howto_type ppc64_elf_howto_raw[] = { /* This reloc does nothing. */ HOWTO (R_PPC64_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -1152,6 +1156,616 @@ static reloc_howto_type ppc64_elf_howto_raw[] = { 0xfffc, /* dst_mask */ FALSE), /* pcrel_offset */ + /* Marker reloc for TLS. */ + HOWTO (R_PPC64_TLS, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_PPC64_TLS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes the load module index of the load module that contains the + definition of its TLS sym. */ + HOWTO (R_PPC64_DTPMOD64, + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPMOD64", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ONES (64), /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes a dtv-relative displacement, the difference between the value + of sym+add and the base address of the thread-local storage block that + contains the definition of sym, minus 0x8000. */ + HOWTO (R_PPC64_DTPREL64, + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL64", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ONES (64), /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit dtprel reloc. */ + HOWTO (R_PPC64_DTPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16, but no overflow. */ + HOWTO (R_PPC64_DTPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HI, but next higher group of 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HIGHER, + 32, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HIGHER", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HIGHER, but adjust for low 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HIGHERA, + 32, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HIGHERA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HIGHER, but next higher group of 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HIGHEST, + 48, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HIGHEST", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_HIGHEST, but adjust for low 16 bits. */ + HOWTO (R_PPC64_DTPREL16_HIGHESTA, + 48, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_HIGHESTA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16, but for insns with a DS field. */ + HOWTO (R_PPC64_DTPREL16_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like DTPREL16_DS, but no overflow. */ + HOWTO (R_PPC64_DTPREL16_LO_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_DTPREL16_LO_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Computes a tp-relative displacement, the difference between the value of + sym+add and the value of the thread pointer (r13). */ + HOWTO (R_PPC64_TPREL64, + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL64", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ONES (64), /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 16 bit tprel reloc. */ + HOWTO (R_PPC64_TPREL16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16, but no overflow. */ + HOWTO (R_PPC64_TPREL16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC64_TPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_TPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HI, but next higher group of 16 bits. */ + HOWTO (R_PPC64_TPREL16_HIGHER, + 32, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HIGHER", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HIGHER, but adjust for low 16 bits. */ + HOWTO (R_PPC64_TPREL16_HIGHERA, + 32, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HIGHERA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HIGHER, but next higher group of 16 bits. */ + HOWTO (R_PPC64_TPREL16_HIGHEST, + 48, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HIGHEST", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_HIGHEST, but adjust for low 16 bits. */ + HOWTO (R_PPC64_TPREL16_HIGHESTA, + 48, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_HIGHESTA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16, but for insns with a DS field. */ + HOWTO (R_PPC64_TPREL16_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like TPREL16_DS, but no overflow. */ + HOWTO (R_PPC64_TPREL16_LO_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_TPREL16_LO_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates two contiguous entries in the GOT to hold a tls_index structure, + with values (sym+add)@dtpmod and (sym+add)@dtprel, and computes the offset + to the first entry relative to the TOC base (r2). */ + HOWTO (R_PPC64_GOT_TLSGD16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSGD16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16, but no overflow. */ + HOWTO (R_PPC64_GOT_TLSGD16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSGD16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC64_GOT_TLSGD16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSGD16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSGD16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_GOT_TLSGD16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSGD16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates two contiguous entries in the GOT to hold a tls_index structure, + with values (sym+add)@dtpmod and zero, and computes the offset to the + first entry relative to the TOC base (r2). */ + HOWTO (R_PPC64_GOT_TLSLD16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSLD16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16, but no overflow. */ + HOWTO (R_PPC64_GOT_TLSLD16_LO, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSLD16_LO", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16_LO, but next higher group of 16 bits. */ + HOWTO (R_PPC64_GOT_TLSLD16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSLD16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TLSLD16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_GOT_TLSLD16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TLSLD16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates an entry in the GOT with value (sym+add)@dtprel, and computes + the offset to the entry relative to the TOC base (r2). */ + HOWTO (R_PPC64_GOT_DTPREL16_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_DTPREL16_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16_DS, but no overflow. */ + HOWTO (R_PPC64_GOT_DTPREL16_LO_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_DTPREL16_LO_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xfffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16_LO_DS, but next higher group of 16 bits. */ + HOWTO (R_PPC64_GOT_DTPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_DTPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_DTPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_GOT_DTPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_DTPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Allocates an entry in the GOT with value (sym+add)@tprel, and computes the + offset to the entry relative to the TOC base (r2). */ + HOWTO (R_PPC64_GOT_TPREL16_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TPREL16_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16_DS, but no overflow. */ + HOWTO (R_PPC64_GOT_TPREL16_LO_DS, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TPREL16_LO_DS", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16_LO_DS, but next higher group of 16 bits. */ + HOWTO (R_PPC64_GOT_TPREL16_HI, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TPREL16_HI", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Like GOT_TPREL16_HI, but adjust for low 16 bits. */ + HOWTO (R_PPC64_GOT_TPREL16_HA, + 16, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + ppc64_elf_unhandled_reloc, /* special_function */ + "R_PPC64_GOT_TPREL16_HA", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* GNU extension to record C++ vtable hierarchy. */ HOWTO (R_PPC64_GNU_VTINHERIT, /* type */ 0, /* rightshift */ @@ -1208,7 +1822,7 @@ ppc64_elf_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { - enum elf_ppc64_reloc_type ppc_reloc = R_PPC64_NONE; + enum elf_ppc64_reloc_type r = R_PPC64_NONE; if (!ppc64_elf_howto_table[R_PPC64_ADDR32]) /* Initialize howto table if needed. */ @@ -1219,131 +1833,211 @@ ppc64_elf_reloc_type_lookup (abfd, code) default: return (reloc_howto_type *) NULL; - case BFD_RELOC_NONE: ppc_reloc = R_PPC64_NONE; + case BFD_RELOC_NONE: r = R_PPC64_NONE; + break; + case BFD_RELOC_32: r = R_PPC64_ADDR32; + break; + case BFD_RELOC_PPC_BA26: r = R_PPC64_ADDR24; + break; + case BFD_RELOC_16: r = R_PPC64_ADDR16; + break; + case BFD_RELOC_LO16: r = R_PPC64_ADDR16_LO; + break; + case BFD_RELOC_HI16: r = R_PPC64_ADDR16_HI; + break; + case BFD_RELOC_HI16_S: r = R_PPC64_ADDR16_HA; + break; + case BFD_RELOC_PPC_BA16: r = R_PPC64_ADDR14; + break; + case BFD_RELOC_PPC_BA16_BRTAKEN: r = R_PPC64_ADDR14_BRTAKEN; + break; + case BFD_RELOC_PPC_BA16_BRNTAKEN: r = R_PPC64_ADDR14_BRNTAKEN; + break; + case BFD_RELOC_PPC_B26: r = R_PPC64_REL24; break; - case BFD_RELOC_32: ppc_reloc = R_PPC64_ADDR32; + case BFD_RELOC_PPC_B16: r = R_PPC64_REL14; break; - case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC64_ADDR24; + case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN; break; - case BFD_RELOC_16: ppc_reloc = R_PPC64_ADDR16; + case BFD_RELOC_PPC_B16_BRNTAKEN: r = R_PPC64_REL14_BRNTAKEN; break; - case BFD_RELOC_LO16: ppc_reloc = R_PPC64_ADDR16_LO; + case BFD_RELOC_16_GOTOFF: r = R_PPC64_GOT16; break; - case BFD_RELOC_HI16: ppc_reloc = R_PPC64_ADDR16_HI; + case BFD_RELOC_LO16_GOTOFF: r = R_PPC64_GOT16_LO; break; - case BFD_RELOC_HI16_S: ppc_reloc = R_PPC64_ADDR16_HA; + case BFD_RELOC_HI16_GOTOFF: r = R_PPC64_GOT16_HI; break; - case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC64_ADDR14; + case BFD_RELOC_HI16_S_GOTOFF: r = R_PPC64_GOT16_HA; break; - case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC64_ADDR14_BRTAKEN; + case BFD_RELOC_PPC_COPY: r = R_PPC64_COPY; break; - case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC64_ADDR14_BRNTAKEN; + case BFD_RELOC_PPC_GLOB_DAT: r = R_PPC64_GLOB_DAT; break; - case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC64_REL24; + case BFD_RELOC_32_PCREL: r = R_PPC64_REL32; break; - case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC64_REL14; + case BFD_RELOC_32_PLTOFF: r = R_PPC64_PLT32; break; - case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC64_REL14_BRTAKEN; + case BFD_RELOC_32_PLT_PCREL: r = R_PPC64_PLTREL32; break; - case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC64_REL14_BRNTAKEN; + case BFD_RELOC_LO16_PLTOFF: r = R_PPC64_PLT16_LO; break; - case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC64_GOT16; + case BFD_RELOC_HI16_PLTOFF: r = R_PPC64_PLT16_HI; break; - case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC64_GOT16_LO; + case BFD_RELOC_HI16_S_PLTOFF: r = R_PPC64_PLT16_HA; break; - case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC64_GOT16_HI; + case BFD_RELOC_16_BASEREL: r = R_PPC64_SECTOFF; break; - case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC64_GOT16_HA; + case BFD_RELOC_LO16_BASEREL: r = R_PPC64_SECTOFF_LO; break; - case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC64_COPY; + case BFD_RELOC_HI16_BASEREL: r = R_PPC64_SECTOFF_HI; break; - case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC64_GLOB_DAT; + case BFD_RELOC_HI16_S_BASEREL: r = R_PPC64_SECTOFF_HA; break; - case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC64_REL32; + case BFD_RELOC_CTOR: r = R_PPC64_ADDR64; break; - case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC64_PLT32; + case BFD_RELOC_64: r = R_PPC64_ADDR64; break; - case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL32; + case BFD_RELOC_PPC64_HIGHER: r = R_PPC64_ADDR16_HIGHER; break; - case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC64_PLT16_LO; + case BFD_RELOC_PPC64_HIGHER_S: r = R_PPC64_ADDR16_HIGHERA; break; - case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC64_PLT16_HI; + case BFD_RELOC_PPC64_HIGHEST: r = R_PPC64_ADDR16_HIGHEST; break; - case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC64_PLT16_HA; + case BFD_RELOC_PPC64_HIGHEST_S: r = R_PPC64_ADDR16_HIGHESTA; break; - case BFD_RELOC_16_BASEREL: ppc_reloc = R_PPC64_SECTOFF; + case BFD_RELOC_64_PCREL: r = R_PPC64_REL64; break; - case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_LO; + case BFD_RELOC_64_PLTOFF: r = R_PPC64_PLT64; break; - case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HI; + case BFD_RELOC_64_PLT_PCREL: r = R_PPC64_PLTREL64; break; - case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC64_SECTOFF_HA; + case BFD_RELOC_PPC_TOC16: r = R_PPC64_TOC16; break; - case BFD_RELOC_CTOR: ppc_reloc = R_PPC64_ADDR64; + case BFD_RELOC_PPC64_TOC16_LO: r = R_PPC64_TOC16_LO; break; - case BFD_RELOC_64: ppc_reloc = R_PPC64_ADDR64; + case BFD_RELOC_PPC64_TOC16_HI: r = R_PPC64_TOC16_HI; break; - case BFD_RELOC_PPC64_HIGHER: ppc_reloc = R_PPC64_ADDR16_HIGHER; + case BFD_RELOC_PPC64_TOC16_HA: r = R_PPC64_TOC16_HA; break; - case BFD_RELOC_PPC64_HIGHER_S: ppc_reloc = R_PPC64_ADDR16_HIGHERA; + case BFD_RELOC_PPC64_TOC: r = R_PPC64_TOC; break; - case BFD_RELOC_PPC64_HIGHEST: ppc_reloc = R_PPC64_ADDR16_HIGHEST; + case BFD_RELOC_PPC64_PLTGOT16: r = R_PPC64_PLTGOT16; break; - case BFD_RELOC_PPC64_HIGHEST_S: ppc_reloc = R_PPC64_ADDR16_HIGHESTA; + case BFD_RELOC_PPC64_PLTGOT16_LO: r = R_PPC64_PLTGOT16_LO; break; - case BFD_RELOC_64_PCREL: ppc_reloc = R_PPC64_REL64; + case BFD_RELOC_PPC64_PLTGOT16_HI: r = R_PPC64_PLTGOT16_HI; break; - case BFD_RELOC_64_PLTOFF: ppc_reloc = R_PPC64_PLT64; + case BFD_RELOC_PPC64_PLTGOT16_HA: r = R_PPC64_PLTGOT16_HA; break; - case BFD_RELOC_64_PLT_PCREL: ppc_reloc = R_PPC64_PLTREL64; + case BFD_RELOC_PPC64_ADDR16_DS: r = R_PPC64_ADDR16_DS; break; - case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC64_TOC16; + case BFD_RELOC_PPC64_ADDR16_LO_DS: r = R_PPC64_ADDR16_LO_DS; break; - case BFD_RELOC_PPC64_TOC16_LO: ppc_reloc = R_PPC64_TOC16_LO; + case BFD_RELOC_PPC64_GOT16_DS: r = R_PPC64_GOT16_DS; break; - case BFD_RELOC_PPC64_TOC16_HI: ppc_reloc = R_PPC64_TOC16_HI; + case BFD_RELOC_PPC64_GOT16_LO_DS: r = R_PPC64_GOT16_LO_DS; break; - case BFD_RELOC_PPC64_TOC16_HA: ppc_reloc = R_PPC64_TOC16_HA; + case BFD_RELOC_PPC64_PLT16_LO_DS: r = R_PPC64_PLT16_LO_DS; break; - case BFD_RELOC_PPC64_TOC: ppc_reloc = R_PPC64_TOC; + case BFD_RELOC_PPC64_SECTOFF_DS: r = R_PPC64_SECTOFF_DS; break; - case BFD_RELOC_PPC64_PLTGOT16: ppc_reloc = R_PPC64_PLTGOT16; + case BFD_RELOC_PPC64_SECTOFF_LO_DS: r = R_PPC64_SECTOFF_LO_DS; break; - case BFD_RELOC_PPC64_PLTGOT16_LO: ppc_reloc = R_PPC64_PLTGOT16_LO; + case BFD_RELOC_PPC64_TOC16_DS: r = R_PPC64_TOC16_DS; break; - case BFD_RELOC_PPC64_PLTGOT16_HI: ppc_reloc = R_PPC64_PLTGOT16_HI; + case BFD_RELOC_PPC64_TOC16_LO_DS: r = R_PPC64_TOC16_LO_DS; break; - case BFD_RELOC_PPC64_PLTGOT16_HA: ppc_reloc = R_PPC64_PLTGOT16_HA; + case BFD_RELOC_PPC64_PLTGOT16_DS: r = R_PPC64_PLTGOT16_DS; break; - case BFD_RELOC_PPC64_ADDR16_DS: ppc_reloc = R_PPC64_ADDR16_DS; + case BFD_RELOC_PPC64_PLTGOT16_LO_DS: r = R_PPC64_PLTGOT16_LO_DS; break; - case BFD_RELOC_PPC64_ADDR16_LO_DS: ppc_reloc = R_PPC64_ADDR16_LO_DS; + case BFD_RELOC_PPC_TLS: r = R_PPC64_TLS; break; - case BFD_RELOC_PPC64_GOT16_DS: ppc_reloc = R_PPC64_GOT16_DS; + case BFD_RELOC_PPC_DTPMOD: r = R_PPC64_DTPMOD64; break; - case BFD_RELOC_PPC64_GOT16_LO_DS: ppc_reloc = R_PPC64_GOT16_LO_DS; + case BFD_RELOC_PPC_TPREL16: r = R_PPC64_TPREL16; break; - case BFD_RELOC_PPC64_PLT16_LO_DS: ppc_reloc = R_PPC64_PLT16_LO_DS; + case BFD_RELOC_PPC_TPREL16_LO: r = R_PPC64_TPREL16_LO; break; - case BFD_RELOC_PPC64_SECTOFF_DS: ppc_reloc = R_PPC64_SECTOFF_DS; + case BFD_RELOC_PPC_TPREL16_HI: r = R_PPC64_TPREL16_HI; break; - case BFD_RELOC_PPC64_SECTOFF_LO_DS: ppc_reloc = R_PPC64_SECTOFF_LO_DS; + case BFD_RELOC_PPC_TPREL16_HA: r = R_PPC64_TPREL16_HA; break; - case BFD_RELOC_PPC64_TOC16_DS: ppc_reloc = R_PPC64_TOC16_DS; + case BFD_RELOC_PPC_TPREL: r = R_PPC64_TPREL64; break; - case BFD_RELOC_PPC64_TOC16_LO_DS: ppc_reloc = R_PPC64_TOC16_LO_DS; + case BFD_RELOC_PPC_DTPREL16: r = R_PPC64_DTPREL16; break; - case BFD_RELOC_PPC64_PLTGOT16_DS: ppc_reloc = R_PPC64_PLTGOT16_DS; + case BFD_RELOC_PPC_DTPREL16_LO: r = R_PPC64_DTPREL16_LO; break; - case BFD_RELOC_PPC64_PLTGOT16_LO_DS: ppc_reloc = R_PPC64_PLTGOT16_LO_DS; + case BFD_RELOC_PPC_DTPREL16_HI: r = R_PPC64_DTPREL16_HI; break; - case BFD_RELOC_VTABLE_INHERIT: ppc_reloc = R_PPC64_GNU_VTINHERIT; + case BFD_RELOC_PPC_DTPREL16_HA: r = R_PPC64_DTPREL16_HA; break; - case BFD_RELOC_VTABLE_ENTRY: ppc_reloc = R_PPC64_GNU_VTENTRY; + case BFD_RELOC_PPC_DTPREL: r = R_PPC64_DTPREL64; + break; + case BFD_RELOC_PPC_GOT_TLSGD16: r = R_PPC64_GOT_TLSGD16; + break; + case BFD_RELOC_PPC_GOT_TLSGD16_LO: r = R_PPC64_GOT_TLSGD16_LO; + break; + case BFD_RELOC_PPC_GOT_TLSGD16_HI: r = R_PPC64_GOT_TLSGD16_HI; + break; + case BFD_RELOC_PPC_GOT_TLSGD16_HA: r = R_PPC64_GOT_TLSGD16_HA; + break; + case BFD_RELOC_PPC_GOT_TLSLD16: r = R_PPC64_GOT_TLSLD16; + break; + case BFD_RELOC_PPC_GOT_TLSLD16_LO: r = R_PPC64_GOT_TLSLD16_LO; + break; + case BFD_RELOC_PPC_GOT_TLSLD16_HI: r = R_PPC64_GOT_TLSLD16_HI; + break; + case BFD_RELOC_PPC_GOT_TLSLD16_HA: r = R_PPC64_GOT_TLSLD16_HA; + break; + case BFD_RELOC_PPC_GOT_TPREL16: r = R_PPC64_GOT_TPREL16_DS; + break; + case BFD_RELOC_PPC_GOT_TPREL16_LO: r = R_PPC64_GOT_TPREL16_LO_DS; + break; + case BFD_RELOC_PPC_GOT_TPREL16_HI: r = R_PPC64_GOT_TPREL16_HI; + break; + case BFD_RELOC_PPC_GOT_TPREL16_HA: r = R_PPC64_GOT_TPREL16_HA; + break; + case BFD_RELOC_PPC_GOT_DTPREL16: r = R_PPC64_GOT_DTPREL16_DS; + break; + case BFD_RELOC_PPC_GOT_DTPREL16_LO: r = R_PPC64_GOT_DTPREL16_LO_DS; + break; + case BFD_RELOC_PPC_GOT_DTPREL16_HI: r = R_PPC64_GOT_DTPREL16_HI; + break; + case BFD_RELOC_PPC_GOT_DTPREL16_HA: r = R_PPC64_GOT_DTPREL16_HA; + break; + case BFD_RELOC_PPC64_TPREL16_DS: r = R_PPC64_TPREL16_DS; + break; + case BFD_RELOC_PPC64_TPREL16_LO_DS: r = R_PPC64_TPREL16_LO_DS; + break; + case BFD_RELOC_PPC64_TPREL16_HIGHER: r = R_PPC64_TPREL16_HIGHER; + break; + case BFD_RELOC_PPC64_TPREL16_HIGHERA: r = R_PPC64_TPREL16_HIGHERA; + break; + case BFD_RELOC_PPC64_TPREL16_HIGHEST: r = R_PPC64_TPREL16_HIGHEST; + break; + case BFD_RELOC_PPC64_TPREL16_HIGHESTA: r = R_PPC64_TPREL16_HIGHESTA; + break; + case BFD_RELOC_PPC64_DTPREL16_DS: r = R_PPC64_DTPREL16_DS; + break; + case BFD_RELOC_PPC64_DTPREL16_LO_DS: r = R_PPC64_DTPREL16_LO_DS; + break; + case BFD_RELOC_PPC64_DTPREL16_HIGHER: r = R_PPC64_DTPREL16_HIGHER; + break; + case BFD_RELOC_PPC64_DTPREL16_HIGHERA: r = R_PPC64_DTPREL16_HIGHERA; + break; + case BFD_RELOC_PPC64_DTPREL16_HIGHEST: r = R_PPC64_DTPREL16_HIGHEST; + break; + case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA; + break; + case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT; + break; + case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY; break; } - return ppc64_elf_howto_table[(int) ppc_reloc]; + return ppc64_elf_howto_table[(int) r]; }; /* Set the howto pointer for a PowerPC ELF reloc. */ @@ -1681,15 +2375,23 @@ ppc64_elf_merge_private_bfd_data (ibfd, obfd) struct _ppc64_elf_section_data { struct bfd_elf_section_data elf; + + /* An array with one entry for each opd function descriptor. */ union { + /* Points to the function code section for local opd entries. */ asection **func_sec; + /* After editing .opd, adjust references to opd local syms. */ long *adjust; } opd; + + /* An array for toc sections, indexed by offset/8. + Specifies the relocation symbol index used at a given toc offset. */ + unsigned *t_symndx; }; #define ppc64_elf_section_data(sec) \ - ((struct _ppc64_elf_section_data *) (sec)->used_by_bfd) + ((struct _ppc64_elf_section_data *) elf_section_data (sec)) static bfd_boolean ppc64_elf_new_section_hook (abfd, sec) @@ -1747,7 +2449,7 @@ ppc64_elf_new_section_hook (abfd, sec) . . .foo_stub: . addis 12,2,Lfoo@toc@ha # in practice, the call stub - . addi 12,12,Lfoo@toc@l # is slightly optimised, but + . addi 12,12,Lfoo@toc@l # is slightly optimized, but . std 2,40(1) # this is the general idea . ld 11,0(12) . ld 2,8(12) @@ -1795,14 +2497,56 @@ struct ppc_dyn_relocs bfd_size_type pc_count; }; +/* Track GOT entries needed for a given symbol. We might need more + than one got entry per symbol. */ +struct got_entry +{ + struct got_entry *next; + + /* The symbol addend that we'll be placing in the GOT. */ + bfd_vma addend; + + /* Reference count until size_dynamic_sections, GOT offset thereafter. */ + union + { + bfd_signed_vma refcount; + bfd_vma offset; + } got; + + /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD, + TLS_TPREL or TLS_DTPREL for tls entries. */ + char tls_type; +}; + +/* The same for PLT. */ +struct plt_entry +{ + struct plt_entry *next; + + bfd_vma addend; + + union + { + bfd_signed_vma refcount; + bfd_vma offset; + } plt; +}; + /* Of those relocs that might be copied as dynamic relocs, this macro - selects between relative and absolute types. */ + selects those that must be copied when linking a shared library, + even when the symbol is local. */ -#define IS_ABSOLUTE_RELOC(RTYPE) \ +#define MUST_BE_DYN_RELOC(RTYPE) \ ((RTYPE) != R_PPC64_REL32 \ && (RTYPE) != R_PPC64_REL64 \ && (RTYPE) != R_PPC64_REL30) +/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid + copying dynamic variables from a shared lib into an app's dynbss + section, and instead use a dynamic relocation to point into the + shared lib. */ +#define ELIMINATE_COPY_RELOCS 1 + /* Section name for stubs is the associated section name plus this string. */ #define STUB_SUFFIX ".stub" @@ -1860,6 +2604,9 @@ struct ppc_stub_hash_entry { /* The symbol table entry, if any, that this was derived from. */ struct ppc_link_hash_entry *h; + /* And the reloc addend that this was derived from. */ + bfd_vma addend; + /* 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; @@ -1895,6 +2642,23 @@ struct ppc_link_hash_entry unsigned int is_func:1; unsigned int is_func_descriptor:1; unsigned int is_entry:1; + + /* Contexts in which symbol is used in the GOT (or TOC). + TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the + corresponding relocs are encountered during check_relocs. + tls_optimize clears TLS_GD .. TLS_TPREL when optimizing to + indicate the corresponding GOT entry type is not needed. + tls_optimize may also set TLS_TPRELGD when a GD reloc turns into + a TPREL one. We use a separate flag rather than setting TPREL + just for convenience in distinguishing the two cases. */ +#define TLS_GD 1 /* GD reloc. */ +#define TLS_LD 2 /* LD reloc. */ +#define TLS_TPREL 4 /* TPREL reloc, => IE. */ +#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */ +#define TLS_TLS 16 /* Any TLS reloc. */ +#define TLS_EXPLICIT 32 /* Marks TOC section TLS relocs. */ +#define TLS_TPRELGD 64 /* TPREL reloc resulting from GD->IE. */ + char tls_mask; }; /* ppc64 ELF linker hash table. */ @@ -1941,6 +2705,18 @@ struct ppc_link_hash_table asection *sbrlt; asection *srelbrlt; + /* Short-cut to first output tls section. */ + asection *tls_sec; + + /* Shortcut to .__tls_get_addr. */ + struct elf_link_hash_entry *tls_get_addr; + + /* TLS local dynamic got entry handling. */ + union { + bfd_signed_vma refcount; + bfd_vma offset; + } tlsld_got; + /* Set on error. */ unsigned int stub_error; @@ -1985,6 +2761,10 @@ static bfd_boolean ppc64_elf_create_dynamic_sections static void ppc64_elf_copy_indirect_symbol PARAMS ((struct elf_backend_data *, struct elf_link_hash_entry *, struct elf_link_hash_entry *)); +static bfd_boolean update_local_sym_info + PARAMS ((bfd *, Elf_Internal_Shdr *, unsigned long, bfd_vma, int)); +static bfd_boolean update_plt_info + PARAMS ((bfd *, struct ppc_link_hash_entry *, bfd_vma)); static bfd_boolean ppc64_elf_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *)); @@ -2002,6 +2782,11 @@ static bfd_boolean ppc64_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); static void ppc64_elf_hide_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean)); +static bfd_boolean get_sym_h + PARAMS ((struct elf_link_hash_entry **, Elf_Internal_Sym **, asection **, + char **, Elf_Internal_Sym **, unsigned long, bfd *)); +static int get_tls_mask + PARAMS ((char **, Elf_Internal_Sym **, const Elf_Internal_Rela *, bfd *)); static bfd_boolean allocate_dynrelocs PARAMS ((struct elf_link_hash_entry *, PTR)); static bfd_boolean readonly_dynrelocs @@ -2010,7 +2795,7 @@ static enum elf_reloc_type_class ppc64_elf_reloc_type_class PARAMS ((const Elf_Internal_Rela *)); static bfd_boolean ppc64_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); -static INLINE enum ppc_stub_type ppc_type_of_stub +static enum ppc_stub_type ppc_type_of_stub PARAMS ((asection *, const Elf_Internal_Rela *, struct ppc_link_hash_entry **, bfd_vma)); static bfd_byte *build_plt_stub @@ -2142,6 +2927,7 @@ link_hash_newfunc (entry, table, string) eh->is_func = 0; eh->is_func_descriptor = 0; eh->is_entry = 0; + eh->tls_mask = 0; } return entry; @@ -2188,11 +2974,22 @@ ppc64_elf_link_hash_table_create (abfd) htab->sfpr = NULL; htab->sbrlt = NULL; htab->srelbrlt = NULL; + htab->tls_sec = NULL; + htab->tls_get_addr = NULL; + htab->tlsld_got.refcount = 0; htab->stub_error = 0; htab->has_14bit_branch = 0; htab->have_undefweak = 0; htab->stub_iteration = 0; htab->sym_sec.abfd = NULL; + /* Initializing two fields of the union is just cosmetic. We really + only care about glist, but when compiled on a 32-bit host the + bfd_vma fields are larger. Setting the bfd_vma to zero makes + debugger inspection of these fields look nicer. */ + htab->elf.init_refcount.refcount = 0; + htab->elf.init_refcount.glist = NULL; + htab->elf.init_offset.offset = 0; + htab->elf.init_offset.glist = NULL; return &htab->elf.root; } @@ -2471,7 +3268,7 @@ ppc64_elf_create_dynamic_sections (dynobj, info) static void ppc64_elf_copy_indirect_symbol (bed, dir, ind) - struct elf_backend_data *bed; + struct elf_backend_data *bed ATTRIBUTE_UNUSED; struct elf_link_hash_entry *dir, *ind; { struct ppc_link_hash_entry *edir, *eind; @@ -2479,6 +3276,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind) edir = (struct ppc_link_hash_entry *) dir; eind = (struct ppc_link_hash_entry *) ind; + /* Copy over any dynamic relocs we may have on the indirect sym. */ if (eind->dyn_relocs != NULL) { if (edir->dyn_relocs != NULL) @@ -2486,7 +3284,7 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind) struct ppc_dyn_relocs **pp; struct ppc_dyn_relocs *p; - if (ind->root.type == bfd_link_hash_indirect) + if (eind->elf.root.type == bfd_link_hash_indirect) abort (); /* Add reloc counts against the weak sym to the strong sym @@ -2516,8 +3314,89 @@ ppc64_elf_copy_indirect_symbol (bed, dir, ind) edir->is_func |= eind->is_func; edir->is_func_descriptor |= eind->is_func_descriptor; edir->is_entry |= eind->is_entry; + edir->tls_mask |= eind->tls_mask; + + /* Copy down any references that we may have already seen to the + symbol which just became indirect. */ + edir->elf.elf_link_hash_flags |= + (eind->elf.elf_link_hash_flags + & (ELF_LINK_HASH_REF_DYNAMIC + | ELF_LINK_HASH_REF_REGULAR + | ELF_LINK_HASH_REF_REGULAR_NONWEAK + | ELF_LINK_NON_GOT_REF)); + + /* If we were called to copy over info for a weak sym, that's all. */ + if (eind->elf.root.type != bfd_link_hash_indirect) + return; + + /* Copy over got entries. */ + if (eind->elf.got.glist != NULL) + { + if (edir->elf.got.glist != NULL) + { + struct got_entry **entp; + struct got_entry *ent; + + for (entp = &eind->elf.got.glist; (ent = *entp) != NULL; ) + { + struct got_entry *dent; + + for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next) + if (dent->addend == ent->addend + && dent->tls_type == ent->tls_type) + { + dent->got.refcount += ent->got.refcount; + *entp = ent->next; + break; + } + if (dent == NULL) + entp = &ent->next; + } + *entp = edir->elf.got.glist; + } - _bfd_elf_link_hash_copy_indirect (bed, dir, ind); + edir->elf.got.glist = eind->elf.got.glist; + eind->elf.got.glist = NULL; + } + + /* And plt entries. */ + if (eind->elf.plt.plist != NULL) + { + if (edir->elf.plt.plist != NULL) + { + struct plt_entry **entp; + struct plt_entry *ent; + + for (entp = &eind->elf.plt.plist; (ent = *entp) != NULL; ) + { + struct plt_entry *dent; + + for (dent = edir->elf.plt.plist; dent != NULL; dent = dent->next) + if (dent->addend == ent->addend) + { + dent->plt.refcount += ent->plt.refcount; + *entp = ent->next; + break; + } + if (dent == NULL) + entp = &ent->next; + } + *entp = edir->elf.plt.plist; + } + + edir->elf.plt.plist = eind->elf.plt.plist; + eind->elf.plt.plist = NULL; + } + + if (edir->elf.dynindx == -1) + { + edir->elf.dynindx = eind->elf.dynindx; + edir->elf.dynstr_index = eind->elf.dynstr_index; + eind->elf.dynindx = -1; + eind->elf.dynstr_index = 0; + } + else + BFD_ASSERT (eind->elf.dynindx == -1); } /* Set a flag, used by ppc64_elf_gc_mark_hook, on the entry symbol and @@ -2542,6 +3421,83 @@ ppc64_elf_mark_entry_syms (info) return TRUE; } +static bfd_boolean +update_local_sym_info (abfd, symtab_hdr, r_symndx, r_addend, tls_type) + bfd *abfd; + Elf_Internal_Shdr *symtab_hdr; + unsigned long r_symndx; + bfd_vma r_addend; + int tls_type; +{ + struct got_entry **local_got_ents = elf_local_got_ents (abfd); + char *local_got_tls_masks; + + if (local_got_ents == NULL) + { + bfd_size_type size = symtab_hdr->sh_info; + + size *= sizeof (*local_got_ents) + sizeof (*local_got_tls_masks); + local_got_ents = (struct got_entry **) bfd_zalloc (abfd, size); + if (local_got_ents == NULL) + return FALSE; + elf_local_got_ents (abfd) = local_got_ents; + } + + if ((tls_type & TLS_EXPLICIT) == 0) + { + struct got_entry *ent; + + for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next) + if (ent->addend == r_addend && ent->tls_type == tls_type) + break; + if (ent == NULL) + { + bfd_size_type amt = sizeof (*ent); + ent = (struct got_entry *) bfd_alloc (abfd, amt); + if (ent == NULL) + return FALSE; + ent->next = local_got_ents[r_symndx]; + ent->addend = r_addend; + ent->tls_type = tls_type; + ent->got.refcount = 0; + local_got_ents[r_symndx] = ent; + } + ent->got.refcount += 1; + } + + local_got_tls_masks = (char *) (local_got_ents + symtab_hdr->sh_info); + local_got_tls_masks[r_symndx] |= tls_type; + return TRUE; +} + +static bfd_boolean +update_plt_info (abfd, eh, addend) + bfd *abfd; + struct ppc_link_hash_entry *eh; + bfd_vma addend; +{ + struct plt_entry *ent; + + for (ent = eh->elf.plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == addend) + break; + if (ent == NULL) + { + bfd_size_type amt = sizeof (*ent); + ent = (struct plt_entry *) bfd_alloc (abfd, amt); + if (ent == NULL) + return FALSE; + ent->next = eh->elf.plt.plist; + ent->addend = addend; + ent->plt.refcount = 0; + eh->elf.plt.plist = ent; + } + ent->plt.refcount += 1; + eh->elf.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; + eh->is_func = 1; + return TRUE; +} + /* Look through the relocs for a section during the first phase, and calculate needed space in the global offset table, procedure linkage table, and dynamic reloc sections. */ @@ -2610,6 +3566,7 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) unsigned long r_symndx; struct elf_link_hash_entry *h; enum elf_ppc64_reloc_type r_type; + int tls_type = 0; r_symndx = ELF64_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) @@ -2620,14 +3577,45 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info); switch (r_type) { - /* GOT16 relocations */ + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + htab->tlsld_got.refcount += 1; + tls_type = TLS_TLS | TLS_LD; + goto dogottls; + + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + tls_type = TLS_TLS | TLS_GD; + goto dogottls; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_TPREL16_HI: + case R_PPC64_GOT_TPREL16_HA: + if (info->shared) + info->flags |= DF_STATIC_TLS; + tls_type = TLS_TLS | TLS_TPREL; + goto dogottls; + + case R_PPC64_GOT_DTPREL16_DS: + case R_PPC64_GOT_DTPREL16_LO_DS: + case R_PPC64_GOT_DTPREL16_HI: + case R_PPC64_GOT_DTPREL16_HA: + tls_type = TLS_TLS | TLS_DTPREL; + dogottls: + sec->has_tls_reloc = 1; + /* Fall thru */ + case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_LO_DS: - /* This symbol requires a global offset table entry. */ if (htab->sgot == NULL && !create_got_section (htab->elf.dynobj, info)) @@ -2635,28 +3623,34 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) if (h != NULL) { - h->got.refcount += 1; - } - else - { - bfd_signed_vma *local_got_refcounts; + struct ppc_link_hash_entry *eh; + struct got_entry *ent; - /* This is a global offset table entry for a local symbol. */ - local_got_refcounts = elf_local_got_refcounts (abfd); - if (local_got_refcounts == NULL) + eh = (struct ppc_link_hash_entry *) h; + for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->tls_type == tls_type) + break; + if (ent == NULL) { - bfd_size_type size; - - size = symtab_hdr->sh_info; - size *= sizeof (bfd_signed_vma); - local_got_refcounts = ((bfd_signed_vma *) - bfd_zalloc (abfd, size)); - if (local_got_refcounts == NULL) + bfd_size_type amt = sizeof (*ent); + ent = (struct got_entry *) bfd_alloc (abfd, amt); + if (ent == NULL) return FALSE; - elf_local_got_refcounts (abfd) = local_got_refcounts; + ent->next = eh->elf.got.glist; + ent->addend = rel->r_addend; + ent->tls_type = tls_type; + ent->got.refcount = 0; + eh->elf.got.glist = ent; } - local_got_refcounts[r_symndx] += 1; + ent->got.refcount += 1; + eh->tls_mask |= tls_type; } + else + /* This is a global offset table entry for a local symbol. */ + if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, + rel->r_addend, tls_type)) + return FALSE; break; case R_PPC64_PLT16_HA: @@ -2676,10 +3670,10 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) bfd_set_error (bfd_error_bad_value); return FALSE; } - - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - h->plt.refcount += 1; - ((struct ppc_link_hash_entry *) h)->is_func = 1; + else + if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, + rel->r_addend)) + return FALSE; break; /* The following relocations don't need to propagate the @@ -2697,6 +3691,16 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) case R_PPC64_TOC16_HA: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_LO_DS: + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_HI: + case R_PPC64_DTPREL16_HA: + case R_PPC64_DTPREL16_DS: + case R_PPC64_DTPREL16_LO_DS: + case R_PPC64_DTPREL16_HIGHER: + case R_PPC64_DTPREL16_HIGHERA: + case R_PPC64_DTPREL16_HIGHEST: + case R_PPC64_DTPREL16_HIGHESTA: break; /* This relocation describes the C++ object vtable hierarchy. @@ -2726,9 +3730,93 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) { /* We may need a .plt entry if the function this reloc refers to is in a shared lib. */ - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - h->plt.refcount += 1; - ((struct ppc_link_hash_entry *) h)->is_func = 1; + if (!update_plt_info (abfd, (struct ppc_link_hash_entry *) h, + rel->r_addend)) + return FALSE; + if (h == htab->tls_get_addr) + sec->has_tls_reloc = 1; + else if ((strncmp (h->root.root.string, ".__tls_get_addr", 15) + == 0) + && (h->root.root.string[15] == 0 + || h->root.root.string[15] == '@')) + { + htab->tls_get_addr = h; + sec->has_tls_reloc = 1; + } + } + break; + + case R_PPC64_TPREL64: + tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL; + if (info->shared) + info->flags |= DF_STATIC_TLS; + goto dotlstoc; + + case R_PPC64_DTPMOD64: + if (rel + 1 < rel_end + && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) + && rel[1].r_offset == rel->r_offset + 8) + tls_type = TLS_EXPLICIT | TLS_TLS | TLS_GD; + else + tls_type = TLS_EXPLICIT | TLS_TLS | TLS_LD; + goto dotlstoc; + + case R_PPC64_DTPREL64: + tls_type = TLS_EXPLICIT | TLS_TLS | TLS_DTPREL; + if (rel != relocs + && rel[-1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPMOD64) + && rel[-1].r_offset == rel->r_offset - 8) + /* This is the second reloc of a dtpmod, dtprel pair. + Don't mark with TLS_DTPREL. */ + goto dodyn; + + dotlstoc: + sec->has_tls_reloc = 1; + if (h != NULL) + { + struct ppc_link_hash_entry *eh; + eh = (struct ppc_link_hash_entry *) h; + eh->tls_mask |= tls_type; + } + else + if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, + rel->r_addend, tls_type)) + return FALSE; + + if (ppc64_elf_section_data (sec)->t_symndx == NULL) + { + /* One extra to simplify get_tls_mask. */ + bfd_size_type amt = sec->_raw_size * sizeof (unsigned) / 8 + 1; + ppc64_elf_section_data (sec)->t_symndx + = (unsigned *) bfd_zalloc (abfd, amt); + if (ppc64_elf_section_data (sec)->t_symndx == NULL) + return FALSE; + } + BFD_ASSERT (rel->r_offset % 8 == 0); + ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8] = r_symndx; + + /* Mark the second slot of a GD or LD entry. + -1 to indicate GD and -2 to indicate LD. */ + if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_GD)) + ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -1; + else if (tls_type == (TLS_EXPLICIT | TLS_TLS | TLS_LD)) + ppc64_elf_section_data (sec)->t_symndx[rel->r_offset / 8 + 1] = -2; + goto dodyn; + + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + case R_PPC64_TPREL16_DS: + case R_PPC64_TPREL16_LO_DS: + case R_PPC64_TPREL16_HIGHER: + case R_PPC64_TPREL16_HIGHERA: + case R_PPC64_TPREL16_HIGHEST: + case R_PPC64_TPREL16_HIGHESTA: + if (info->shared) + { + info->flags |= DF_STATIC_TLS; + goto dodyn; } break; @@ -2793,6 +3881,10 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) if (NO_OPD_RELOCS && opd_sym_map != NULL) break; + /* Don't propagate relocs that the dynamic linker won't relocate. */ + if ((sec->flags & SEC_ALLOC) == 0) + break; + /* If we are creating a shared library, and this is a reloc against a global symbol, or a non PC relative reloc against a local symbol, then we need to copy the reloc @@ -2805,7 +3897,7 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) later (it is never cleared). In case of a weak definition, DEF_REGULAR may be cleared later by a strong definition in a shared library. We account for that possibility below by - storing information in the relocs_copied field of the hash + storing information in the dyn_relocs field of the hash table entry. A similar situation occurs when creating shared libraries and symbol visibility changes render the symbol local. @@ -2814,16 +3906,16 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) may need to keep relocations for symbols satisfied by a dynamic library if we manage to avoid copy relocs for the symbol. */ + dodyn: if ((info->shared - && (sec->flags & SEC_ALLOC) != 0 - && (IS_ABSOLUTE_RELOC (r_type) + && (MUST_BE_DYN_RELOC (r_type) || (h != NULL && (! info->symbolic || h->root.type == bfd_link_hash_defweak || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) - || (!info->shared - && (sec->flags & SEC_ALLOC) != 0 + || (ELIMINATE_COPY_RELOCS + && !info->shared && h != NULL && (h->root.type == bfd_link_hash_defweak || (h->elf_link_hash_flags @@ -2914,7 +4006,7 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs) } p->count += 1; - if (!IS_ABSOLUTE_RELOC (r_type)) + if (!MUST_BE_DYN_RELOC (r_type)) p->pc_count += 1; } break; @@ -3004,49 +4096,106 @@ ppc64_elf_gc_mark_hook (sec, info, rel, h, sym) static bfd_boolean ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd; - struct bfd_link_info *info ATTRIBUTE_UNUSED; + struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs; { + struct ppc_link_hash_table *htab; Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; - bfd_signed_vma *local_got_refcounts; + struct got_entry **local_got_ents; const Elf_Internal_Rela *rel, *relend; elf_section_data (sec)->local_dynrel = NULL; + htab = ppc_hash_table (info); symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); - local_got_refcounts = elf_local_got_refcounts (abfd); + local_got_ents = elf_local_got_ents (abfd); relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { unsigned long r_symndx; enum elf_ppc64_reloc_type r_type; - struct elf_link_hash_entry *h; + struct elf_link_hash_entry *h = NULL; + char tls_type = 0; r_symndx = ELF64_R_SYM (rel->r_info); r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct ppc_link_hash_entry *eh; + struct ppc_dyn_relocs **pp; + struct ppc_dyn_relocs *p; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct ppc_link_hash_entry *) h; + + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } + switch (r_type) { + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + htab->tlsld_got.refcount -= 1; + tls_type = TLS_TLS | TLS_LD; + goto dogot; + + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + tls_type = TLS_TLS | TLS_GD; + goto dogot; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_TPREL16_HI: + case R_PPC64_GOT_TPREL16_HA: + tls_type = TLS_TLS | TLS_TPREL; + goto dogot; + + case R_PPC64_GOT_DTPREL16_DS: + case R_PPC64_GOT_DTPREL16_LO_DS: + case R_PPC64_GOT_DTPREL16_HI: + case R_PPC64_GOT_DTPREL16_HA: + tls_type = TLS_TLS | TLS_DTPREL; + goto dogot; + case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_LO_DS: - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount--; - } - else - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx]--; - } + dogot: + { + struct got_entry *ent; + + if (h != NULL) + ent = h->got.glist; + else + ent = local_got_ents[r_symndx]; + + for (; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->tls_type == tls_type) + break; + if (ent == NULL) + abort (); + if (ent->got.refcount > 0) + ent->got.refcount -= 1; + } break; case R_PPC64_PLT16_HA: @@ -3054,87 +4203,21 @@ ppc64_elf_gc_sweep_hook (abfd, info, sec, relocs) case R_PPC64_PLT16_LO: case R_PPC64_PLT32: case R_PPC64_PLT64: - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount--; - } - break; - case R_PPC64_REL14: case R_PPC64_REL14_BRNTAKEN: case R_PPC64_REL14_BRTAKEN: case R_PPC64_REL24: - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount--; - } - break; - - case R_PPC64_REL30: - case R_PPC64_REL32: - case R_PPC64_REL64: - if (r_symndx >= symtab_hdr->sh_info) - { - struct ppc_link_hash_entry *eh; - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; - - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - eh = (struct ppc_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; - - case R_PPC64_ADDR14: - case R_PPC64_ADDR14_BRNTAKEN: - case R_PPC64_ADDR14_BRTAKEN: - case R_PPC64_ADDR16: - case R_PPC64_ADDR16_DS: - case R_PPC64_ADDR16_HA: - case R_PPC64_ADDR16_HI: - case R_PPC64_ADDR16_HIGHER: - case R_PPC64_ADDR16_HIGHERA: - case R_PPC64_ADDR16_HIGHEST: - case R_PPC64_ADDR16_HIGHESTA: - case R_PPC64_ADDR16_LO: - case R_PPC64_ADDR16_LO_DS: - case R_PPC64_ADDR24: - case R_PPC64_ADDR32: - case R_PPC64_ADDR64: - case R_PPC64_UADDR16: - case R_PPC64_UADDR32: - case R_PPC64_UADDR64: - case R_PPC64_TOC: - if (r_symndx >= symtab_hdr->sh_info) + if (h != NULL) { - struct ppc_link_hash_entry *eh; - struct ppc_dyn_relocs **pp; - struct ppc_dyn_relocs *p; + struct plt_entry *ent; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - eh = (struct ppc_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } + for (ent = h->plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend) + break; + if (ent == NULL) + abort (); + if (ent->plt.refcount > 0) + ent->plt.refcount -= 1; } break; @@ -3155,6 +4238,7 @@ func_desc_adjust (h, inf) { struct bfd_link_info *info; struct ppc_link_hash_table *htab; + struct plt_entry *ent; if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -3174,7 +4258,10 @@ func_desc_adjust (h, inf) && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR)) htab->have_undefweak = TRUE; - if (h->plt.refcount > 0 + for (ent = h->plt.plist; ent != NULL; ent = ent->next) + if (ent->plt.refcount > 0) + break; + if (ent != NULL && h->root.root.string[0] == '.' && h->root.root.string[1] != '\0') { @@ -3233,7 +4320,7 @@ func_desc_adjust (h, inf) | ELF_LINK_NON_GOT_REF)); if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) { - fdh->plt.refcount = h->plt.refcount; + fdh->plt.plist = h->plt.plist; fdh->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; } ((struct ppc_link_hash_entry *) fdh)->is_func_descriptor = 1; @@ -3392,8 +4479,6 @@ ppc64_elf_adjust_dynamic_symbol (info, h) struct elf_link_hash_entry *h; { struct ppc_link_hash_table *htab; - struct ppc_link_hash_entry * eh; - struct ppc_dyn_relocs *p; asection *s; unsigned int power_of_two; @@ -3405,20 +4490,24 @@ ppc64_elf_adjust_dynamic_symbol (info, h) { /* Clear procedure linkage table information for any symbol that won't need a .plt entry. */ + struct plt_entry *ent; + for (ent = h->plt.plist; ent != NULL; ent = ent->next) + if (ent->plt.refcount > 0) + break; if (!((struct ppc_link_hash_entry *) h)->is_func_descriptor - || h->plt.refcount <= 0 + || ent == NULL || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0 || (! info->shared && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)) { - h->plt.offset = (bfd_vma) -1; + h->plt.plist = NULL; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } return TRUE; } else - h->plt.offset = (bfd_vma) -1; + h->plt.plist = NULL; /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the @@ -3447,20 +4536,26 @@ ppc64_elf_adjust_dynamic_symbol (info, h) if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0) return TRUE; - eh = (struct ppc_link_hash_entry *) h; - for (p = eh->dyn_relocs; p != NULL; p = p->next) + if (ELIMINATE_COPY_RELOCS) { - s = p->sec->output_section; - if (s != NULL && (s->flags & SEC_READONLY) != 0) - break; - } + struct ppc_link_hash_entry * eh; + struct ppc_dyn_relocs *p; - /* If we didn't find any dynamic relocs in read-only sections, then - we'll be keeping the dynamic relocs and avoiding the copy reloc. */ - if (p == NULL) - { - h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; - return TRUE; + eh = (struct ppc_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + s = p->sec->output_section; + if (s != NULL && (s->flags & SEC_READONLY) != 0) + break; + } + + /* If we didn't find any dynamic relocs in read-only sections, then + we'll be keeping the dynamic relocs and avoiding the copy reloc. */ + if (p == NULL) + { + h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF; + return TRUE; + } } /* We must allocate the symbol in our .dynbss section, which will @@ -3567,17 +4662,166 @@ ppc64_elf_hide_symbol (info, h, force_local) } } +static bfd_boolean +get_sym_h (hp, symp, symsecp, tls_maskp, locsymsp, r_symndx, ibfd) + struct elf_link_hash_entry **hp; + Elf_Internal_Sym **symp; + asection **symsecp; + char **tls_maskp; + Elf_Internal_Sym **locsymsp; + unsigned long r_symndx; + bfd *ibfd; +{ + Elf_Internal_Shdr *symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; + + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (ibfd); + struct elf_link_hash_entry *h; + + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + if (hp != NULL) + *hp = h; + + if (symp != NULL) + *symp = NULL; + + if (symsecp != NULL) + { + asection *symsec = NULL; + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + symsec = h->root.u.def.section; + *symsecp = symsec; + } + + if (tls_maskp != NULL) + { + struct ppc_link_hash_entry *eh; + + eh = (struct ppc_link_hash_entry *) h; + *tls_maskp = &eh->tls_mask; + } + } + else + { + Elf_Internal_Sym *sym; + Elf_Internal_Sym *locsyms = *locsymsp; + + if (locsyms == NULL) + { + locsyms = (Elf_Internal_Sym *) symtab_hdr->contents; + if (locsyms == NULL) + locsyms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, + symtab_hdr->sh_info, + 0, NULL, NULL, NULL); + if (locsyms == NULL) + return FALSE; + *locsymsp = locsyms; + } + sym = locsyms + r_symndx; + + if (hp != NULL) + *hp = NULL; + + if (symp != NULL) + *symp = sym; + + if (symsecp != NULL) + { + asection *symsec = NULL; + if ((sym->st_shndx != SHN_UNDEF + && sym->st_shndx < SHN_LORESERVE) + || sym->st_shndx > SHN_HIRESERVE) + symsec = bfd_section_from_elf_index (ibfd, sym->st_shndx); + *symsecp = symsec; + } + + if (tls_maskp != NULL) + { + struct got_entry **lgot_ents; + char *tls_mask; + + tls_mask = NULL; + lgot_ents = elf_local_got_ents (ibfd); + if (lgot_ents != NULL) + { + char *lgot_masks = (char *) (lgot_ents + symtab_hdr->sh_info); + tls_mask = &lgot_masks[r_symndx]; + } + *tls_maskp = tls_mask; + } + } + return TRUE; +} + +/* Returns TLS_MASKP for the given REL symbol. Function return is 0 on + error, 2 on a toc GD type suitable for optimization, 3 on a toc LD + type suitable for optimization, and 1 otherwise. */ + +static int +get_tls_mask (tls_maskp, locsymsp, rel, ibfd) + char **tls_maskp; + Elf_Internal_Sym **locsymsp; + const Elf_Internal_Rela *rel; + bfd *ibfd; +{ + unsigned long r_symndx; + unsigned int next_r; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + asection *sec; + bfd_vma off; + + r_symndx = ELF64_R_SYM (rel->r_info); + if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) + return 0; + + if ((*tls_maskp != NULL && **tls_maskp != 0) + || sec == NULL + || ppc64_elf_section_data (sec)->t_symndx == NULL) + return 1; + + /* Look inside a TOC section too. */ + if (h != NULL) + { + BFD_ASSERT (h->root.type == bfd_link_hash_defined); + off = h->root.u.def.value; + } + else + off = sym->st_value; + off += rel->r_addend; + BFD_ASSERT (off % 8 == 0); + r_symndx = ppc64_elf_section_data (sec)->t_symndx[off / 8]; + next_r = ppc64_elf_section_data (sec)->t_symndx[off / 8 + 1]; + if (!get_sym_h (&h, &sym, &sec, tls_maskp, locsymsp, r_symndx, ibfd)) + return 0; + if (h == NULL + || h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + if (next_r == (unsigned) -1) + return 2; + if (next_r == (unsigned) -2 + && (h == NULL + || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))) + return 3; + } + return 1; +} + bfd_boolean ppc64_elf_edit_opd (obfd, info) bfd *obfd; struct bfd_link_info *info; { bfd *ibfd; - unsigned int bfd_indx; - for (bfd_indx = 0, ibfd = info->input_bfds; - ibfd != NULL; - ibfd = ibfd->link_next, bfd_indx++) + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { asection *sec; Elf_Internal_Rela *relstart, *rel, *relend; @@ -3672,44 +4916,22 @@ ppc64_elf_edit_opd (obfd, info) } r_symndx = ELF64_R_SYM (rel->r_info); - sym_sec = NULL; - h = NULL; - sym = NULL; - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - sym_sec = h->root.u.def.section; - } - else - { - if (local_syms == NULL) - { - local_syms = (Elf_Internal_Sym *) symtab_hdr->contents; - if (local_syms == NULL) - local_syms = bfd_elf_get_elf_syms (ibfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (local_syms == NULL) - goto error_free_rel; - } - sym = local_syms + r_symndx; - if ((sym->st_shndx != SHN_UNDEF - && sym->st_shndx < SHN_LORESERVE) - || sym->st_shndx > SHN_HIRESERVE) - sym_sec = bfd_section_from_elf_index (ibfd, sym->st_shndx); - } + if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, + r_symndx, ibfd)) + goto error_free_rel; if (sym_sec == NULL || sym_sec->owner == NULL) { + const char *sym_name; + if (h != NULL) + sym_name = h->root.root.string; + else + sym_name = bfd_elf_local_sym_name (ibfd, sym); + (*_bfd_error_handler) (_("%s: undefined sym `%s' in .opd section"), bfd_archive_filename (ibfd), - h != NULL ? h->root.root.string : "<local symbol>"); + sym_name); need_edit = FALSE; break; } @@ -3774,28 +4996,8 @@ ppc64_elf_edit_opd (obfd, info) Elf_Internal_Sym *sym; r_symndx = ELF64_R_SYM (rel->r_info); - sym_sec = NULL; - h = NULL; - sym = NULL; - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - while (h->root.type == bfd_link_hash_indirect - || h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - sym_sec = h->root.u.def.section; - } - else - { - sym = local_syms + r_symndx; - if ((sym->st_shndx != SHN_UNDEF - && sym->st_shndx < SHN_LORESERVE) - || sym->st_shndx > SHN_HIRESERVE) - sym_sec = bfd_section_from_elf_index (ibfd, - sym->st_shndx); - } + get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, + r_symndx, ibfd); skip = (sym_sec->owner != ibfd || sym_sec->output_section == bfd_abs_section_ptr); @@ -3918,13 +5120,340 @@ ppc64_elf_edit_opd (obfd, info) return TRUE; } +/* Set htab->tls_sec. */ + +bfd_boolean +ppc64_elf_tls_setup (obfd, info) + bfd *obfd; + struct bfd_link_info *info; +{ + asection *tls; + struct ppc_link_hash_table *htab; + + for (tls = obfd->sections; tls != NULL; tls = tls->next) + if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) + == (SEC_THREAD_LOCAL | SEC_LOAD)) + break; + + htab = ppc_hash_table (info); + htab->tls_sec = tls; + + if (htab->tls_get_addr != NULL) + { + struct elf_link_hash_entry *h = htab->tls_get_addr; + + while (h->root.type == bfd_link_hash_indirect + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + + htab->tls_get_addr = h; + } + + return tls != NULL; +} + +/* Run through all the TLS relocs looking for optimization + opportunities. The linker has been hacked (see ppc64elf.em) to do + a preliminary section layout so that we know the TLS segment + offsets. We can't optimize earlier because some optimizations need + to know the tp offset, and we need to optimize before allocating + dynamic relocations. */ + +bfd_boolean +ppc64_elf_tls_optimize (obfd, info) + bfd *obfd ATTRIBUTE_UNUSED; + struct bfd_link_info *info; +{ + bfd *ibfd; + asection *sec; + struct ppc_link_hash_table *htab; + + if (info->relocateable || info->shared) + return TRUE; + + htab = ppc_hash_table (info); + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + Elf_Internal_Sym *locsyms = NULL; + + for (sec = ibfd->sections; sec != NULL; sec = sec->next) + if (sec->has_tls_reloc && !bfd_is_abs_section (sec->output_section)) + { + Elf_Internal_Rela *relstart, *rel, *relend; + int expecting_tls_get_addr; + + /* Read the relocations. */ + relstart = _bfd_elf64_link_read_relocs (ibfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, + info->keep_memory); + if (relstart == NULL) + return FALSE; + + expecting_tls_get_addr = 0; + relend = relstart + sec->reloc_count; + for (rel = relstart; rel < relend; rel++) + { + enum elf_ppc64_reloc_type r_type; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + asection *sym_sec; + char *tls_mask; + char tls_set, tls_clear, tls_type = 0; + bfd_vma value; + bfd_boolean ok_tprel, is_local; + + r_symndx = ELF64_R_SYM (rel->r_info); + if (!get_sym_h (&h, &sym, &sym_sec, &tls_mask, &locsyms, + r_symndx, ibfd)) + { + err_free_rel: + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + if (locsyms != NULL + && (elf_tdata (ibfd)->symtab_hdr.contents + != (unsigned char *) locsyms)) + free (locsyms); + return FALSE; + } + + if (h != NULL) + { + if (h->root.type != bfd_link_hash_defined + && h->root.type != bfd_link_hash_defweak) + continue; + value = h->root.u.def.value; + } + else + value = sym->st_value; + + ok_tprel = FALSE; + is_local = FALSE; + if (h == NULL + || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) + { + is_local = TRUE; + value += sym_sec->output_offset; + value += sym_sec->output_section->vma; + value -= htab->tls_sec->vma; + ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31) + < (bfd_vma) 1 << 32); + } + + r_type + = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info); + switch (r_type) + { + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + /* These relocs should never be against a symbol + defined in a shared lib. Leave them alone if + that turns out to be the case. */ + htab->tlsld_got.refcount -= 1; + if (!is_local) + continue; + + /* LD -> LE */ + tls_set = 0; + tls_clear = TLS_LD; + tls_type = TLS_TLS | TLS_LD; + expecting_tls_get_addr = 1; + break; + + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + if (ok_tprel) + /* GD -> LE */ + tls_set = 0; + else + /* GD -> IE */ + tls_set = TLS_TLS | TLS_TPRELGD; + tls_clear = TLS_GD; + tls_type = TLS_TLS | TLS_GD; + expecting_tls_get_addr = 1; + break; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_TPREL16_HI: + case R_PPC64_GOT_TPREL16_HA: + expecting_tls_get_addr = 0; + if (ok_tprel) + { + /* IE -> LE */ + tls_set = 0; + tls_clear = TLS_TPREL; + tls_type = TLS_TLS | TLS_TPREL; + break; + } + else + continue; + + case R_PPC64_REL14: + case R_PPC64_REL14_BRTAKEN: + case R_PPC64_REL14_BRNTAKEN: + case R_PPC64_REL24: + if (h != NULL + && h == htab->tls_get_addr) + { + if (!expecting_tls_get_addr + && rel != relstart + && ((ELF64_R_TYPE (rel[-1].r_info) + == R_PPC64_TOC16) + || (ELF64_R_TYPE (rel[-1].r_info) + == R_PPC64_TOC16_LO))) + { + /* Check for toc tls entries. */ + char *toc_tls; + int retval; + + retval = get_tls_mask (&toc_tls, &locsyms, + rel - 1, ibfd); + if (retval == 0) + goto err_free_rel; + if (toc_tls != NULL) + expecting_tls_get_addr = retval > 1; + } + + if (expecting_tls_get_addr) + { + struct plt_entry *ent; + for (ent = h->plt.plist; ent; ent = ent->next) + if (ent->addend == 0) + { + if (ent->plt.refcount > 0) + ent->plt.refcount -= 1; + break; + } + } + } + expecting_tls_get_addr = 0; + continue; + + case R_PPC64_TPREL64: + expecting_tls_get_addr = 0; + if (ok_tprel) + { + /* IE -> LE */ + tls_set = TLS_EXPLICIT; + tls_clear = TLS_TPREL; + break; + } + else + continue; + + case R_PPC64_DTPMOD64: + expecting_tls_get_addr = 0; + if (rel + 1 < relend + && (rel[1].r_info + == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64)) + && rel[1].r_offset == rel->r_offset + 8) + { + if (ok_tprel) + /* GD -> LE */ + tls_set = TLS_EXPLICIT | TLS_GD; + else + /* GD -> IE */ + tls_set = TLS_EXPLICIT | TLS_GD | TLS_TPRELGD; + tls_clear = TLS_GD; + } + else + { + if (!is_local) + continue; + + /* LD -> LE */ + tls_set = TLS_EXPLICIT; + tls_clear = TLS_LD; + } + break; + + default: + expecting_tls_get_addr = 0; + continue; + } + + if ((tls_set & TLS_EXPLICIT) == 0) + { + struct got_entry *ent; + + /* Adjust got entry for this reloc. */ + if (h != NULL) + ent = h->got.glist; + else + ent = elf_local_got_ents (ibfd)[r_symndx]; + + for (; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->tls_type == tls_type) + break; + if (ent == NULL) + abort (); + + if (tls_set == 0) + { + /* We managed to get rid of a got entry. */ + if (ent->got.refcount > 0) + ent->got.refcount -= 1; + } + } + else if (h != NULL) + { + struct ppc_link_hash_entry * eh; + struct ppc_dyn_relocs **pp; + struct ppc_dyn_relocs *p; + + /* Adjust dynamic relocs. */ + eh = (struct ppc_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; + (p = *pp) != NULL; + pp = &p->next) + if (p->sec == sec) + { + /* If we got rid of a DTPMOD/DTPREL reloc + pair then we'll lose one or two dyn + relocs. */ + if (tls_set == (TLS_EXPLICIT | TLS_GD)) + p->count -= 1; + p->count -= 1; + if (p->count == 0) + *pp = p->next; + break; + } + } + + *tls_mask |= tls_set; + *tls_mask &= ~tls_clear; + } + + if (elf_section_data (sec)->relocs != relstart) + free (relstart); + } + + if (locsyms != NULL + && (elf_tdata (ibfd)->symtab_hdr.contents + != (unsigned char *) locsyms)) + { + if (!info->keep_memory) + free (locsyms); + else + elf_tdata (ibfd)->symtab_hdr.contents = (unsigned char *) locsyms; + } + } + return TRUE; +} + /* This is the condition under which ppc64_elf_finish_dynamic_symbol will be called from elflink.h. If elflink.h doesn't call our finish_dynamic_symbol routine, we'll need to do something about initializing any .plt and .got entries in ppc64_elf_relocate_section. */ -#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \ ((DYN) \ - && ((INFO)->shared \ + && ((SHARED) \ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \ && ((H)->dynindx != -1 \ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)) @@ -3942,6 +5471,7 @@ allocate_dynrelocs (h, inf) asection *s; struct ppc_link_hash_entry *eh; struct ppc_dyn_relocs *p; + struct got_entry *gent; if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -3953,73 +5483,117 @@ allocate_dynrelocs (h, inf) htab = ppc_hash_table (info); if (htab->elf.dynamic_sections_created - && h->plt.refcount > 0 - && h->dynindx != -1) + && h->dynindx != -1 + && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h)) { - BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor); - - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h)) - { - /* If this is the first .plt entry, make room for the special - first entry. */ - s = htab->splt; - if (s->_raw_size == 0) - s->_raw_size += PLT_INITIAL_ENTRY_SIZE; - - h->plt.offset = s->_raw_size; - - /* Make room for this entry. */ - s->_raw_size += PLT_ENTRY_SIZE; - - /* Make room for the .glink code. */ - s = htab->sglink; - if (s->_raw_size == 0) - s->_raw_size += GLINK_CALL_STUB_SIZE; - /* We need bigger stubs past index 32767. */ - if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4) - s->_raw_size += 4; - s->_raw_size += 2*4; - - /* We also need to make an entry in the .rela.plt section. */ - s = htab->srelplt; - s->_raw_size += sizeof (Elf64_External_Rela); - } - else + struct plt_entry *pent; + bfd_boolean doneone = FALSE; + for (pent = h->plt.plist; pent != NULL; pent = pent->next) + if (pent->plt.refcount > 0) + { + BFD_ASSERT (((struct ppc_link_hash_entry *) h)->is_func_descriptor); + + /* If this is the first .plt entry, make room for the special + first entry. */ + s = htab->splt; + if (s->_raw_size == 0) + s->_raw_size += PLT_INITIAL_ENTRY_SIZE; + + pent->plt.offset = s->_raw_size; + + /* Make room for this entry. */ + s->_raw_size += PLT_ENTRY_SIZE; + + /* Make room for the .glink code. */ + s = htab->sglink; + if (s->_raw_size == 0) + s->_raw_size += GLINK_CALL_STUB_SIZE; + /* We need bigger stubs past index 32767. */ + if (s->_raw_size >= GLINK_CALL_STUB_SIZE + 32768*2*4) + s->_raw_size += 4; + s->_raw_size += 2*4; + + /* We also need to make an entry in the .rela.plt section. */ + s = htab->srelplt; + s->_raw_size += sizeof (Elf64_External_Rela); + doneone = TRUE; + } + else + pent->plt.offset = (bfd_vma) -1; + if (!doneone) { - h->plt.offset = (bfd_vma) -1; + h->plt.plist = NULL; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } } else { - h->plt.offset = (bfd_vma) -1; + h->plt.plist = NULL; h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } - if (h->got.refcount > 0) - { - bfd_boolean dyn; - - /* Make sure this symbol is output as a dynamic symbol. - Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 - && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + eh = (struct ppc_link_hash_entry *) h; + /* Run through the TLS GD got entries first if we're changing them + to TPREL. */ + if ((eh->tls_mask & TLS_TPRELGD) != 0) + for (gent = h->got.glist; gent != NULL; gent = gent->next) + if (gent->got.refcount > 0 + && (gent->tls_type & TLS_GD) != 0) { - if (! bfd_elf64_link_record_dynamic_symbol (info, h)) - return FALSE; + /* This was a GD entry that has been converted to TPREL. If + there happens to be a TPREL entry we can use that one. */ + struct got_entry *ent; + for (ent = h->got.glist; ent != NULL; ent = ent->next) + if (ent->got.refcount > 0 + && (ent->tls_type & TLS_TPREL) != 0 + && ent->addend == gent->addend) + { + gent->got.refcount = 0; + break; + } + + /* If not, then we'll be using our own TPREL entry. */ + if (gent->got.refcount != 0) + gent->tls_type = TLS_TLS | TLS_TPREL; } - s = htab->sgot; - h->got.offset = s->_raw_size; - s->_raw_size += 8; - dyn = htab->elf.dynamic_sections_created; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h)) - htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); - } - else - h->got.offset = (bfd_vma) -1; + for (gent = h->got.glist; gent != NULL; gent = gent->next) + if (gent->got.refcount > 0) + { + bfd_boolean dyn; + + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic, + nor will all TLS symbols. */ + if (h->dynindx == -1 + && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) + { + if (! bfd_elf64_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + if ((gent->tls_type & TLS_LD) != 0 + && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)) + { + gent->got.offset = htab->tlsld_got.offset; + continue; + } + + s = htab->sgot; + gent->got.offset = s->_raw_size; + s->_raw_size + += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8; + dyn = htab->elf.dynamic_sections_created; + if (info->shared + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) + htab->srelgot->_raw_size + += (gent->tls_type & eh->tls_mask & TLS_GD + ? 2 * sizeof (Elf64_External_Rela) + : sizeof (Elf64_External_Rela)); + } + else + gent->got.offset = (bfd_vma) -1; - eh = (struct ppc_link_hash_entry *) h; if (eh->dyn_relocs == NULL) return TRUE; @@ -4048,18 +5622,15 @@ allocate_dynrelocs (h, inf) } } } - else + else if (ELIMINATE_COPY_RELOCS) { /* For the non-shared case, discard space for relocs against symbols which turn out to need copy relocs or are not dynamic. */ if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) - || (htab->elf.dynamic_sections_created - && (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined)))) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ @@ -4153,12 +5724,23 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) } } + if (htab->tlsld_got.refcount > 0) + { + htab->tlsld_got.offset = htab->sgot->_raw_size; + htab->sgot->_raw_size += 16; + if (info->shared) + htab->srelgot->_raw_size += sizeof (Elf64_External_Rela); + } + else + htab->tlsld_got.offset = (bfd_vma) -1; + /* Set up .got offsets for local syms, and space for local dynamic relocs. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) { - bfd_signed_vma *local_got; - bfd_signed_vma *end_local_got; + struct got_entry **lgot_ents; + struct got_entry **end_lgot_ents; + char *lgot_masks; bfd_size_type locsymcount; Elf_Internal_Shdr *symtab_hdr; asection *srel; @@ -4193,26 +5775,53 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) } } - local_got = elf_local_got_refcounts (ibfd); - if (!local_got) + lgot_ents = elf_local_got_ents (ibfd); + if (!lgot_ents) continue; symtab_hdr = &elf_tdata (ibfd)->symtab_hdr; locsymcount = symtab_hdr->sh_info; - end_local_got = local_got + locsymcount; + end_lgot_ents = lgot_ents + locsymcount; + lgot_masks = (char *) end_lgot_ents; s = htab->sgot; srel = htab->srelgot; - for (; local_got < end_local_got; ++local_got) + for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks) { - if (*local_got > 0) - { - *local_got = s->_raw_size; - s->_raw_size += 8; - if (info->shared) - srel->_raw_size += sizeof (Elf64_External_Rela); - } - else - *local_got = (bfd_vma) -1; + struct got_entry *ent; + + for (ent = *lgot_ents; ent != NULL; ent = ent->next) + if (ent->got.refcount > 0) + { + if ((ent->tls_type & *lgot_masks & TLS_LD) != 0) + { + if (htab->tlsld_got.offset == (bfd_vma) -1) + { + htab->tlsld_got.offset = s->_raw_size; + s->_raw_size += 16; + if (info->shared) + srel->_raw_size += sizeof (Elf64_External_Rela); + } + ent->got.offset = htab->tlsld_got.offset; + } + else + { + ent->got.offset = s->_raw_size; + if ((ent->tls_type & *lgot_masks & TLS_GD) != 0) + { + s->_raw_size += 16; + if (info->shared) + srel->_raw_size += 2 * sizeof (Elf64_External_Rela); + } + else + { + s->_raw_size += 8; + if (info->shared) + srel->_raw_size += sizeof (Elf64_External_Rela); + } + } + } + else + ent->got.offset = (bfd_vma) -1; } } @@ -4228,6 +5837,10 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) if ((s->flags & SEC_LINKER_CREATED) == 0) continue; + /* Reset _cooked_size since prelim layout will set it wrongly, + and a non-zero _cooked_size sticks. */ + s->_cooked_size = 0; + if (s == htab->sbrlt || s == htab->srelbrlt) /* These haven't been allocated yet; don't strip. */ continue; @@ -4281,8 +5894,10 @@ ppc64_elf_size_dynamic_sections (output_bfd, info) /* Allocate memory for the section contents. We use bfd_zalloc here in case unused entries are not reclaimed before the section's contents are written out. This should not happen, - but this way if it does, we get a R_PPC64_NONE reloc instead - of garbage. */ + but this way if it does we get a R_PPC64_NONE reloc in .rela + sections instead of garbage. + We also rely on the section contents being zero when writing + the GOT. */ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size); if (s->contents == NULL) return FALSE; @@ -4364,11 +5979,16 @@ ppc_type_of_stub (input_sec, rel, hash, destination) if (h != NULL) { if (h->oh != NULL - && h->oh->plt.offset != (bfd_vma) -1 && h->oh->dynindx != -1) { - *hash = (struct ppc_link_hash_entry *) h->oh; - return ppc_stub_plt_call; + struct plt_entry *ent; + for (ent = h->oh->plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->plt.offset != (bfd_vma) -1) + { + *hash = (struct ppc_link_hash_entry *) h->oh; + return ppc_stub_plt_call; + } } if (h->elf.root.type == bfd_link_hash_undefweak @@ -4443,6 +6063,7 @@ ppc_build_one_stub (gen_entry, in_arg) bfd_byte *loc; bfd_byte *p; unsigned int indx; + struct plt_entry *ent; bfd_vma off; int size; @@ -4554,7 +6175,13 @@ ppc_build_one_stub (gen_entry, in_arg) } /* Now build the stub. */ - off = stub_entry->h->elf.plt.offset; + off = (bfd_vma) -1; + for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == stub_entry->addend) + { + off = ent->plt.offset; + break; + } if (off >= (bfd_vma) -2) abort (); @@ -4607,7 +6234,16 @@ ppc_size_one_stub (gen_entry, in_arg) if (stub_entry->stub_type == ppc_stub_plt_call) { - off = stub_entry->h->elf.plt.offset & ~(bfd_vma) 1; + struct plt_entry *ent; + off = (bfd_vma) -1; + for (ent = stub_entry->h->elf.plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == stub_entry->addend) + { + off = ent->plt.offset & ~(bfd_vma) 1; + break; + } + if (off >= (bfd_vma) -2) + abort (); off += (htab->splt->output_offset + htab->splt->output_section->vma - elf_gp (htab->splt->output_section->owner) @@ -4786,12 +6422,15 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) asection *curr; asection *prev; bfd_size_type total; + bfd_boolean big_sec; curr = tail; if (tail->_cooked_size) total = tail->_cooked_size; else total = tail->_raw_size; + big_sec = total >= stub_group_size; + while ((prev = PREV_SEC (curr)) != NULL && ((total += curr->output_offset - prev->output_offset) < stub_group_size)) @@ -4806,7 +6445,7 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) section size. That's a little tricky, and this way will 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 2834432 bytes, or over 100000 plt call stubs. */ + more than 2097152 bytes, or nearly 75000 plt call stubs. */ do { prev = PREV_SEC (tail); @@ -4816,8 +6455,11 @@ group_sections (htab, stub_group_size, stubs_always_before_branch) while (tail != curr && (tail = prev) != NULL); /* But wait, there's more! Input sections up to stub_group_size - bytes before the stub section can be handled by it too. */ - if (!stubs_always_before_branch) + bytes before the stub section can be handled by it too. + Don't do this if we have a really large section after the + stubs, as adding more stubs increases the chance that + branches may not reach into the stub section. */ + if (!stubs_always_before_branch && !big_sec) { total = 0; while (prev != NULL @@ -4869,9 +6511,18 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, if (stub_group_size == 1) { /* Default values. */ - stub_group_size = 30720000; - if (htab->has_14bit_branch) - stub_group_size = 30000; + 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); @@ -4938,6 +6589,8 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, bfd_vma sym_value; bfd_vma destination; struct ppc_link_hash_entry *hash; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; char *stub_name; const asection *id_sec; @@ -4959,33 +6612,16 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, /* Now determine the call target, its name, value, section. */ - sym_sec = NULL; - sym_value = 0; destination = 0; - hash = NULL; - if (r_indx < symtab_hdr->sh_info) + if (!get_sym_h (&h, &sym, &sym_sec, NULL, &local_syms, + r_indx, input_bfd)) + goto error_ret_free_internal; + hash = (struct ppc_link_hash_entry *) h; + + if (hash == NULL) { /* It's a local symbol. */ - Elf_Internal_Sym *sym; - Elf_Internal_Shdr *hdr; - - if (local_syms == NULL) - { - local_syms - = (Elf_Internal_Sym *) symtab_hdr->contents; - if (local_syms == NULL) - local_syms - = bfd_elf_get_elf_syms (input_bfd, symtab_hdr, - symtab_hdr->sh_info, 0, - NULL, NULL, NULL); - if (local_syms == NULL) - goto error_ret_free_internal; - } - sym = local_syms + r_indx; - hdr = elf_elfsections (input_bfd)[sym->st_shndx]; - sym_sec = hdr->bfd_section; - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) - sym_value = sym->st_value; + sym_value = sym->st_value; destination = (sym_value + irela->r_addend + sym_sec->output_offset + sym_sec->output_section->vma); @@ -4993,21 +6629,10 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, else { /* It's an external symbol. */ - int e_indx; - - e_indx = r_indx - symtab_hdr->sh_info; - hash = ((struct ppc_link_hash_entry *) - elf_sym_hashes (input_bfd)[e_indx]); - - while (hash->elf.root.type == bfd_link_hash_indirect - || hash->elf.root.type == bfd_link_hash_warning) - hash = ((struct ppc_link_hash_entry *) - hash->elf.root.u.i.link); - + sym_value = 0; if (hash->elf.root.type == bfd_link_hash_defined || hash->elf.root.type == bfd_link_hash_defweak) { - sym_sec = hash->elf.root.u.def.section; sym_value = hash->elf.root.u.def.value; if (sym_sec->output_section != NULL) destination = (sym_value + irela->r_addend @@ -5031,6 +6656,23 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, if (stub_type == ppc_stub_none) continue; + /* __tls_get_addr calls might be eliminated. */ + if (stub_type != ppc_stub_plt_call + && hash != NULL + && &hash->elf == htab->tls_get_addr + && section->has_tls_reloc + && irela != internal_relocs) + { + /* Get tls info. */ + char *tls_mask; + + if (!get_tls_mask (&tls_mask, &local_syms, + irela - 1, input_bfd)) + goto error_ret_free_internal; + if (*tls_mask != 0) + continue; + } + /* Support for grouping stub sections. */ id_sec = htab->stub_group[section->id].link_sec; @@ -5067,6 +6709,7 @@ ppc64_elf_size_stubs (output_bfd, stub_bfd, info, group_size, stub_entry->target_section = sym_sec; stub_entry->stub_type = stub_type; stub_entry->h = hash; + stub_entry->addend = irela->r_addend; stub_changed = TRUE; } @@ -5317,7 +6960,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, struct elf_link_hash_entry **sym_hashes; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; - bfd_vma *local_got_offsets; + Elf_Internal_Rela outrel; + bfd_byte *loc; + struct got_entry **local_got_ents; bfd_vma TOCstart; bfd_boolean ret = TRUE; bfd_boolean is_opd; @@ -5332,7 +6977,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, ppc_howto_init (); htab = ppc_hash_table (info); - local_got_offsets = elf_local_got_offsets (input_bfd); + local_got_ents = elf_local_got_ents (input_bfd); TOCstart = elf_gp (output_bfd); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); @@ -5343,7 +6988,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, for (; rel < relend; rel++) { enum elf_ppc64_reloc_type r_type; - bfd_vma offset; bfd_vma addend; bfd_reloc_status_type r; Elf_Internal_Sym *sym; @@ -5352,6 +6996,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, struct elf_link_hash_entry *fdh; const char *sym_name; unsigned long r_symndx; + char tls_mask, tls_gd, tls_type; bfd_vma relocation; bfd_boolean unresolved_reloc; bfd_boolean warned; @@ -5362,9 +7007,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, r_type = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel->r_info); r_symndx = ELF64_R_SYM (rel->r_info); - offset = rel->r_offset; - addend = rel->r_addend; - r = bfd_reloc_other; sym = (Elf_Internal_Sym *) 0; sec = (asection *) 0; h = (struct elf_link_hash_entry *) 0; @@ -5382,12 +7024,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* It's a local symbol. */ sym = local_syms + r_symndx; sec = local_sections[r_symndx]; - sym_name = "<local symbol>"; - + sym_name = bfd_elf_local_sym_name (input_bfd, sym); relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); - /* rel may have changed, update our copy of addend. */ - addend = rel->r_addend; - if (elf_section_data (sec) != NULL) { long *opd_sym_adjust; @@ -5424,7 +7062,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) ; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -5432,15 +7069,323 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, - offset, (!info->shared - || info->no_undefined - || ELF_ST_VISIBILITY (h->other))))) + rel->r_offset, (!info->shared + || info->no_undefined + || ELF_ST_VISIBILITY (h->other))))) return FALSE; warned = TRUE; } } - /* First handle relocations that tweak non-addend part of insn. */ + /* TLS optimizations. Replace instruction sequences and relocs + based on information we collected in tls_optimize. We edit + RELOCS so that --emit-relocs will output something sensible + for the final instruction stream. */ + tls_mask = 0; + tls_gd = 0; + if (IS_PPC64_TLS_RELOC (r_type)) + { + if (h != NULL) + tls_mask = ((struct ppc_link_hash_entry *) h)->tls_mask; + else if (local_got_ents != NULL) + { + char *lgot_masks; + lgot_masks = (char *) (local_got_ents + symtab_hdr->sh_info); + tls_mask = lgot_masks[r_symndx]; + } + } + + /* Ensure reloc mapping code below stays sane. */ + if (R_PPC64_TOC16_LO_DS != R_PPC64_TOC16_DS + 1 + || R_PPC64_TOC16_LO != R_PPC64_TOC16 + 1 + || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TLSGD16 & 3) + || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TLSGD16_LO & 3) + || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TLSGD16_HI & 3) + || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TLSGD16_HA & 3) + || (R_PPC64_GOT_TLSLD16 & 3) != (R_PPC64_GOT_TPREL16_DS & 3) + || (R_PPC64_GOT_TLSLD16_LO & 3) != (R_PPC64_GOT_TPREL16_LO_DS & 3) + || (R_PPC64_GOT_TLSLD16_HI & 3) != (R_PPC64_GOT_TPREL16_HI & 3) + || (R_PPC64_GOT_TLSLD16_HA & 3) != (R_PPC64_GOT_TPREL16_HA & 3)) + abort (); + switch (r_type) + { + default: + break; + + case R_PPC64_TOC16: + case R_PPC64_TOC16_LO: + case R_PPC64_TOC16_DS: + case R_PPC64_TOC16_LO_DS: + { + /* Check for toc tls entries. */ + char *toc_tls; + int retval; + + retval = get_tls_mask (&toc_tls, &local_syms, rel, input_bfd); + if (retval == 0) + return FALSE; + + if (toc_tls) + { + tls_mask = *toc_tls; + if (r_type == R_PPC64_TOC16_DS + || r_type == R_PPC64_TOC16_LO_DS) + goto toctprel; + else + { + /* If we found a GD reloc pair, then we might be + doing a GD->IE transition. */ + if (retval == 2) + { + tls_gd = TLS_TPRELGD; + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + goto tls_get_addr_check; + } + else if (retval == 3) + { + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + goto tls_get_addr_check; + } + } + } + } + break; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + toctprel: + if (tls_mask != 0 + && (tls_mask & TLS_TPREL) == 0) + { + bfd_vma insn; + insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2); + insn &= 31 << 21; + insn |= 0x3c0d0000; /* addis 0,13,0 */ + bfd_put_32 (output_bfd, insn, contents + rel->r_offset - 2); + r_type = R_PPC64_TPREL16_HA; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + break; + + case R_PPC64_TLS: + if (tls_mask == 0) + { + /* Check for toc tls entries. */ + char *toc_tls; + + if (!get_tls_mask (&toc_tls, &local_syms, rel, input_bfd)) + return FALSE; + + if (toc_tls) + tls_mask = *toc_tls; + } + if (tls_mask != 0 + && (tls_mask & TLS_TPREL) == 0) + { + bfd_vma insn, rtra; + insn = bfd_get_32 (output_bfd, contents + rel->r_offset); + if ((insn & ((31 << 26) | (31 << 11))) + == ((31 << 26) | (13 << 11))) + rtra = insn & ((1 << 26) - (1 << 16)); + else if ((insn & ((31 << 26) | (31 << 16))) + == ((31 << 26) | (13 << 16))) + rtra = (insn & (31 << 21)) | ((insn & (31 << 11)) << 5); + else + abort (); + if ((insn & ((1 << 11) - (1 << 1))) == 266 << 1) + /* add -> addi. */ + insn = 14 << 26; + else if ((insn & (31 << 1)) == 23 << 1 + && ((insn & (31 << 6)) < 14 << 6 + || ((insn & (31 << 6)) >= 16 << 6 + && (insn & (31 << 6)) < 24 << 6))) + /* load and store indexed -> dform. */ + insn = (32 | ((insn >> 6) & 31)) << 26; + else if ((insn & (31 << 1)) == 21 << 1 + && (insn & (0x1a << 6)) == 0) + /* ldx, ldux, stdx, stdux -> ld, ldu, std, stdu. */ + insn = (((58 | ((insn >> 6) & 4)) << 26) + | ((insn >> 6) & 1)); + else if ((insn & (31 << 1)) == 21 << 1 + && (insn & ((1 << 11) - (1 << 1))) == 341 << 1) + /* lwax -> lwa. */ + insn = (58 << 26) | 2; + else + abort (); + insn |= rtra; + bfd_put_32 (output_bfd, insn, contents + rel->r_offset); + r_type = R_PPC64_TPREL16_LO; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + /* Was PPC64_TLS which sits on insn boundary, now + PPC64_TPREL16_LO which is at insn+2. */ + rel->r_offset += 2; + } + break; + + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + tls_gd = TLS_TPRELGD; + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + goto tls_gdld_hi; + break; + + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + tls_gdld_hi: + if ((tls_mask & tls_gd) != 0) + r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) + + R_PPC64_GOT_TPREL16_DS); + else + { + bfd_put_32 (output_bfd, NOP, contents + rel->r_offset); + rel->r_offset -= 2; + r_type = R_PPC64_NONE; + } + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + break; + + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + tls_gd = TLS_TPRELGD; + if (tls_mask != 0 && (tls_mask & TLS_GD) == 0) + goto tls_get_addr_check; + break; + + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + if (tls_mask != 0 && (tls_mask & TLS_LD) == 0) + { + tls_get_addr_check: + if (rel + 1 < relend) + { + enum elf_ppc64_reloc_type r_type2; + unsigned long r_symndx2; + struct elf_link_hash_entry *h2; + bfd_vma insn1, insn2, insn3; + bfd_vma offset; + + /* The next instruction should be a call to + __tls_get_addr. Peek at the reloc to be sure. */ + r_type2 + = (enum elf_ppc64_reloc_type) ELF64_R_TYPE (rel[1].r_info); + r_symndx2 = ELF64_R_SYM (rel[1].r_info); + if (r_symndx2 < symtab_hdr->sh_info + || (r_type2 != R_PPC64_REL14 + && r_type2 != R_PPC64_REL14_BRTAKEN + && r_type2 != R_PPC64_REL14_BRNTAKEN + && r_type2 != R_PPC64_REL24)) + break; + + h2 = sym_hashes[r_symndx2 - symtab_hdr->sh_info]; + while (h2->root.type == bfd_link_hash_indirect + || h2->root.type == bfd_link_hash_warning) + h2 = (struct elf_link_hash_entry *) h2->root.u.i.link; + if (h2 == NULL || h2 != htab->tls_get_addr) + break; + + /* OK, it checks out. Replace the call. */ + offset = rel[1].r_offset; + insn1 = bfd_get_32 (output_bfd, + contents + rel->r_offset - 2); + insn3 = bfd_get_32 (output_bfd, + contents + offset + 4); + if ((tls_mask & tls_gd) != 0) + { + /* IE */ + insn1 &= (1 << 26) - (1 << 2); + insn1 |= 58 << 26; /* ld */ + insn2 = 0x7c636a14; /* add 3,3,13 */ + rel[1].r_info = ELF64_R_INFO (r_symndx2, R_PPC64_NONE); + if ((tls_mask & TLS_EXPLICIT) == 0) + r_type = (((r_type - (R_PPC64_GOT_TLSGD16 & 3)) & 3) + + R_PPC64_GOT_TPREL16_DS); + else + r_type += R_PPC64_TOC16_DS - R_PPC64_TOC16; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + else + { + /* LE */ + insn1 = 0x3c6d0000; /* addis 3,13,0 */ + insn2 = 0x38630000; /* addi 3,3,0 */ + if (tls_gd == 0) + { + /* Was an LD reloc. */ + r_symndx = 0; + rel->r_addend = htab->tls_sec->vma + DTP_OFFSET; + rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET; + } + r_type = R_PPC64_TPREL16_HA; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + rel[1].r_info = ELF64_R_INFO (r_symndx, + R_PPC64_TPREL16_LO); + rel[1].r_offset += 2; + } + if (insn3 == NOP + || insn3 == CROR_151515 || insn3 == CROR_313131) + { + insn3 = insn2; + insn2 = NOP; + rel[1].r_offset += 4; + } + bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2); + bfd_put_32 (output_bfd, insn2, contents + offset); + bfd_put_32 (output_bfd, insn3, contents + offset + 4); + if (tls_gd == 0) + { + /* We changed the symbol on an LD reloc. Start over + in order to get h, sym, sec etc. right. */ + rel--; + continue; + } + } + } + break; + + case R_PPC64_DTPMOD64: + if (rel + 1 < relend + && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_DTPREL64) + && rel[1].r_offset == rel->r_offset + 8) + { + if ((tls_mask & TLS_GD) == 0) + { + rel[1].r_info = ELF64_R_INFO (r_symndx, R_PPC64_NONE); + if ((tls_mask & TLS_TPRELGD) != 0) + r_type = R_PPC64_TPREL64; + else + { + bfd_put_64 (output_bfd, (bfd_vma) 1, + contents + rel->r_offset); + r_type = R_PPC64_NONE; + } + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + } + else + { + if ((tls_mask & TLS_LD) == 0) + { + bfd_put_64 (output_bfd, (bfd_vma) 1, + contents + rel->r_offset); + r_type = R_PPC64_NONE; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + } + break; + + case R_PPC64_TPREL64: + if ((tls_mask & TLS_TPREL) == 0) + { + r_type = R_PPC64_NONE; + rel->r_info = ELF64_R_INFO (r_symndx, r_type); + } + break; + } + + /* Handle other relocations that tweak non-addend part of insn. */ insn = 0; switch (r_type) { @@ -5456,7 +7401,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* Branch not taken prediction relocations. */ case R_PPC64_ADDR14_BRNTAKEN: case R_PPC64_REL14_BRNTAKEN: - insn |= bfd_get_32 (output_bfd, contents + offset) & ~(0x01 << 21); + insn |= bfd_get_32 (output_bfd, + contents + rel->r_offset) & ~(0x01 << 21); if (is_power4) { /* Set 'a' bit. This is 0b00010 in BO field for branch @@ -5471,16 +7417,16 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, } else { - from = (offset + from = (rel->r_offset + input_section->output_offset + input_section->output_section->vma); /* Invert 'y' bit if not the default. */ - if ((bfd_signed_vma) (relocation + addend - from) < 0) + if ((bfd_signed_vma) (relocation + rel->r_addend - from) < 0) insn ^= 0x01 << 21; } - bfd_put_32 (output_bfd, (bfd_vma) insn, contents + offset); + bfd_put_32 (output_bfd, (bfd_vma) insn, contents + rel->r_offset); break; case R_PPC64_REL24: @@ -5491,20 +7437,20 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, need for a PLT entry. */ if (h != NULL && (fdh = ((struct ppc_link_hash_entry *) h)->oh) != NULL - && fdh->plt.offset != (bfd_vma) -1 + && fdh->plt.plist != NULL && (stub_entry = ppc_get_stub_entry (input_section, sec, fdh, rel, htab)) != NULL) { bfd_boolean can_plt_call = 0; - if (offset + 8 <= input_section->_cooked_size) + if (rel->r_offset + 8 <= input_section->_cooked_size) { - insn = bfd_get_32 (input_bfd, contents + offset + 4); + insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); if (insn == NOP || insn == CROR_151515 || insn == CROR_313131) { bfd_put_32 (input_bfd, (bfd_vma) LD_R2_40R1, - contents + offset + 4); + contents + rel->r_offset + 4); can_plt_call = 1; } } @@ -5513,7 +7459,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, { /* If this is a plain branch rather than a branch and link, don't require a nop. */ - insn = bfd_get_32 (input_bfd, contents + offset); + insn = bfd_get_32 (input_bfd, contents + rel->r_offset); if ((insn & 1) == 0) can_plt_call = 1; } @@ -5523,7 +7469,6 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (stub_entry->stub_offset + stub_entry->stub_sec->output_offset + stub_entry->stub_sec->output_section->vma); - addend = 0; unresolved_reloc = FALSE; } } @@ -5531,7 +7476,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h != NULL && h->root.type == bfd_link_hash_undefweak && relocation == 0 - && addend == 0) + && rel->r_addend == 0) { /* Tweak calls to undefined weak functions to point at a blr. We can thus call a weak function without first @@ -5541,7 +7486,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = (htab->sfpr->_raw_size - 4 + htab->sfpr->output_offset + htab->sfpr->output_section->vma); - from = (offset + from = (rel->r_offset + input_section->output_offset + input_section->output_section->vma); @@ -5555,6 +7500,8 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, } /* Set `addend'. */ + tls_type = 0; + addend = rel->r_addend; switch (r_type) { default: @@ -5567,103 +7514,179 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, continue; case R_PPC64_NONE: + case R_PPC64_TLS: case R_PPC64_GNU_VTINHERIT: case R_PPC64_GNU_VTENTRY: continue; /* GOT16 relocations. Like an ADDR16 using the symbol's address in the GOT as relocation value instead of the - symbols value itself. Also, create a GOT entry for the + symbol's value itself. Also, create a GOT entry for the symbol and put the symbol value there. */ + case R_PPC64_GOT_TLSGD16: + case R_PPC64_GOT_TLSGD16_LO: + case R_PPC64_GOT_TLSGD16_HI: + case R_PPC64_GOT_TLSGD16_HA: + tls_type = TLS_TLS | TLS_GD; + goto dogot; + + case R_PPC64_GOT_TLSLD16: + case R_PPC64_GOT_TLSLD16_LO: + case R_PPC64_GOT_TLSLD16_HI: + case R_PPC64_GOT_TLSLD16_HA: + tls_type = TLS_TLS | TLS_LD; + goto dogot; + + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_TPREL16_HI: + case R_PPC64_GOT_TPREL16_HA: + tls_type = TLS_TLS | TLS_TPREL; + goto dogot; + + case R_PPC64_GOT_DTPREL16_DS: + case R_PPC64_GOT_DTPREL16_LO_DS: + case R_PPC64_GOT_DTPREL16_HI: + case R_PPC64_GOT_DTPREL16_HA: + tls_type = TLS_TLS | TLS_DTPREL; + goto dogot; + case R_PPC64_GOT16: case R_PPC64_GOT16_LO: case R_PPC64_GOT16_HI: case R_PPC64_GOT16_HA: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_LO_DS: + dogot: { /* Relocation is to the entry for this symbol in the global offset table. */ + bfd_vma *offp; bfd_vma off; + unsigned long indx = 0; if (htab->sgot == NULL) abort (); - if (h != NULL) + if (tls_type == (TLS_TLS | TLS_LD) + && (h == NULL + || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))) + offp = &htab->tlsld_got.offset; + else { - bfd_boolean dyn; - - off = h->got.offset; - dyn = htab->elf.dynamic_sections_created; - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h) - || (info->shared - && (info->symbolic - || h->dynindx == -1 - || (h->elf_link_hash_flags - & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR))) + struct got_entry *ent; + + if (h != NULL) { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of 8, we use the - least significant bit to record whether we have - initialized it already. - - When doing a dynamic link, we create a .rel.got - relocation entry to initialize the value. This - is done in the finish_dynamic_symbol routine. */ - if ((off & 1) != 0) - off &= ~1; + bfd_boolean dyn = htab->elf.dynamic_sections_created; + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) + || (info->shared + && (info->symbolic + || h->dynindx == -1 + || (h->elf_link_hash_flags + & ELF_LINK_FORCED_LOCAL)) + && (h->elf_link_hash_flags + & ELF_LINK_HASH_DEF_REGULAR))) + /* This is actually a static link, or it is a + -Bsymbolic link and the symbol is defined + locally, or the symbol was forced to be local + because of a version file. */ + ; else { - bfd_put_64 (output_bfd, relocation, - htab->sgot->contents + off); - h->got.offset |= 1; + indx = h->dynindx; + unresolved_reloc = FALSE; } + ent = h->got.glist; } else - unresolved_reloc = FALSE; + { + if (local_got_ents == NULL) + abort (); + ent = local_got_ents[r_symndx]; + } + + for (; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->tls_type == tls_type) + break; + if (ent == NULL) + abort (); + offp = &ent->got.offset; } + + /* The offset must always be a multiple of 8. We use the + least significant bit to record whether we have already + processed this entry. */ + off = *offp; + if ((off & 1) != 0) + off &= ~1; else { - if (local_got_offsets == NULL) - abort (); - - off = local_got_offsets[r_symndx]; + /* Generate relocs for the dynamic linker, except in + the case of TLSLD where we'll use one entry per + module. */ + *offp = off | 1; + if (info->shared || indx != 0) + { + outrel.r_offset = (htab->sgot->output_section->vma + + htab->sgot->output_offset + + off); + if (tls_type & (TLS_LD | TLS_GD)) + { + outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64); + outrel.r_addend = 0; + if (tls_type == (TLS_TLS | TLS_GD)) + { + loc = htab->srelgot->contents; + loc += (htab->srelgot->reloc_count++ + * sizeof (Elf64_External_Rela)); + bfd_elf64_swap_reloca_out (output_bfd, + &outrel, loc); + outrel.r_info + = ELF64_R_INFO (indx, R_PPC64_DTPREL64); + outrel.r_offset += 8; + } + } + else if (tls_type == (TLS_TLS | TLS_DTPREL)) + outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64); + else if (tls_type == (TLS_TLS | TLS_TPREL)) + outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64); + else if (indx == 0) + outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE); + else + outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT); + outrel.r_addend = rel->r_addend; + if (indx == 0) + outrel.r_addend += relocation; + loc = htab->srelgot->contents; + loc += (htab->srelgot->reloc_count++ + * sizeof (Elf64_External_Rela)); + bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); + } - /* The offset must always be a multiple of 8. We use - the least significant bit to record whether we have - already processed this entry. */ - if ((off & 1) != 0) - off &= ~1; + /* Init the .got section contents if we're not + emitting a reloc. */ else { - bfd_put_64 (output_bfd, relocation, - htab->sgot->contents + off); - - if (info->shared) + relocation += rel->r_addend; + if (tls_type != 0) { - Elf_Internal_Rela outrel; - bfd_byte *loc; - - /* We need to generate a R_PPC64_RELATIVE reloc - for the dynamic linker. */ - outrel.r_offset = (htab->sgot->output_section->vma - + htab->sgot->output_offset - + off); - outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); - outrel.r_addend = relocation; - loc = htab->srelgot->contents; - loc += (htab->srelgot->reloc_count++ - * sizeof (Elf64_External_Rela)); - bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc); + relocation -= htab->tls_sec->vma + DTP_OFFSET; + if ((tls_type & TLS_TPREL) != 0) + relocation += DTP_OFFSET - TP_OFFSET; } - local_got_offsets[r_symndx] |= 1; + if ((tls_type & TLS_GD) != 0) + { + bfd_put_64 (output_bfd, relocation, + htab->sgot->contents + off + 8); + relocation = 1; + } + else if (tls_type == (TLS_TLS | TLS_LD)) + relocation = 1; + bfd_put_64 (output_bfd, relocation, + htab->sgot->contents + off); } } @@ -5673,7 +7696,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, relocation = htab->sgot->output_offset + off; /* TOC base (r2) is TOC start plus 0x8000. */ - addend -= TOC_BASE_OFF; + addend = - TOC_BASE_OFF; } break; @@ -5690,19 +7713,23 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, if (h == NULL) break; - if (h->plt.offset == (bfd_vma) -1 - || htab->splt == NULL) + /* It's possible that we didn't make a PLT entry for this + symbol. This happens when statically linking PIC code, + or when using -Bsymbolic. Go find a match if there is a + PLT entry. */ + if (htab->splt != NULL) { - /* We didn't make a PLT entry for this symbol. This - happens when statically linking PIC code, or when - using -Bsymbolic. */ - break; + struct plt_entry *ent; + for (ent = h->plt.plist; ent != NULL; ent = ent->next) + if (ent->addend == rel->r_addend + && ent->plt.offset != (bfd_vma) -1) + { + relocation = (htab->splt->output_section->vma + + htab->splt->output_offset + + ent->plt.offset); + unresolved_reloc = FALSE; + } } - - relocation = (htab->splt->output_section->vma - + htab->splt->output_offset - + h->plt.offset); - unresolved_reloc = FALSE; break; /* TOC16 relocs. We want the offset relative to the TOC base, @@ -5735,8 +7762,48 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_PPC64_REL24: break; + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + case R_PPC64_TPREL16_DS: + case R_PPC64_TPREL16_LO_DS: + case R_PPC64_TPREL16_HIGHER: + case R_PPC64_TPREL16_HIGHERA: + case R_PPC64_TPREL16_HIGHEST: + case R_PPC64_TPREL16_HIGHESTA: + addend -= htab->tls_sec->vma + TP_OFFSET; + if (info->shared) + /* The TPREL16 relocs shouldn't really be used in shared + libs as they will result in DT_TEXTREL being set, but + support them anyway. */ + goto dodyn; + break; + + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_HI: + case R_PPC64_DTPREL16_HA: + case R_PPC64_DTPREL16_DS: + case R_PPC64_DTPREL16_LO_DS: + case R_PPC64_DTPREL16_HIGHER: + case R_PPC64_DTPREL16_HIGHERA: + case R_PPC64_DTPREL16_HIGHEST: + case R_PPC64_DTPREL16_HIGHESTA: + addend -= htab->tls_sec->vma + DTP_OFFSET; + break; + + case R_PPC64_TPREL64: + addend -= htab->tls_sec->vma + TP_OFFSET; + goto dodyn; + + case R_PPC64_DTPREL64: + addend -= htab->tls_sec->vma + DTP_OFFSET; + /* Fall thru */ + /* Relocations that may need to be propagated if this is a dynamic object. */ + case R_PPC64_DTPMOD64: case R_PPC64_REL30: case R_PPC64_REL32: case R_PPC64_REL64: @@ -5762,6 +7829,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* r_symndx will be zero only for relocs against symbols from removed linkonce sections, or sections discarded by a linker script. */ + dodyn: if (r_symndx == 0) break; /* Fall thru. */ @@ -5774,22 +7842,19 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, break; if ((info->shared - && (IS_ABSOLUTE_RELOC (r_type) + && (MUST_BE_DYN_RELOC (r_type) || (h != NULL && h->dynindx != -1 && (! info->symbolic || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)))) - || (!info->shared + || (ELIMINATE_COPY_RELOCS + && !info->shared && h != NULL && h->dynindx != -1 && (h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0 - && (((h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_DYNAMIC) != 0 - && (h->elf_link_hash_flags - & ELF_LINK_HASH_DEF_REGULAR) == 0) - || h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined))) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)) { Elf_Internal_Rela outrel; bfd_boolean skip, relocate; @@ -5812,14 +7877,14 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, skip = TRUE, relocate = TRUE; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); - outrel.r_addend = addend; + outrel.r_addend = rel->r_addend; if (skip) memset (&outrel, 0, sizeof outrel); else if (h != NULL && h->dynindx != -1 && !is_opd - && (!IS_ABSOLUTE_RELOC (r_type) + && (!MUST_BE_DYN_RELOC (r_type) || !info->shared || !info->symbolic || (h->elf_link_hash_flags @@ -5831,6 +7896,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, or this is an opd section reloc which must point at a local function. */ outrel.r_addend += relocation; + /* ??? why? */ relocate = TRUE; if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC) { @@ -5902,7 +7968,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_PPC64_RELATIVE: /* We shouldn't ever see these dynamic relocs in relocatable files. */ - /* Fall thru */ + /* Fall through. */ case R_PPC64_PLTGOT16: case R_PPC64_PLTGOT16_DS: @@ -5938,6 +8004,20 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_PPC64_PLT16_HA: case R_PPC64_TOC16_HA: case R_PPC64_SECTOFF_HA: + case R_PPC64_TPREL16_HA: + case R_PPC64_DTPREL16_HA: + case R_PPC64_GOT_TLSGD16_HA: + case R_PPC64_GOT_TLSLD16_HA: + case R_PPC64_GOT_TPREL16_HA: + case R_PPC64_GOT_DTPREL16_HA: + case R_PPC64_TPREL16_HIGHER: + case R_PPC64_TPREL16_HIGHERA: + case R_PPC64_TPREL16_HIGHEST: + case R_PPC64_TPREL16_HIGHESTA: + case R_PPC64_DTPREL16_HIGHER: + case R_PPC64_DTPREL16_HIGHERA: + case R_PPC64_DTPREL16_HIGHEST: + case R_PPC64_DTPREL16_HIGHESTA: /* It's just possible that this symbol is a weak symbol that's not actually defined anywhere. In that case, 'sec' would be NULL, and we should leave the symbol @@ -5958,6 +8038,14 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, case R_PPC64_TOC16_LO_DS: case R_PPC64_PLTGOT16_DS: case R_PPC64_PLTGOT16_LO_DS: + case R_PPC64_GOT_TPREL16_DS: + case R_PPC64_GOT_TPREL16_LO_DS: + case R_PPC64_GOT_DTPREL16_DS: + case R_PPC64_GOT_DTPREL16_LO_DS: + case R_PPC64_TPREL16_DS: + case R_PPC64_TPREL16_LO_DS: + case R_PPC64_DTPREL16_DS: + case R_PPC64_DTPREL16_LO_DS: if (((relocation + addend) & 3) != 0) { (*_bfd_error_handler) @@ -5982,7 +8070,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, branch_check: /* If the branch is out of reach, then redirect the call to the local stub for this function. */ - from = (offset + from = (rel->r_offset + input_section->output_offset + input_section->output_section->vma); if (relocation + addend - from + max_br_offset >= 2 * max_br_offset @@ -6019,17 +8107,20 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, input_bfd, input_section, contents, - offset, + rel->r_offset, relocation, addend); if (r != bfd_reloc_ok) { - const char *name; - - if (h != NULL) + if (sym_name == NULL) + sym_name = "(null)"; + if (r == bfd_reloc_overflow) { - if (h->root.type == bfd_link_hash_undefweak + if (warned) + continue; + if (h != NULL + && h->root.type == bfd_link_hash_undefweak && ppc64_elf_howto_table[(int) r_type]->pc_relative) { /* Assume this is a call protected by other code that @@ -6041,26 +8132,9 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, continue; } - name = h->root.root.string; - } - else - { - name = bfd_elf_string_from_elf_section (input_bfd, - symtab_hdr->sh_link, - sym->st_name); - if (name == NULL) - continue; - if (*name == '\0') - name = bfd_section_name (input_bfd, sec); - } - - if (r == bfd_reloc_overflow) - { - if (warned) - continue; if (!((*info->callbacks->reloc_overflow) - (info, name, ppc64_elf_howto_table[(int) r_type]->name, - rel->r_addend, input_bfd, input_section, offset))) + (info, sym_name, ppc64_elf_howto_table[(int) r_type]->name, + rel->r_addend, input_bfd, input_section, rel->r_offset))) return FALSE; } else @@ -6069,7 +8143,7 @@ ppc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, (_("%s(%s+0x%lx): reloc against `%s': error %d"), bfd_archive_filename (input_bfd), bfd_get_section_name (input_bfd, input_section), - (long) rel->r_offset, name, (int) r); + (long) rel->r_offset, sym_name, (int) r); ret = FALSE; } } @@ -6094,79 +8168,36 @@ ppc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) htab = ppc_hash_table (info); dynobj = htab->elf.dynobj; - if (h->plt.offset != (bfd_vma) -1 - && ((struct ppc_link_hash_entry *) h)->is_func_descriptor) - { - Elf_Internal_Rela rela; - bfd_byte *loc; - - /* This symbol has an entry in the procedure linkage table. Set - it up. */ - - if (htab->splt == NULL - || htab->srelplt == NULL - || htab->sglink == NULL) - abort (); - - /* Create a JMP_SLOT reloc to inform the dynamic linker to - fill in the PLT entry. */ - - rela.r_offset = (htab->splt->output_section->vma - + htab->splt->output_offset - + h->plt.offset); - rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); - rela.r_addend = 0; - - loc = htab->srelplt->contents; - loc += ((h->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE - * sizeof (Elf64_External_Rela)); - bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); - } - - if (h->got.offset != (bfd_vma) -1) + if (((struct ppc_link_hash_entry *) h)->is_func_descriptor) { + struct plt_entry *ent; Elf_Internal_Rela rela; bfd_byte *loc; - /* This symbol has an entry in the global offset table. Set it - up. */ - - if (htab->sgot == NULL || htab->srelgot == NULL) - abort (); + for (ent = h->plt.plist; ent != NULL; ent = ent->next) + if (ent->plt.offset != (bfd_vma) -1) + { + /* This symbol has an entry in the procedure linkage + table. Set it up. */ - rela.r_offset = (htab->sgot->output_section->vma - + htab->sgot->output_offset - + (h->got.offset &~ (bfd_vma) 1)); - - /* If this is a static link, or it is a -Bsymbolic link and the - symbol is defined locally or was forced to be local because - of a version file, we just want to emit a RELATIVE reloc. - The entry in the global offset table will already have been - initialized in the relocate_section function. */ - if (info->shared - && (info->symbolic - || h->dynindx == -1 - || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL)) - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)) - { - BFD_ASSERT((h->got.offset & 1) != 0); - rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE); - rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); - } - else - { - BFD_ASSERT ((h->got.offset & 1) == 0); - bfd_put_64 (output_bfd, (bfd_vma) 0, - htab->sgot->contents + h->got.offset); - rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_GLOB_DAT); - rela.r_addend = 0; - } + if (htab->splt == NULL + || htab->srelplt == NULL + || htab->sglink == NULL) + abort (); - loc = htab->srelgot->contents; - loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela); - bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); + /* Create a JMP_SLOT reloc to inform the dynamic linker to + fill in the PLT entry. */ + rela.r_offset = (htab->splt->output_section->vma + + htab->splt->output_offset + + ent->plt.offset); + rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT); + rela.r_addend = ent->addend; + + loc = htab->srelplt->contents; + loc += ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE + * sizeof (Elf64_External_Rela)); + bfd_elf64_swap_reloca_out (output_bfd, &rela, loc); + } } if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h index 3115ea5..4b80cc5 100644 --- a/bfd/elf64-ppc.h +++ b/bfd/elf64-ppc.h @@ -1,5 +1,5 @@ /* PowerPC64-specific support for 64-bit ELF. - Copyright 2002 Free Software Foundation, Inc. + Copyright 2002, 2003 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -21,6 +21,10 @@ bfd_boolean ppc64_elf_mark_entry_syms PARAMS ((struct bfd_link_info *)); bfd_boolean ppc64_elf_edit_opd PARAMS ((bfd *, struct bfd_link_info *)); +bfd_boolean ppc64_elf_tls_setup + PARAMS ((bfd *, struct bfd_link_info *)); +bfd_boolean ppc64_elf_tls_optimize + PARAMS ((bfd *, struct bfd_link_info *)); bfd_vma ppc64_elf_toc PARAMS ((bfd *)); int ppc64_elf_setup_section_lists diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c index 1c81edf..e3c7f22 100644 --- a/bfd/elf64-s390.c +++ b/bfd/elf64-s390.c @@ -1,5 +1,5 @@ /* IBM S/390-specific support for 64-bit ELF - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed Martin Schwidefsky (schwidefsky@de.ibm.com). This file is part of BFD, the Binary File Descriptor library. @@ -373,7 +373,7 @@ elf_s390_info_to_howto (abfd, cache_ptr, dst) /* A relocation function which doesn't do anything. */ static bfd_reloc_status_type s390_tls_reloc (abfd, reloc_entry, symbol, data, input_section, - output_bfd, error_message) + output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry; asymbol *symbol ATTRIBUTE_UNUSED; @@ -986,7 +986,7 @@ elf_s390_check_relocs (abfd, info, sec, relocs) /* Fall through */ case R_390_GOT12: - case R_390_GOT16: + case R_390_GOT16: case R_390_GOT32: case R_390_GOT64: case R_390_GOTENT: @@ -1292,9 +1292,6 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - int r_type; - struct elf_link_hash_entry *h; elf_section_data (sec)->local_dynrel = NULL; @@ -1305,16 +1302,31 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; + r_symndx = ELF64_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf_s390_link_hash_entry *eh; + struct elf_s390_dyn_relocs **pp; + struct elf_s390_dyn_relocs *p; - if (r_symndx < symtab_hdr->sh_info) - h = NULL; - else - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf_s390_link_hash_entry *) h; - r_type = elf_s390_tls_transition (info, - ELF64_R_TYPE (rel->r_info), - r_symndx >= symtab_hdr->sh_info); + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } + + r_type = ELF64_R_TYPE (rel->r_info); + r_type = elf_s390_tls_transition (info, r_type, h != NULL); switch (r_type) { case R_390_TLS_LDM64: @@ -1347,14 +1359,7 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) if (local_got_refcounts[r_symndx] > 0) local_got_refcounts[r_symndx] -= 1; } - if (r_type != R_390_TLS_IE64) - break; - /* Fall through */ - - case R_390_TLS_LE64: - if (!info->shared) - break; - /* Fall through */ + break; case R_390_8: case R_390_12: @@ -1366,33 +1371,9 @@ elf_s390_gc_sweep_hook (abfd, info, sec, relocs) case R_390_PC32: case R_390_PC32DBL: case R_390_PC64: - if (h != NULL) - { - struct elf_s390_link_hash_entry *eh; - struct elf_s390_dyn_relocs **pp; - struct elf_s390_dyn_relocs *p; - - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; - - eh = (struct elf_s390_link_hash_entry *) h; - - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF64_R_TYPE (rel->r_info) == R_390_PC16 - || ELF64_R_TYPE (rel->r_info) == R_390_PC16DBL - || ELF64_R_TYPE (rel->r_info) == R_390_PC32 - || ELF64_R_TYPE (rel->r_info) == R_390_PC32DBL - || ELF64_R_TYPE (rel->r_info) == R_390_PC64) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + if (info->shared) + break; + /* Fall through */ case R_390_PLT16DBL: case R_390_PLT32: @@ -2226,7 +2207,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; @@ -2266,14 +2246,14 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, Current offset - size first entry / entry size. */ plt_index = (h->plt.offset - PLT_FIRST_ENTRY_SIZE) / PLT_ENTRY_SIZE; - + /* Offset in GOT is PLT index plus GOT headers(3) times 4, addr & GOT addr. */ relocation = (plt_index + 3) * GOT_ENTRY_SIZE; unresolved_reloc = FALSE; if (r_type == R_390_GOTPLTENT) - relocation += htab->sgot->output_section->vma; + relocation += htab->sgot->output_section->vma; break; } /* Fall through. */ @@ -2371,12 +2351,10 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, relocation = htab->sgot->output_offset + off; - /* - * For @GOTENT the relocation is against the offset between - * the instruction and the symbols entry in the GOT and not - * between the start of the GOT and the symbols entry. We - * add the vma of the GOT to get the correct value. - */ + /* For @GOTENT the relocation is against the offset between + the instruction and the symbols entry in the GOT and not + between the start of the GOT and the symbols entry. We + add the vma of the GOT to get the correct value. */ if ( r_type == R_390_GOTENT || r_type == R_390_GOTPLTENT) relocation += htab->sgot->output_section->vma; @@ -2429,17 +2407,17 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, + htab->splt->output_offset + h->plt.offset); unresolved_reloc = FALSE; - break; + break; case R_390_PLTOFF16: case R_390_PLTOFF32: case R_390_PLTOFF64: - /* Relocation is to the entry for this symbol in the - procedure linkage table relative to the start of the GOT. */ + /* Relocation is to the entry for this symbol in the + procedure linkage table relative to the start of the GOT. */ /* For local symbols or if we didn't make a PLT entry for this symbol resolve the symbol directly. */ - if ( h == NULL + if ( h == NULL || h->plt.offset == (bfd_vma) -1 || htab->splt == NULL) { @@ -2447,9 +2425,9 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, break; } - relocation = (htab->splt->output_section->vma - + htab->splt->output_offset - + h->plt.offset + relocation = (htab->splt->output_section->vma + + htab->splt->output_offset + + h->plt.offset - htab->sgot->output_section->vma); unresolved_reloc = FALSE; break; @@ -2500,7 +2478,6 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - skip = FALSE; relocate = FALSE; @@ -2577,7 +2554,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela); bfd_elf64_swap_reloc_out (output_bfd, &outrel, loc); } - /* Fall through */ + /* Fall through. */ case R_390_TLS_GD64: case R_390_TLS_GOTIE64: @@ -2621,7 +2598,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -2756,7 +2733,7 @@ elf_s390_relocate_section (output_bfd, info, input_bfd, input_section, htab->tls_ldm_got.offset |= 1; } relocation = htab->sgot->output_offset + off; - unresolved_reloc = FALSE; + unresolved_reloc = FALSE; break; case R_390_TLS_LE64: @@ -3067,7 +3044,6 @@ elf_s390_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the global offset table. Set it up. */ - if (htab->sgot == NULL || htab->srelgot == NULL) abort (); @@ -3278,11 +3254,9 @@ elf_s390_finish_dynamic_sections (output_bfd, info) return TRUE; } -/* - * Why was the hash table entry size definition changed from - * ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and - * this is the only reason for the s390_elf64_size_info structure. - */ +/* Why was the hash table entry size definition changed from + ARCH_SIZE/8 to 4? This breaks the 64 bit dynamic linker and + this is the only reason for the s390_elf64_size_info structure. */ const struct elf_size_info s390_elf64_size_info = { @@ -3294,10 +3268,10 @@ const struct elf_size_info s390_elf64_size_info = sizeof (Elf64_External_Sym), sizeof (Elf64_External_Dyn), sizeof (Elf_External_Note), - 8, /* hash-table entry size */ - 1, /* internal relocations per external relocations */ - 64, /* arch_size */ - 8, /* file_align */ + 8, /* hash-table entry size. */ + 1, /* internal relocations per external relocations. */ + 64, /* arch_size. */ + 8, /* file_align. */ ELFCLASS64, EV_CURRENT, bfd_elf64_write_out_phdrs, bfd_elf64_write_shdrs_and_ehdr, diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index 7164be2..e4f04b5 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -2,21 +2,21 @@ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -1925,7 +1925,7 @@ struct sparc64_elf_section_data }; #define sec_do_relax(sec) \ - ((struct sparc64_elf_section_data *) (sec)->used_by_bfd)->do_relax + ((struct sparc64_elf_section_data *) elf_section_data (sec))->do_relax static bfd_boolean sparc64_elf_new_section_hook (abfd, sec) @@ -2067,7 +2067,6 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) ; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -2083,7 +2082,6 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, /* To avoid generating warning messages about truncated relocations, set the relocation's address to be the same as the start of this section. */ - if (input_section->output_section != NULL) relocation = input_section->output_section->vma; else @@ -2615,7 +2613,7 @@ sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, } } } - /* FALLTHROUGH */ + /* Fall through. */ default: do_default: @@ -2820,7 +2818,6 @@ sparc64_elf_finish_dynamic_symbol (output_bfd, info, h, sym) bfd_byte *loc; /* This symbols needs a copy reloc. Set it up. */ - BFD_ASSERT (h->dynindx != -1); s = bfd_get_section_by_name (h->root.u.def.section->owner, @@ -2923,10 +2920,8 @@ sparc64_elf_finish_dynamic_sections (output_bfd, info) /* Initialize the contents of the .plt section. */ if (splt->_raw_size > 0) - { - sparc64_elf_build_plt (output_bfd, splt->contents, - (int) (splt->_raw_size / PLT_ENTRY_SIZE)); - } + sparc64_elf_build_plt (output_bfd, splt->contents, + (int) (splt->_raw_size / PLT_ENTRY_SIZE)); elf_section_data (splt->output_section)->this_hdr.sh_entsize = PLT_ENTRY_SIZE; @@ -3137,14 +3132,14 @@ const struct elf_size_info sparc64_elf_size_info = sizeof (Elf64_External_Sym), sizeof (Elf64_External_Dyn), sizeof (Elf_External_Note), - 4, /* hash-table entry size */ - /* internal relocations per external relocations. + 4, /* hash-table entry size. */ + /* Internal relocations per external relocations. For link purposes we use just 1 internal per 1 external, for assembly and slurp symbol table we use 2. */ 1, - 64, /* arch_size */ - 8, /* file_align */ + 64, /* arch_size. */ + 8, /* file_align. */ ELFCLASS64, EV_CURRENT, bfd_elf64_write_out_phdrs, diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index a3c36ff..f13b4d2 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1,22 +1,22 @@ /* X86-64 specific support for 64-bit ELF - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Jan Hubicka <jh@suse.cz>. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" @@ -1091,9 +1091,6 @@ elf64_x86_64_gc_sweep_hook (abfd, info, sec, relocs) struct elf_link_hash_entry **sym_hashes; bfd_signed_vma *local_got_refcounts; const Elf_Internal_Rela *rel, *relend; - unsigned long r_symndx; - int r_type; - struct elf_link_hash_entry *h; elf_section_data (sec)->local_dynrel = NULL; @@ -1103,85 +1100,79 @@ elf64_x86_64_gc_sweep_hook (abfd, info, sec, relocs) relend = relocs + sec->reloc_count; for (rel = relocs; rel < relend; rel++) - switch ((r_type = elf64_x86_64_tls_transition (info, - ELF64_R_TYPE (rel->r_info), - ELF64_R_SYM (rel->r_info) - >= symtab_hdr->sh_info))) - { - case R_X86_64_TLSLD: - if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0) - elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1; - break; - - case R_X86_64_TLSGD: - case R_X86_64_GOTTPOFF: - case R_X86_64_GOT32: - case R_X86_64_GOTPCREL: - r_symndx = ELF64_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->got.refcount > 0) - h->got.refcount -= 1; - } - else if (local_got_refcounts != NULL) - { - if (local_got_refcounts[r_symndx] > 0) - local_got_refcounts[r_symndx] -= 1; - } - break; + { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h = NULL; - case R_X86_64_8: - case R_X86_64_16: - case R_X86_64_32: - case R_X86_64_64: - case R_X86_64_32S: - case R_X86_64_PC8: - case R_X86_64_PC16: - case R_X86_64_PC32: - r_symndx = ELF64_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - struct elf64_x86_64_link_hash_entry *eh; - struct elf64_x86_64_dyn_relocs **pp; - struct elf64_x86_64_dyn_relocs *p; + r_symndx = ELF64_R_SYM (rel->r_info); + if (r_symndx >= symtab_hdr->sh_info) + { + struct elf64_x86_64_link_hash_entry *eh; + struct elf64_x86_64_dyn_relocs **pp; + struct elf64_x86_64_dyn_relocs *p; - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; + eh = (struct elf64_x86_64_link_hash_entry *) h; - if (!info->shared && h->plt.refcount > 0) - h->plt.refcount -= 1; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) + if (p->sec == sec) + { + /* Everything must go for SEC. */ + *pp = p->next; + break; + } + } - eh = (struct elf64_x86_64_link_hash_entry *) h; + r_type = ELF64_R_TYPE (rel->r_info); + r_type = elf64_x86_64_tls_transition (info, r_type, h != NULL); + switch (r_type) + { + case R_X86_64_TLSLD: + if (elf64_x86_64_hash_table (info)->tls_ld_got.refcount > 0) + elf64_x86_64_hash_table (info)->tls_ld_got.refcount -= 1; + break; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next) - if (p->sec == sec) - { - if (ELF64_R_TYPE (rel->r_info) == R_X86_64_PC8 - || ELF64_R_TYPE (rel->r_info) == R_X86_64_PC16 - || ELF64_R_TYPE (rel->r_info) == R_X86_64_PC32) - p->pc_count -= 1; - p->count -= 1; - if (p->count == 0) - *pp = p->next; - break; - } - } - break; + case R_X86_64_TLSGD: + case R_X86_64_GOTTPOFF: + case R_X86_64_GOT32: + case R_X86_64_GOTPCREL: + if (h != NULL) + { + if (h->got.refcount > 0) + h->got.refcount -= 1; + } + else if (local_got_refcounts != NULL) + { + if (local_got_refcounts[r_symndx] > 0) + local_got_refcounts[r_symndx] -= 1; + } + break; + case R_X86_64_8: + case R_X86_64_16: + case R_X86_64_32: + case R_X86_64_64: + case R_X86_64_32S: + case R_X86_64_PC8: + case R_X86_64_PC16: + case R_X86_64_PC32: + if (info->shared) + break; + /* Fall thru */ - case R_X86_64_PLT32: - r_symndx = ELF64_R_SYM (rel->r_info); - if (r_symndx >= symtab_hdr->sh_info) - { - h = sym_hashes[r_symndx - symtab_hdr->sh_info]; - if (h->plt.refcount > 0) - h->plt.refcount -= 1; - } - break; + case R_X86_64_PLT32: + if (h != NULL) + { + if (h->plt.refcount > 0) + h->plt.refcount -= 1; + } + break; - default: - break; - } + default: + break; + } + } return TRUE; } @@ -1921,7 +1912,6 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) relocation = 0; @@ -2106,7 +2096,6 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ - skip = FALSE; relocate = FALSE; @@ -2330,7 +2319,7 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, if ((off & 1) != 0) off &= ~1; - else + else { Elf_Internal_Rela outrel; bfd_byte *loc; @@ -2408,12 +2397,12 @@ elf64_x86_64_relocate_section (output_bfd, info, input_bfd, input_section, addq foo@gottpoff(%rip), %rax */ BFD_ASSERT (rel->r_offset >= 4); for (i = 0; i < 4; i++) - BFD_ASSERT (bfd_get_8 (input_bfd, + BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 4 + i) == tlsgd[i]); BFD_ASSERT (rel->r_offset + 12 <= input_section->_raw_size); for (i = 0; i < 4; i++) - BFD_ASSERT (bfd_get_8 (input_bfd, + BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4 + i) == tlsgd[i+4]); BFD_ASSERT (rel + 1 < relend); @@ -2592,7 +2581,6 @@ elf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the procedure linkage table. Set it up. */ - if (h->dynindx == -1 || htab->splt == NULL || htab->sgotplt == NULL @@ -2671,7 +2659,6 @@ elf64_x86_64_finish_dynamic_symbol (output_bfd, info, h, sym) /* This symbol has an entry in the global offset table. Set it up. */ - if (htab->sgot == NULL || htab->srelgot == NULL) abort (); diff --git a/bfd/elfcore.h b/bfd/elfcore.h index 4f9fcf7..724d607 100644 --- a/bfd/elfcore.h +++ b/bfd/elfcore.h @@ -1,22 +1,22 @@ /* ELF core file support for BFD. - Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002 + Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ char* elf_core_file_failing_command (abfd) @@ -48,11 +48,11 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd) } /* See if the name in the corefile matches the executable name. */ - corename = elf_tdata (core_bfd)->core_program; if (corename != NULL) { const char* execname = strrchr (exec_bfd->filename, '/'); + execname = execname ? execname + 1 : exec_bfd->filename; if (strcmp(execname, corename) != 0) @@ -71,17 +71,15 @@ elf_core_file_matches_executable_p (core_bfd, exec_bfd) register set) and the floating point register set are stored in a segment of type PT_NOTE. We handcraft a couple of extra bfd sections that allow standard bfd access to the general registers (.reg) and the - floating point registers (.reg2). - - */ + floating point registers (.reg2). */ const bfd_target * elf_core_file_p (abfd) bfd *abfd; { - Elf_External_Ehdr x_ehdr; /* Elf file header, external form */ - Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ - Elf_Internal_Phdr *i_phdrp; /* Elf program header, internal form */ + Elf_External_Ehdr x_ehdr; /* Elf file header, external form. */ + Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */ + Elf_Internal_Phdr *i_phdrp; /* Elf program header, internal form. */ unsigned int phindex; struct elf_backend_data *ebd; struct bfd_preserve preserve; @@ -103,7 +101,7 @@ elf_core_file_p (abfd) if (! elf_file_p (&x_ehdr)) goto wrong; - /* FIXME: Check EI_VERSION here ! */ + /* FIXME: Check EI_VERSION here ! */ /* Check the address size ("class"). */ if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS) @@ -112,11 +110,11 @@ elf_core_file_p (abfd) /* Check the byteorder. */ switch (x_ehdr.e_ident[EI_DATA]) { - case ELFDATA2MSB: /* Big-endian */ + case ELFDATA2MSB: /* Big-endian. */ if (! bfd_big_endian (abfd)) goto wrong; break; - case ELFDATA2LSB: /* Little-endian */ + case ELFDATA2LSB: /* Little-endian. */ if (! bfd_little_endian (abfd)) goto wrong; break; @@ -168,7 +166,11 @@ elf_core_file_p (abfd) if ((*target_ptr)->flavour != bfd_target_elf_flavour) continue; back = (struct elf_backend_data *) (*target_ptr)->backend_data; - if (back->elf_machine_code == i_ehdrp->e_machine) + if (back->elf_machine_code == i_ehdrp->e_machine + || (back->elf_machine_alt1 != 0 + && i_ehdrp->e_machine == back->elf_machine_alt1) + || (back->elf_machine_alt2 != 0 + && i_ehdrp->e_machine == back->elf_machine_alt2)) { /* target_ptr is an ELF backend which matches this object file, so reject the generic ELF target. */ @@ -203,6 +205,7 @@ elf_core_file_p (abfd) for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) { Elf_External_Phdr x_phdr; + if (bfd_bread ((PTR) &x_phdr, (bfd_size_type) sizeof (x_phdr), abfd) != sizeof (x_phdr)) goto fail; @@ -222,21 +225,17 @@ elf_core_file_p (abfd) /* Process each program header. */ for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex) - { - if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex)) - goto fail; - } + if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex)) + goto fail; /* Save the entry point from the ELF header. */ bfd_get_start_address (abfd) = i_ehdrp->e_entry; /* Let the backend double check the format and override global information. */ - if (ebd->elf_backend_object_p) - { - if (! (*ebd->elf_backend_object_p) (abfd)) - goto wrong; - } + if (ebd->elf_backend_object_p + && (! (*ebd->elf_backend_object_p) (abfd))) + goto wrong; bfd_preserve_finish (abfd, &preserve); return abfd->xvec; diff --git a/bfd/elflink.c b/bfd/elflink.c index 3170035..962c104 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,5 +1,5 @@ /* ELF linking support for BFD. - Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -31,14 +31,15 @@ _bfd_elf_create_got_section (abfd, info) struct bfd_link_info *info; { flagword flags; - register asection *s; + asection *s; struct elf_link_hash_entry *h; struct bfd_link_hash_entry *bh; struct elf_backend_data *bed = get_elf_backend_data (abfd); int ptralign; /* This function may be called more than once. */ - if (bfd_get_section_by_name (abfd, ".got") != NULL) + s = bfd_get_section_by_name (abfd, ".got"); + if (s != NULL && (s->flags & SEC_LINKER_CREATED) != 0) return TRUE; switch (bed->s->arch_size) @@ -111,7 +112,7 @@ _bfd_elf_create_dynamic_sections (abfd, info) struct bfd_link_info *info; { flagword flags, pltflags; - register asection *s; + asection *s; struct elf_backend_data *bed = get_elf_backend_data (abfd); int ptralign; @@ -272,7 +273,7 @@ _bfd_elf_link_record_dynamic_symbol (info, h) } /* We don't put any version information in the dynamic string - table. */ + table. */ name = h->root.root.string; p = strchr (name, ELF_VER_CHR); if (p == NULL) @@ -525,18 +526,19 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults) s->_raw_size = align_power (s->_raw_size, lsect->alignment); - /* Is there a hole we have to provide? If so check whether the segment is - too big already */ + /* Is there a hole we have to provide? If so check whether the + segment is too big already */ if (lsect->hole_size) { lsect->hole_offset = s->_raw_size; s->_raw_size += lsect->hole_size; if (lsect->hole_offset > lsect->max_hole_offset) { - (*_bfd_error_handler) (_("%s: Section %s is too large to add hole of %ld bytes"), - bfd_get_filename (abfd), - lsect->name, - (long) lsect->hole_size); + (*_bfd_error_handler) + (_("%s: Section %s is too large to add hole of %ld bytes"), + bfd_get_filename (abfd), + lsect->name, + (long) lsect->hole_size); bfd_set_error (bfd_error_bad_value); return (elf_linker_section_t *)0; diff --git a/bfd/elflink.h b/bfd/elflink.h index 060b129..7d2d2e2 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -1,22 +1,22 @@ /* ELF linker support. - Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 + Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ELF linker code. */ @@ -1168,6 +1168,8 @@ elf_link_add_object_symbols (abfd, info) Elf_External_Versym *extversym = NULL; Elf_External_Versym *ever; struct elf_link_hash_entry *weaks; + struct elf_link_hash_entry **nondeflt_vers = NULL; + bfd_size_type nondeflt_vers_cnt = 0; Elf_Internal_Sym *isymbuf = NULL; Elf_Internal_Sym *isym; Elf_Internal_Sym *isymend; @@ -1304,7 +1306,7 @@ elf_link_add_object_symbols (abfd, info) Test for --just-symbols by looking at info set up by _bfd_elf_link_just_syms. */ if ((s = abfd->sections) != NULL - && elf_section_data (s)->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) + && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) goto error_return; /* Find the name to use in a DT_NEEDED entry that refers to this @@ -1997,6 +1999,23 @@ elf_link_add_object_symbols (abfd, info) override, dt_needed)) goto error_free_vers; + if (definition && (abfd->flags & DYNAMIC) == 0) + { + char *p = strchr (name, ELF_VER_CHR); + if (p != NULL && p[1] != ELF_VER_CHR) + { + /* Queue non-default versions so that .symver x, x@FOO + aliases can be checked. */ + if (! nondeflt_vers) + { + amt = (isymend - isym + 1) + * sizeof (struct elf_link_hash_entry *); + nondeflt_vers = bfd_malloc (amt); + } + nondeflt_vers [nondeflt_vers_cnt++] = h; + } + } + if (dynsym && h->dynindx == -1) { if (! _bfd_elf_link_record_dynamic_symbol (info, h)) @@ -2071,6 +2090,55 @@ elf_link_add_object_symbols (abfd, info) } } + /* Now that all the symbols from this input file are created, handle + .symver foo, foo@BAR such that any relocs against foo become foo@BAR. */ + if (nondeflt_vers != NULL) + { + bfd_size_type cnt, symidx; + + for (cnt = 0; cnt < nondeflt_vers_cnt; ++cnt) + { + struct elf_link_hash_entry *h = nondeflt_vers[cnt], *hi; + char *shortname, *p; + + p = strchr (h->root.root.string, ELF_VER_CHR); + if (p == NULL + || (h->root.type != bfd_link_hash_defined + && h->root.type != bfd_link_hash_defweak)) + continue; + + amt = p - h->root.root.string; + shortname = bfd_malloc (amt + 1); + memcpy (shortname, h->root.root.string, amt); + shortname[amt] = '\0'; + + hi = (struct elf_link_hash_entry *) + bfd_link_hash_lookup (info->hash, shortname, + FALSE, FALSE, FALSE); + if (hi != NULL + && hi->root.type == h->root.type + && hi->root.u.def.value == h->root.u.def.value + && hi->root.u.def.section == h->root.u.def.section) + { + (*bed->elf_backend_hide_symbol) (info, hi, TRUE); + hi->root.type = bfd_link_hash_indirect; + hi->root.u.i.link = (struct bfd_link_hash_entry *) h; + (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi); + sym_hash = elf_sym_hashes (abfd); + if (sym_hash) + for (symidx = 0; symidx < extsymcount; ++symidx) + if (sym_hash[symidx] == hi) + { + sym_hash[symidx] = h; + break; + } + } + free (shortname); + } + free (nondeflt_vers); + nondeflt_vers = NULL; + } + if (extversym != NULL) { free (extversym); @@ -2234,7 +2302,7 @@ elf_link_add_object_symbols (abfd, info) &secdata->sec_info)) goto error_return; if (secdata->sec_info) - secdata->sec_info_type = ELF_INFO_TYPE_STABS; + stab->sec_info_type = ELF_INFO_TYPE_STABS; } } } @@ -2256,7 +2324,7 @@ elf_link_add_object_symbols (abfd, info) s, &secdata->sec_info)) goto error_return; else if (secdata->sec_info) - secdata->sec_info_type = ELF_INFO_TYPE_MERGE; + s->sec_info_type = ELF_INFO_TYPE_MERGE; } } @@ -2277,6 +2345,8 @@ elf_link_add_object_symbols (abfd, info) return TRUE; error_free_vers: + if (nondeflt_vers != NULL) + free (nondeflt_vers); if (extversym != NULL) free (extversym); error_free_sym: @@ -2509,7 +2579,10 @@ elf_link_read_relocs_from_section (abfd, shdr, external_relocs, else if (shdr->sh_entsize == sizeof (Elf_External_Rela)) swap_in = bed->s->swap_reloca_in; else - abort (); + { + bfd_set_error (bfd_error_wrong_format); + return FALSE; + } erela = external_relocs; erelaend = erela + NUM_SHDR_ENTRIES (shdr) * shdr->sh_entsize; @@ -2902,7 +2975,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, /* Any syms created from now on start with -1 in got.refcount/offset and plt.refcount/offset. */ - elf_hash_table (info)->init_refcount = -1; + elf_hash_table (info)->init_refcount = elf_hash_table (info)->init_offset; /* The backend may have to create some sections regardless of whether we're dynamic or not. */ @@ -3909,10 +3982,13 @@ elf_adjust_dynamic_symbol (h, data) bfd *dynobj; struct elf_backend_data *bed; + if (! is_elf_hash_table (eif->info)) + return FALSE; + if (h->root.type == bfd_link_hash_warning) { - h->plt.offset = (bfd_vma) -1; - h->got.offset = (bfd_vma) -1; + h->plt = elf_hash_table (eif->info)->init_offset; + h->got = elf_hash_table (eif->info)->init_offset; /* When warning symbols are created, they **replace** the "real" entry in the hash table, thus we never get to see the real @@ -3924,9 +4000,6 @@ elf_adjust_dynamic_symbol (h, data) if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (! is_elf_hash_table (eif->info)) - return FALSE; - /* Fix the symbol flags. */ if (! elf_fix_symbol_flags (h, eif)) return FALSE; @@ -3944,7 +4017,7 @@ elf_adjust_dynamic_symbol (h, data) || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0 && (h->weakdef == NULL || h->weakdef->dynindx == -1)))) { - h->plt.offset = (bfd_vma) -1; + h->plt = elf_hash_table (eif->info)->init_offset; return TRUE; } @@ -4878,18 +4951,24 @@ elf_bfd_final_link (abfd, info) merged = FALSE; for (o = abfd->sections; o != (asection *) NULL; o = o->next) { + struct bfd_elf_section_data *esdo = elf_section_data (o); o->reloc_count = 0; for (p = o->link_order_head; p != NULL; p = p->next) { + unsigned int reloc_count = 0; + struct bfd_elf_section_data *esdi = NULL; + unsigned int *rel_count1; + if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) - ++o->reloc_count; + reloc_count = 1; else if (p->type == bfd_indirect_link_order) { asection *sec; sec = p->u.indirect.section; + esdi = elf_section_data (sec); /* Mark all sections which are to be included in the link. This will normally be every section. We need @@ -4901,7 +4980,7 @@ elf_bfd_final_link (abfd, info) merged = TRUE; if (info->relocateable || info->emitrelocations) - o->reloc_count += sec->reloc_count; + reloc_count = sec->reloc_count; else if (bed->elf_backend_count_relocs) { Elf_Internal_Rela * relocs; @@ -4910,8 +4989,7 @@ elf_bfd_final_link (abfd, info) (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, info->keep_memory)); - o->reloc_count - += (*bed->elf_backend_count_relocs) (sec, relocs); + reloc_count = (*bed->elf_backend_count_relocs) (sec, relocs); if (elf_section_data (o)->relocs != relocs) free (relocs); @@ -4954,6 +5032,56 @@ elf_bfd_final_link (abfd, info) } } } + + if (reloc_count == 0) + continue; + + o->reloc_count += reloc_count; + + /* MIPS may have a mix of REL and RELA relocs on sections. + To support this curious ABI we keep reloc counts in + elf_section_data too. We must be careful to add the + relocations from the input section to the right output + count. FIXME: Get rid of one count. We have + o->reloc_count == esdo->rel_count + esdo->rel_count2. */ + rel_count1 = &esdo->rel_count; + if (esdi != NULL) + { + bfd_boolean same_size; + bfd_size_type entsize1; + + entsize1 = esdi->rel_hdr.sh_entsize; + BFD_ASSERT (entsize1 == sizeof (Elf_External_Rel) + || entsize1 == sizeof (Elf_External_Rela)); + same_size = (!o->use_rela_p + == (entsize1 == sizeof (Elf_External_Rel))); + + if (!same_size) + rel_count1 = &esdo->rel_count2; + + if (esdi->rel_hdr2 != NULL) + { + bfd_size_type entsize2 = esdi->rel_hdr2->sh_entsize; + unsigned int alt_count; + unsigned int *rel_count2; + + BFD_ASSERT (entsize2 != entsize1 + && (entsize2 == sizeof (Elf_External_Rel) + || entsize2 == sizeof (Elf_External_Rela))); + + rel_count2 = &esdo->rel_count2; + if (!same_size) + rel_count2 = &esdo->rel_count; + + /* The following is probably too simplistic if the + backend counts output relocs unusually. */ + BFD_ASSERT (bed->elf_backend_count_relocs == NULL); + alt_count = NUM_SHDR_ENTRIES (esdi->rel_hdr2); + *rel_count2 += alt_count; + reloc_count -= alt_count; + } + } + *rel_count1 += reloc_count; } if (o->reloc_count > 0) @@ -4987,63 +5115,6 @@ elf_bfd_final_link (abfd, info) if (! _bfd_elf_compute_section_file_positions (abfd, info)) goto error_return; - /* Figure out how many relocations we will have in each section. - Just using RELOC_COUNT isn't good enough since that doesn't - maintain a separate value for REL vs. RELA relocations. */ - if (emit_relocs) - for (sub = info->input_bfds; sub != NULL; sub = sub->link_next) - for (o = sub->sections; o != NULL; o = o->next) - { - asection *output_section; - - if (! o->linker_mark) - { - /* This section was omitted from the link. */ - continue; - } - - output_section = o->output_section; - - if (output_section != NULL - && (o->flags & SEC_RELOC) != 0) - { - struct bfd_elf_section_data *esdi - = elf_section_data (o); - struct bfd_elf_section_data *esdo - = elf_section_data (output_section); - unsigned int *rel_count; - unsigned int *rel_count2; - bfd_size_type entsize; - bfd_size_type entsize2; - - /* We must be careful to add the relocations from the - input section to the right output count. */ - entsize = esdi->rel_hdr.sh_entsize; - entsize2 = esdi->rel_hdr2 ? esdi->rel_hdr2->sh_entsize : 0; - BFD_ASSERT ((entsize == sizeof (Elf_External_Rel) - || entsize == sizeof (Elf_External_Rela)) - && entsize2 != entsize - && (entsize2 == 0 - || entsize2 == sizeof (Elf_External_Rel) - || entsize2 == sizeof (Elf_External_Rela))); - if (entsize == esdo->rel_hdr.sh_entsize) - { - rel_count = &esdo->rel_count; - rel_count2 = &esdo->rel_count2; - } - else - { - rel_count = &esdo->rel_count2; - rel_count2 = &esdo->rel_count; - } - - *rel_count += NUM_SHDR_ENTRIES (& esdi->rel_hdr); - if (esdi->rel_hdr2) - *rel_count2 += NUM_SHDR_ENTRIES (esdi->rel_hdr2); - output_section->flags |= SEC_RELOC; - } - } - /* That created the reloc sections. Set their sizes, and assign them file positions, and allocate some buffers. */ for (o = abfd->sections; o != NULL; o = o->next) @@ -5916,7 +5987,7 @@ elf_link_sec_merge_syms (h, data) if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && ((sec = h->root.u.def.section)->flags & SEC_MERGE) - && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE) + && sec->sec_info_type == ELF_INFO_TYPE_MERGE) { bfd *output_bfd = (bfd *) data; @@ -6096,8 +6167,7 @@ elf_link_output_extsym (h, data) referenced by regular files, because we will already have issued warnings for them. */ if (! finfo->info->relocateable - && ! finfo->info->allow_shlib_undefined - && ! finfo->info->shared + && (! finfo->info->shared || ! finfo->info->allow_shlib_undefined) && h->root.type == bfd_link_hash_undefined && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0 @@ -6522,7 +6592,7 @@ elf_link_input_bfd (finfo, input_bfd) { isec = section_from_elf_index (input_bfd, isym->st_shndx); if (isec - && elf_section_data (isec)->sec_info_type == ELF_INFO_TYPE_MERGE + && isec->sec_info_type == ELF_INFO_TYPE_MERGE && ELF_ST_TYPE (isym->st_info) != STT_SECTION) isym->st_value = _bfd_merged_section_offset (output_bfd, &isec, @@ -7015,7 +7085,7 @@ elf_link_input_bfd (finfo, input_bfd) { /* Section written out. */ } - else switch (elf_section_data (o)->sec_info_type) + else switch (o->sec_info_type) { case ELF_INFO_TYPE_STABS: if (! (_bfd_write_section_stabs @@ -8268,7 +8338,7 @@ elf_bfd_discard_info (output_bfd, info) if (stab != NULL && (stab->_raw_size == 0 || bfd_is_abs_section (stab->output_section) - || elf_section_data (stab)->sec_info_type != ELF_INFO_TYPE_STABS)) + || stab->sec_info_type != ELF_INFO_TYPE_STABS)) stab = NULL; if (stab == NULL @@ -8374,7 +8444,7 @@ elf_section_ignore_discarded_relocs (sec) { struct elf_backend_data *bed; - switch (elf_section_data (sec)->sec_info_type) + switch (sec->sec_info_type) { case ELF_INFO_TYPE_STABS: case ELF_INFO_TYPE_EH_FRAME: diff --git a/bfd/elfn32-mips.c b/bfd/elfn32-mips.c index 00a0e88..b2d745b 100644 --- a/bfd/elfn32-mips.c +++ b/bfd/elfn32-mips.c @@ -275,9 +275,11 @@ static reloc_howto_type elf_mips_howto_table_rel[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -772,9 +774,11 @@ static reloc_howto_type elf_mips_howto_table_rela[] = 0x0000ffff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* 16 bit PC relative reference. */ + /* 16 bit PC relative reference. Note that the ABI document has a typo + and claims R_MIPS_PC16 to be not rightshifted, rendering it useless. + We do the right thing here. */ HOWTO (R_MIPS_PC16, /* type */ - 0, /* rightshift */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ TRUE, /* pc_relative */ @@ -1837,7 +1841,7 @@ static const struct elf_reloc_map mips_reloc_map[] = /* There is no BFD reloc for R_MIPS_REL32. */ { BFD_RELOC_CTOR, R_MIPS_32 }, { BFD_RELOC_64, R_MIPS_64 }, - { BFD_RELOC_16_PCREL, R_MIPS_PC16 }, + { BFD_RELOC_16_PCREL_S2, R_MIPS_PC16 }, { BFD_RELOC_HI16_S, R_MIPS_HI16 }, { BFD_RELOC_LO16, R_MIPS_LO16 }, { BFD_RELOC_GPREL16, R_MIPS_GPREL16 }, diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c index 7097de0..6678dd6 100644 --- a/bfd/elfxx-ia64.c +++ b/bfd/elfxx-ia64.c @@ -102,6 +102,7 @@ struct elfNN_ia64_dyn_sym_info /* TRUE for the different kinds of linker data we want created. */ unsigned want_got : 1; + unsigned want_gotx : 1; unsigned want_fptr : 1; unsigned want_ltoff_fptr : 1; unsigned want_plt : 1; @@ -154,6 +155,12 @@ struct elfNN_ia64_link_hash_table struct elfNN_ia64_local_hash_table loc_hash_table; }; +struct elfNN_ia64_allocate_data +{ + struct bfd_link_info *info; + bfd_size_type ofs; +}; + #define elfNN_ia64_hash_table(p) \ ((struct elfNN_ia64_link_hash_table *) ((p)->hash)) @@ -169,6 +176,8 @@ static void elfNN_ia64_info_to_howto static bfd_boolean elfNN_ia64_relax_section PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info, bfd_boolean *again)); +static void elfNN_ia64_relax_ldxmov + PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off)); static bfd_boolean is_unwind_section_name PARAMS ((bfd *abfd, const char *)); static bfd_boolean elfNN_ia64_section_from_shdr @@ -299,6 +308,8 @@ static bfd_vma elfNN_ia64_dtprel_base PARAMS ((struct bfd_link_info *info)); static int elfNN_ia64_unwind_entry_compare PARAMS ((const PTR, const PTR)); +static bfd_boolean elfNN_ia64_choose_gp + PARAMS ((bfd *abfd, struct bfd_link_info *info)); static bfd_boolean elfNN_ia64_final_link PARAMS ((bfd *abfd, struct bfd_link_info *info)); static bfd_boolean elfNN_ia64_relocate_section @@ -671,11 +682,7 @@ static const bfd_byte oor_ip[48] = }; #endif -/* These functions do relaxation for IA-64 ELF. - - This is primarily to support branches to targets out of range; - relaxation of R_IA64_LTOFF22X and R_IA64_LDXMOV is handled in - relocate_section directly. */ +/* These functions do relaxation for IA-64 ELF. */ static bfd_boolean elfNN_ia64_relax_section (abfd, sec, link_info, again) @@ -701,6 +708,8 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) struct one_fixup *fixups = NULL; bfd_boolean changed_contents = FALSE; bfd_boolean changed_relocs = FALSE; + bfd_boolean changed_got = FALSE; + bfd_vma gp = 0; /* Assume we're not going to change any sizes, and we'll only need one pass. */ @@ -728,24 +737,6 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) ia64_info = elfNN_ia64_hash_table (link_info); irelend = internal_relocs + sec->reloc_count; - for (irel = internal_relocs; irel < irelend; irel++) - { - unsigned long r_type = ELFNN_R_TYPE (irel->r_info); - if (r_type == R_IA64_PCREL21B - || r_type == R_IA64_PCREL21BI - || r_type == R_IA64_PCREL21M - || r_type == R_IA64_PCREL21F) - break; - } - - /* No branch-type relocations. */ - if (irel == irelend) - { - if (elf_section_data (sec)->relocs != internal_relocs) - free (internal_relocs); - return TRUE; - } - /* Get the section contents. */ if (elf_section_data (sec)->this_hdr.contents != NULL) contents = elf_section_data (sec)->this_hdr.contents; @@ -760,19 +751,33 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) goto error_return; } - for (; irel < irelend; irel++) + for (irel = internal_relocs; irel < irelend; irel++) { unsigned long r_type = ELFNN_R_TYPE (irel->r_info); bfd_vma symaddr, reladdr, trampoff, toff, roff; asection *tsec; struct one_fixup *f; bfd_size_type amt; + bfd_boolean is_branch; + struct elfNN_ia64_dyn_sym_info *dyn_i; - if (r_type != R_IA64_PCREL21B - && r_type != R_IA64_PCREL21BI - && r_type != R_IA64_PCREL21M - && r_type != R_IA64_PCREL21F) - continue; + switch (r_type) + { + case R_IA64_PCREL21B: + case R_IA64_PCREL21BI: + case R_IA64_PCREL21M: + case R_IA64_PCREL21F: + is_branch = TRUE; + break; + + case R_IA64_LTOFF22X: + case R_IA64_LDXMOV: + is_branch = FALSE; + break; + + default: + continue; + } /* Get the value of the symbol referred to by the reloc. */ if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info) @@ -805,12 +810,12 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) tsec = bfd_section_from_elf_index (abfd, isym->st_shndx); toff = isym->st_value; + dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE); } else { unsigned long indx; struct elf_link_hash_entry *h; - struct elfNN_ia64_dyn_sym_info *dyn_i; indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info; h = elf_sym_hashes (abfd)[indx]; @@ -824,7 +829,7 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) /* For branches to dynamic symbols, we're interested instead in a branch to the PLT entry. */ - if (dyn_i && dyn_i->want_plt2) + if (is_branch && dyn_i && dyn_i->want_plt2) { /* Internal branches shouldn't be sent to the PLT. Leave this for now and we'll give an error later. */ @@ -834,6 +839,11 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) tsec = ia64_info->plt_sec; toff = dyn_i->plt2_offset; } + + /* Can't do anything else with dynamic symbols. */ + else if (elfNN_ia64_dynamic_symbol_p (h, link_info)) + continue; + else { /* We can't do anthing with undefined symbols. */ @@ -852,103 +862,152 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) + irel->r_addend); roff = irel->r_offset; - reladdr = (sec->output_section->vma - + sec->output_offset - + roff) & (bfd_vma) -4; - - /* If the branch is in range, no need to do anything. */ - if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 - && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0) - continue; - /* If the branch and target are in the same section, you've - got one honking big section and we can't help you. You'll - get an error message later. */ - if (tsec == sec) - continue; + if (is_branch) + { + reladdr = (sec->output_section->vma + + sec->output_offset + + roff) & (bfd_vma) -4; - /* Look for an existing fixup to this address. */ - for (f = fixups; f ; f = f->next) - if (f->tsec == tsec && f->toff == toff) - break; + /* If the branch is in range, no need to do anything. */ + if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 + && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0) + continue; - if (f == NULL) - { - /* Two alternatives: If it's a branch to a PLT entry, we can - make a copy of the FULL_PLT entry. Otherwise, we'll have - to use a `brl' insn to get where we're going. */ + /* If the branch and target are in the same section, you've + got one honking big section and we can't help you. You'll + get an error message later. */ + if (tsec == sec) + continue; - size_t size; + /* Look for an existing fixup to this address. */ + for (f = fixups; f ; f = f->next) + if (f->tsec == tsec && f->toff == toff) + break; - if (tsec == ia64_info->plt_sec) - size = sizeof (plt_full_entry); - else + if (f == NULL) { + /* Two alternatives: If it's a branch to a PLT entry, we can + make a copy of the FULL_PLT entry. Otherwise, we'll have + to use a `brl' insn to get where we're going. */ + + size_t size; + + if (tsec == ia64_info->plt_sec) + size = sizeof (plt_full_entry); + else + { #ifdef USE_BRL - size = sizeof (oor_brl); + size = sizeof (oor_brl); #else - size = sizeof (oor_ip); + size = sizeof (oor_ip); #endif - } + } - /* Resize the current section to make room for the new branch. */ - trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16; - amt = trampoff + size; - contents = (bfd_byte *) bfd_realloc (contents, amt); - if (contents == NULL) - goto error_return; - sec->_cooked_size = amt; + /* Resize the current section to make room for the new branch. */ + trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16; + amt = trampoff + size; + contents = (bfd_byte *) bfd_realloc (contents, amt); + if (contents == NULL) + goto error_return; + sec->_cooked_size = amt; - if (tsec == ia64_info->plt_sec) - { - memcpy (contents + trampoff, plt_full_entry, size); + if (tsec == ia64_info->plt_sec) + { + memcpy (contents + trampoff, plt_full_entry, size); - /* Hijack the old relocation for use as the PLTOFF reloc. */ - irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), - R_IA64_PLTOFF22); - irel->r_offset = trampoff; - } - else - { + /* Hijack the old relocation for use as the PLTOFF reloc. */ + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_PLTOFF22); + irel->r_offset = trampoff; + } + else + { #ifdef USE_BRL - memcpy (contents + trampoff, oor_brl, size); - irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), - R_IA64_PCREL60B); - irel->r_offset = trampoff + 2; + memcpy (contents + trampoff, oor_brl, size); + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_PCREL60B); + irel->r_offset = trampoff + 2; #else - memcpy (contents + trampoff, oor_ip, size); - irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), - R_IA64_PCREL64I); - irel->r_addend -= 16; - irel->r_offset = trampoff + 2; + memcpy (contents + trampoff, oor_ip, size); + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_PCREL64I); + irel->r_addend -= 16; + irel->r_offset = trampoff + 2; #endif + } + + /* Record the fixup so we don't do it again this section. */ + f = (struct one_fixup *) + bfd_malloc ((bfd_size_type) sizeof (*f)); + f->next = fixups; + f->tsec = tsec; + f->toff = toff; + f->trampoff = trampoff; + fixups = f; } + else + { + /* Nop out the reloc, since we're finalizing things here. */ + irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); + } + + /* Fix up the existing branch to hit the trampoline. Hope like + hell this doesn't overflow too. */ + if (elfNN_ia64_install_value (abfd, contents + roff, + f->trampoff - (roff & (bfd_vma) -4), + r_type) != bfd_reloc_ok) + goto error_return; - /* Record the fixup so we don't do it again this section. */ - f = (struct one_fixup *) bfd_malloc ((bfd_size_type) sizeof (*f)); - f->next = fixups; - f->tsec = tsec; - f->toff = toff; - f->trampoff = trampoff; - fixups = f; + changed_contents = TRUE; + changed_relocs = TRUE; } else { - /* Nop out the reloc, since we're finalizing things here. */ - irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); - } + /* Fetch the gp. */ + if (gp == 0) + { + bfd *obfd = sec->output_section->owner; + gp = _bfd_get_gp_value (obfd); + if (gp == 0) + { + if (!elfNN_ia64_choose_gp (obfd, link_info)) + goto error_return; + gp = _bfd_get_gp_value (obfd); + } + } - /* Fix up the existing branch to hit the trampoline. Hope like - hell this doesn't overflow too. */ - if (elfNN_ia64_install_value (abfd, contents + roff, - f->trampoff - (roff & (bfd_vma) -4), - r_type) != bfd_reloc_ok) - goto error_return; + /* If the data is out of range, do nothing. */ + if ((bfd_signed_vma) (symaddr - gp) >= 0x200000 + ||(bfd_signed_vma) (symaddr - gp) < -0x200000) + continue; - changed_contents = TRUE; - changed_relocs = TRUE; + if (r_type == R_IA64_LTOFF22X) + { + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_IA64_GPREL22); + changed_relocs = TRUE; + if (dyn_i->want_gotx) + { + dyn_i->want_gotx = 0; + changed_got |= !dyn_i->want_got; + } + } + else + { + elfNN_ia64_relax_ldxmov (abfd, contents, roff); + irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); + changed_contents = TRUE; + changed_relocs = TRUE; + } + } } + /* ??? If we created fixups, this may push the code segment large + enough that the data segment moves, which will change the GP. + Reset the GP so that we re-calculate next round. We need to + do this at the _beginning_ of the next round; now will not do. */ + /* Clean up and go home. */ while (fixups) { @@ -989,6 +1048,21 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) elf_section_data (sec)->relocs = internal_relocs; } + if (changed_got) + { + struct elfNN_ia64_allocate_data data; + data.info = link_info; + data.ofs = 0; + + elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data); + elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data); + elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data); + ia64_info->got_sec->_raw_size = data.ofs; + ia64_info->got_sec->_cooked_size = data.ofs; + + /* ??? Resize .rela.got too. */ + } + *again = changed_contents || changed_relocs; return TRUE; @@ -1003,6 +1077,39 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again) free (internal_relocs); return FALSE; } + +static void +elfNN_ia64_relax_ldxmov (abfd, contents, off) + bfd *abfd; + bfd_byte *contents; + bfd_vma off; +{ + int shift, r1, r3; + bfd_vma dword, insn; + + switch ((int)off & 0x3) + { + case 0: shift = 5; break; + case 1: shift = 14; off += 3; break; + case 2: shift = 23; off += 6; break; + case 3: + abort (); + } + + dword = bfd_get_64 (abfd, contents + off); + insn = (dword >> shift) & 0x1ffffffffffLL; + + r1 = (insn >> 6) & 127; + r3 = (insn >> 20) & 127; + if (r1 == r3) + insn = 0x8000000; /* nop */ + else + insn = (insn & 0x7f01fff) | 0x10800000000LL; /* (qp) mov r1 = r3 */ + + dword &= ~(0x1ffffffffffLL << shift); + dword |= (insn << shift); + bfd_put_64 (abfd, dword, contents + off); +} /* Return TRUE if NAME is an unwind table section name. */ @@ -2125,15 +2232,16 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) { enum { NEED_GOT = 1, - NEED_FPTR = 2, - NEED_PLTOFF = 4, - NEED_MIN_PLT = 8, - NEED_FULL_PLT = 16, - NEED_DYNREL = 32, - NEED_LTOFF_FPTR = 64, - NEED_TPREL = 128, - NEED_DTPMOD = 256, - NEED_DTPREL = 512 + NEED_GOTX = 2, + NEED_FPTR = 4, + NEED_PLTOFF = 8, + NEED_MIN_PLT = 16, + NEED_FULL_PLT = 32, + NEED_DYNREL = 64, + NEED_LTOFF_FPTR = 128, + NEED_TPREL = 256, + NEED_DTPMOD = 512, + NEED_DTPREL = 1024 }; struct elf_link_hash_entry *h = NULL; @@ -2230,11 +2338,14 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) break; case R_IA64_LTOFF22: - case R_IA64_LTOFF22X: case R_IA64_LTOFF64I: need_entry = NEED_GOT; break; + case R_IA64_LTOFF22X: + need_entry = NEED_GOTX; + break; + case R_IA64_PLTOFF22: case R_IA64_PLTOFF64I: case R_IA64_PLTOFF64MSB: @@ -2316,7 +2427,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) dyn_i->h = h; /* Create what's needed. */ - if (need_entry & (NEED_GOT | NEED_TPREL | NEED_DTPMOD | NEED_DTPREL)) + if (need_entry & (NEED_GOT | NEED_GOTX | NEED_TPREL + | NEED_DTPMOD | NEED_DTPREL)) { if (!got) { @@ -2326,6 +2438,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) } if (need_entry & NEED_GOT) dyn_i->want_got = 1; + if (need_entry & NEED_GOTX) + dyn_i->want_gotx = 1; if (need_entry & NEED_TPREL) dyn_i->want_tprel = 1; if (need_entry & NEED_DTPMOD) @@ -2385,12 +2499,6 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs) return TRUE; } -struct elfNN_ia64_allocate_data -{ - struct bfd_link_info *info; - bfd_size_type ofs; -}; - /* For cleanliness, and potentially faster dynamic loading, allocate external GOT entries first. */ @@ -2401,7 +2509,7 @@ allocate_global_data_got (dyn_i, data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; - if (dyn_i->want_got + if ((dyn_i->want_got || dyn_i->want_gotx) && ! dyn_i->want_fptr && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info) || (elfNN_ia64_aix_vec (x->info->hash->creator) @@ -2473,7 +2581,7 @@ allocate_local_got (dyn_i, data) { struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data; - if (dyn_i->want_got + if ((dyn_i->want_got || dyn_i->want_gotx) && ! (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info) || elfNN_ia64_aix_vec (x->info->hash->creator))) { @@ -2699,7 +2807,7 @@ allocate_dynrel_entries (dyn_i, data) /* Take care of the GOT and PLT relocations. */ - if (((dynamic_symbol || shared) && dyn_i->want_got) + if (((dynamic_symbol || shared) && (dyn_i->want_got || dyn_i->want_gotx)) || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1)) ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela); if ((dynamic_symbol || shared) && dyn_i->want_tprel) @@ -3516,125 +3624,148 @@ elfNN_ia64_unwind_entry_compare (a, b) return (av < bv ? -1 : av > bv ? 1 : 0); } +/* Make sure we've got ourselves a nice fat __gp value. */ static bfd_boolean -elfNN_ia64_final_link (abfd, info) +elfNN_ia64_choose_gp (abfd, info) bfd *abfd; struct bfd_link_info *info; { + bfd_vma min_vma = (bfd_vma) -1, max_vma = 0; + bfd_vma min_short_vma = min_vma, max_short_vma = 0; + struct elf_link_hash_entry *gp; + bfd_vma gp_val; + asection *os; struct elfNN_ia64_link_hash_table *ia64_info; - asection *unwind_output_sec; ia64_info = elfNN_ia64_hash_table (info); - /* Make sure we've got ourselves a nice fat __gp value. */ - if (!info->relocateable) + /* Find the min and max vma of all sections marked short. Also collect + min and max vma of any type, for use in selecting a nice gp. */ + for (os = abfd->sections; os ; os = os->next) { - bfd_vma min_vma = (bfd_vma) -1, max_vma = 0; - bfd_vma min_short_vma = min_vma, max_short_vma = 0; - struct elf_link_hash_entry *gp; - bfd_vma gp_val; - asection *os; + bfd_vma lo, hi; + + if ((os->flags & SEC_ALLOC) == 0) + continue; + + lo = os->vma; + hi = os->vma + os->_raw_size; + if (hi < lo) + hi = (bfd_vma) -1; - /* Find the min and max vma of all sections marked short. Also - collect min and max vma of any type, for use in selecting a - nice gp. */ - for (os = abfd->sections; os ; os = os->next) + if (min_vma > lo) + min_vma = lo; + if (max_vma < hi) + max_vma = hi; + if (os->flags & SEC_SMALL_DATA) { - bfd_vma lo, hi; + if (min_short_vma > lo) + min_short_vma = lo; + if (max_short_vma < hi) + max_short_vma = hi; + } + } - if ((os->flags & SEC_ALLOC) == 0) - continue; + /* See if the user wants to force a value. */ + gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE, + FALSE, FALSE); - lo = os->vma; - hi = os->vma + os->_raw_size; - if (hi < lo) - hi = (bfd_vma) -1; + if (gp + && (gp->root.type == bfd_link_hash_defined + || gp->root.type == bfd_link_hash_defweak)) + { + asection *gp_sec = gp->root.u.def.section; + gp_val = (gp->root.u.def.value + + gp_sec->output_section->vma + + gp_sec->output_offset); + } + else + { + /* Pick a sensible value. */ - if (min_vma > lo) - min_vma = lo; - if (max_vma < hi) - max_vma = hi; - if (os->flags & SEC_SMALL_DATA) - { - if (min_short_vma > lo) - min_short_vma = lo; - if (max_short_vma < hi) - max_short_vma = hi; - } + asection *got_sec = ia64_info->got_sec; + + /* Start with just the address of the .got. */ + if (got_sec) + gp_val = got_sec->output_section->vma; + else if (max_short_vma != 0) + gp_val = min_short_vma; + else + gp_val = min_vma; + + /* If it is possible to address the entire image, but we + don't with the choice above, adjust. */ + if (max_vma - min_vma < 0x400000 + && max_vma - gp_val <= 0x200000 + && gp_val - min_vma > 0x200000) + gp_val = min_vma + 0x200000; + else if (max_short_vma != 0) + { + /* If we don't cover all the short data, adjust. */ + if (max_short_vma - gp_val >= 0x200000) + gp_val = min_short_vma + 0x200000; + + /* If we're addressing stuff past the end, adjust back. */ + if (gp_val > max_vma) + gp_val = max_vma - 0x200000 + 8; } + } - /* See if the user wants to force a value. */ - gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE, - FALSE, FALSE); + /* Validate whether all SHF_IA_64_SHORT sections are within + range of the chosen GP. */ - if (gp - && (gp->root.type == bfd_link_hash_defined - || gp->root.type == bfd_link_hash_defweak)) + if (max_short_vma != 0) + { + if (max_short_vma - min_short_vma >= 0x400000) { - asection *gp_sec = gp->root.u.def.section; - gp_val = (gp->root.u.def.value - + gp_sec->output_section->vma - + gp_sec->output_offset); + (*_bfd_error_handler) + (_("%s: short data segment overflowed (0x%lx >= 0x400000)"), + bfd_get_filename (abfd), + (unsigned long) (max_short_vma - min_short_vma)); + return FALSE; } - else + else if ((gp_val > min_short_vma + && gp_val - min_short_vma > 0x200000) + || (gp_val < max_short_vma + && max_short_vma - gp_val >= 0x200000)) { - /* Pick a sensible value. */ + (*_bfd_error_handler) + (_("%s: __gp does not cover short data segment"), + bfd_get_filename (abfd)); + return FALSE; + } + } - asection *got_sec = ia64_info->got_sec; + _bfd_set_gp_value (abfd, gp_val); - /* Start with just the address of the .got. */ - if (got_sec) - gp_val = got_sec->output_section->vma; - else if (max_short_vma != 0) - gp_val = min_short_vma; - else - gp_val = min_vma; - - /* If it is possible to address the entire image, but we - don't with the choice above, adjust. */ - if (max_vma - min_vma < 0x400000 - && max_vma - gp_val <= 0x200000 - && gp_val - min_vma > 0x200000) - gp_val = min_vma + 0x200000; - else if (max_short_vma != 0) - { - /* If we don't cover all the short data, adjust. */ - if (max_short_vma - gp_val >= 0x200000) - gp_val = min_short_vma + 0x200000; + return TRUE; +} - /* If we're addressing stuff past the end, adjust back. */ - if (gp_val > max_vma) - gp_val = max_vma - 0x200000 + 8; - } - } +static bfd_boolean +elfNN_ia64_final_link (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + struct elfNN_ia64_link_hash_table *ia64_info; + asection *unwind_output_sec; - /* Validate whether all SHF_IA_64_SHORT sections are within - range of the chosen GP. */ + ia64_info = elfNN_ia64_hash_table (info); + + /* Make sure we've got ourselves a nice fat __gp value. */ + if (!info->relocateable) + { + bfd_vma gp_val = _bfd_get_gp_value (abfd); + struct elf_link_hash_entry *gp; - if (max_short_vma != 0) + if (gp_val == 0) { - if (max_short_vma - min_short_vma >= 0x400000) - { - (*_bfd_error_handler) - (_("%s: short data segment overflowed (0x%lx >= 0x400000)"), - bfd_get_filename (abfd), - (unsigned long) (max_short_vma - min_short_vma)); - return FALSE; - } - else if ((gp_val > min_short_vma - && gp_val - min_short_vma > 0x200000) - || (gp_val < max_short_vma - && max_short_vma - gp_val >= 0x200000)) - { - (*_bfd_error_handler) - (_("%s: __gp does not cover short data segment"), - bfd_get_filename (abfd)); - return FALSE; - } + if (! elfNN_ia64_choose_gp (abfd, info)) + return FALSE; + gp_val = _bfd_get_gp_value (abfd); } - _bfd_set_gp_value (abfd, gp_val); - + gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE, + FALSE, FALSE); if (gp) { gp->root.type = bfd_link_hash_defined; @@ -3763,8 +3894,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel); if ((sym_sec->flags & SEC_MERGE) && ELF_ST_TYPE (sym->st_info) == STT_SECTION - && (elf_section_data (sym_sec)->sec_info_type - == ELF_INFO_TYPE_MERGE)) + && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE) { struct elfNN_ia64_local_hash_entry *loc_h; @@ -3829,7 +3959,6 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, else if (h->root.type == bfd_link_hash_undefweak) undef_weak_ref = TRUE; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) ; @@ -3927,7 +4056,7 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section, srel, rel->r_offset, dyn_r_type, dynindx, addend); } - /* FALLTHRU */ + /* Fall through. */ case R_IA64_LTV32MSB: case R_IA64_LTV32LSB: @@ -4537,7 +4666,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info) bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon); } - /* Initialize the PLT0 entry */ + /* Initialize the PLT0 entry. */ if (ia64_info->plt_sec) { bfd_byte *loc = ia64_info->plt_sec->contents; @@ -4556,7 +4685,7 @@ elfNN_ia64_finish_dynamic_sections (abfd, info) return TRUE; } -/* ELF file flag handling: */ +/* ELF file flag handling: */ /* Function to keep IA-64 specific file flags. */ static bfd_boolean diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 22cc8a2..6ca4f06 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -9,21 +9,21 @@ Traditional MIPS targets support added by Koundinya.K, Dansk Data Elektronik & Operations Research Group. <kk@ddeorg.soft.net> -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file handles functionality common to the different MIPS ABI's. */ @@ -148,7 +148,7 @@ struct _mips_elf_section_data }; #define mips_elf_section_data(sec) \ - ((struct _mips_elf_section_data *) (sec)->used_by_bfd) + ((struct _mips_elf_section_data *) elf_section_data (sec)) /* This structure is passed to mips_elf_sort_hash_table_f when sorting the dynamic symbols. */ @@ -359,17 +359,17 @@ typedef struct loader for use by the static exception system. */ typedef struct runtime_pdr { - bfd_vma adr; /* memory address of start of procedure */ - long regmask; /* save register mask */ - long regoffset; /* save register offset */ - long fregmask; /* save floating point register mask */ - long fregoffset; /* save floating point register offset */ - long frameoffset; /* frame size */ - short framereg; /* frame pointer register */ - short pcreg; /* offset or reg of return pc */ - long irpss; /* index into the runtime string table */ + bfd_vma adr; /* Memory address of start of procedure. */ + long regmask; /* Save register mask. */ + long regoffset; /* Save register offset. */ + long fregmask; /* Save floating point register mask. */ + long fregoffset; /* Save floating point register offset. */ + long frameoffset; /* Frame size. */ + short framereg; /* Frame pointer register. */ + short pcreg; /* Offset or reg of return pc. */ + long irpss; /* Index into the runtime string table. */ long reserved; - struct exception_info *exception_info;/* pointer to exception array */ + struct exception_info *exception_info;/* Pointer to exception array. */ } RPDR, *pRPDR; #define cbRPDR sizeof (RPDR) #define rpdNil ((pRPDR) 0) @@ -496,7 +496,6 @@ static struct mips_got_info *mips_elf_got_for_ibfd static bfd *reldyn_sorting_bfd; /* Nonzero if ABFD is using the N32 ABI. */ - #define ABI_N32_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0) @@ -2130,7 +2129,7 @@ mips_elf_bfd2got_entry_eq (entry1, entry2) return e1->bfd == e2->bfd; } -/* In a multi-got link, determine the GOT to be used for IBDF. G must +/* In a multi-got link, determine the GOT to be used for IBFD. G must be the master GOT data. */ static struct mips_got_info * @@ -3095,7 +3094,6 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info, addresses. */ symbol = 0; else if (info->shared - && (!info->symbolic || info->allow_shlib_undefined) && !info->no_undefined && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) symbol = 0; @@ -3317,12 +3315,6 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info, value &= howto->dst_mask; break; - case R_MIPS_GNU_REL16_S2: - value = symbol + mips_elf_sign_extend (addend << 2, 18) - p; - overflowed_p = mips_elf_overflow_p (value, 18); - value = (value >> 2) & howto->dst_mask; - break; - case R_MIPS_GNU_REL_HI16: /* Instead of subtracting 'p' here, we should be subtracting the equivalent value for the LO part of the reloc, since the value @@ -3451,8 +3443,10 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info, break; case R_MIPS_PC16: - value = mips_elf_sign_extend (addend, 16) + symbol - p; - overflowed_p = mips_elf_overflow_p (value, 16); + case R_MIPS_GNU_REL16_S2: + value = mips_elf_sign_extend (addend << 2, 18) + symbol - p; + overflowed_p = mips_elf_overflow_p (value, 18); + value = (value >> 2) & howto->dst_mask; break; case R_MIPS_GOT_HI16: @@ -4600,8 +4594,7 @@ _bfd_mips_elf_fake_sections (abfd, hdr, sec) esd->rel_hdr2 = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt); if (!esd->rel_hdr2) return FALSE; - _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, - !elf_section_data (sec)->use_rela_p); + _bfd_elf_init_reloc_shdr (abfd, esd->rel_hdr2, sec, !sec->use_rela_p); } return TRUE; diff --git a/bfd/format.c b/bfd/format.c index 8cc7b7a..9af6efc 100644 --- a/bfd/format.c +++ b/bfd/format.c @@ -1,23 +1,23 @@ /* Generic BFD support for file formats. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002 + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SECTION @@ -52,7 +52,7 @@ FUNCTION bfd_check_format SYNOPSIS - bfd_boolean bfd_check_format(bfd *abfd, bfd_format format); + bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); DESCRIPTION Verify if the file attached to the BFD @var{abfd} is compatible @@ -98,7 +98,8 @@ FUNCTION bfd_check_format_matches SYNOPSIS - bfd_boolean bfd_check_format_matches(bfd *abfd, bfd_format format, char ***matching); + bfd_boolean bfd_check_format_matches (bfd *abfd, bfd_format format, + char ***matching); DESCRIPTION Like <<bfd_check_format>>, except when it returns FALSE with @@ -210,7 +211,7 @@ bfd_check_format_matches (abfd, format, matching) if (*target == &binary_vec) continue; - abfd->xvec = *target; /* Change BFD's target temporarily */ + abfd->xvec = *target; /* Change BFD's target temporarily. */ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) return FALSE; @@ -224,7 +225,8 @@ bfd_check_format_matches (abfd, format, matching) temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); if (temp) - { /* This format checks out as ok! */ + { + /* This format checks out as ok! */ right_targ = temp; /* If this is the default target, accept it, even if other @@ -279,6 +281,7 @@ bfd_check_format_matches (abfd, format, matching) { /* Try partial matches. */ right_targ = ar_right_targ; + if (right_targ == bfd_default_vector[0]) { match_count = 1; @@ -286,12 +289,11 @@ bfd_check_format_matches (abfd, format, matching) else { match_count = ar_match_index - _bfd_target_vector_entries; + if (matching && match_count > 1) - { - memcpy (matching_vector, - matching_vector + _bfd_target_vector_entries, - sizeof (*matching_vector) * match_count); - } + memcpy (matching_vector, + matching_vector + _bfd_target_vector_entries, + sizeof (*matching_vector) * match_count); } } @@ -361,7 +363,7 @@ FUNCTION bfd_set_format SYNOPSIS - bfd_boolean bfd_set_format(bfd *abfd, bfd_format format); + bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); DESCRIPTION This function sets the file format of the BFD @var{abfd} to the @@ -402,7 +404,7 @@ FUNCTION bfd_format_string SYNOPSIS - const char *bfd_format_string(bfd_format format); + const char *bfd_format_string (bfd_format format); DESCRIPTION Return a pointer to a const string @@ -1,6 +1,6 @@ /* BFD back-end for ieee-695 objects. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support. @@ -2074,7 +2074,7 @@ ieee_slurp_section_data (abfd) for (s = abfd->sections; s != (asection *) NULL; s = s->next) { - ieee_per_section_type *per = (ieee_per_section_type *) s->used_by_bfd; + ieee_per_section_type *per = ieee_per_section (s); if ((s->flags & SEC_DEBUGGING) != 0) continue; per->data = (bfd_byte *) bfd_alloc (ieee->h.abfd, s->_raw_size); @@ -2098,7 +2098,7 @@ ieee_slurp_section_data (abfd) section_number = must_parse_int (&(ieee->h)); s = ieee->section_table[section_number]; s->flags |= SEC_LOAD | SEC_HAS_CONTENTS; - current_map = (ieee_per_section_type *) s->used_by_bfd; + current_map = ieee_per_section (s); location_ptr = current_map->data - s->vma; /* The document I have says that Microtec's compilers reset */ /* this after a sec section, even though the standard says not */ @@ -2192,8 +2192,8 @@ ieee_new_section_hook (abfd, newsect) bfd *abfd; asection *newsect; { - newsect->used_by_bfd = (PTR) - bfd_alloc (abfd, (bfd_size_type) sizeof (ieee_per_section_type)); + newsect->used_by_bfd + = (PTR) bfd_alloc (abfd, (bfd_size_type) sizeof (ieee_per_section_type)); if (!newsect->used_by_bfd) return FALSE; ieee_per_section (newsect)->data = (bfd_byte *) NULL; @@ -2221,7 +2221,7 @@ ieee_get_section_contents (abfd, section, location, offset, count) file_ptr offset; bfd_size_type count; { - ieee_per_section_type *p = (ieee_per_section_type *) section->used_by_bfd; + ieee_per_section_type *p = ieee_per_section (section); if ((section->flags & SEC_DEBUGGING) != 0) return _bfd_generic_get_section_contents (abfd, section, location, offset, count); @@ -2237,7 +2237,6 @@ ieee_canonicalize_reloc (abfd, section, relptr, symbols) arelent **relptr; asymbol **symbols; { -/* ieee_per_section_type *p = (ieee_per_section_type *) section->used_by_bfd;*/ ieee_reloc_type *src = (ieee_reloc_type *) (section->relocation); ieee_data_type *ieee = IEEE_DATA (abfd); diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 4ee9d87..14978ba 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -850,6 +850,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_LO16", "BFD_RELOC_PCREL_HI16_S", "BFD_RELOC_PCREL_LO16", + "BFD_RELOC_MIPSEMB_16_PCREL_S2", "BFD_RELOC_MIPS_LITERAL", "BFD_RELOC_MIPS_GOT16", "BFD_RELOC_MIPS_CALL16", @@ -991,6 +992,46 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_PPC64_TOC16_LO_DS", "BFD_RELOC_PPC64_PLTGOT16_DS", "BFD_RELOC_PPC64_PLTGOT16_LO_DS", + "BFD_RELOC_PPC_TLS", + "BFD_RELOC_PPC_DTPMOD", + "BFD_RELOC_PPC_TPREL16", + "BFD_RELOC_PPC_TPREL16_LO", + "BFD_RELOC_PPC_TPREL16_HI", + "BFD_RELOC_PPC_TPREL16_HA", + "BFD_RELOC_PPC_TPREL", + "BFD_RELOC_PPC_DTPREL16", + "BFD_RELOC_PPC_DTPREL16_LO", + "BFD_RELOC_PPC_DTPREL16_HI", + "BFD_RELOC_PPC_DTPREL16_HA", + "BFD_RELOC_PPC_DTPREL", + "BFD_RELOC_PPC_GOT_TLSGD16", + "BFD_RELOC_PPC_GOT_TLSGD16_LO", + "BFD_RELOC_PPC_GOT_TLSGD16_HI", + "BFD_RELOC_PPC_GOT_TLSGD16_HA", + "BFD_RELOC_PPC_GOT_TLSLD16", + "BFD_RELOC_PPC_GOT_TLSLD16_LO", + "BFD_RELOC_PPC_GOT_TLSLD16_HI", + "BFD_RELOC_PPC_GOT_TLSLD16_HA", + "BFD_RELOC_PPC_GOT_TPREL16", + "BFD_RELOC_PPC_GOT_TPREL16_LO", + "BFD_RELOC_PPC_GOT_TPREL16_HI", + "BFD_RELOC_PPC_GOT_TPREL16_HA", + "BFD_RELOC_PPC_GOT_DTPREL16", + "BFD_RELOC_PPC_GOT_DTPREL16_LO", + "BFD_RELOC_PPC_GOT_DTPREL16_HI", + "BFD_RELOC_PPC_GOT_DTPREL16_HA", + "BFD_RELOC_PPC64_TPREL16_DS", + "BFD_RELOC_PPC64_TPREL16_LO_DS", + "BFD_RELOC_PPC64_TPREL16_HIGHER", + "BFD_RELOC_PPC64_TPREL16_HIGHERA", + "BFD_RELOC_PPC64_TPREL16_HIGHEST", + "BFD_RELOC_PPC64_TPREL16_HIGHESTA", + "BFD_RELOC_PPC64_DTPREL16_DS", + "BFD_RELOC_PPC64_DTPREL16_LO_DS", + "BFD_RELOC_PPC64_DTPREL16_HIGHER", + "BFD_RELOC_PPC64_DTPREL16_HIGHERA", + "BFD_RELOC_PPC64_DTPREL16_HIGHEST", + "BFD_RELOC_PPC64_DTPREL16_HIGHESTA", "BFD_RELOC_I370_D12", "BFD_RELOC_CTOR", "BFD_RELOC_ARM_PCREL_BRANCH", diff --git a/bfd/libcoff.h b/bfd/libcoff.h index c0279e5..1beec22 100644 --- a/bfd/libcoff.h +++ b/bfd/libcoff.h @@ -866,7 +866,8 @@ typedef struct #define bfd_coff_set_arch_mach_hook(abfd, filehdr)\ ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr)) #define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\ - ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr)) + ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook)\ + (abfd, filehdr, aouthdr)) #define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name, section, flags_ptr)\ ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook)\ @@ -891,7 +892,8 @@ typedef struct ((coff_backend_info (abfd)->_bfd_coff_print_aux)\ (abfd, file, base, symbol, aux, indaux)) -#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)\ +#define bfd_coff_reloc16_extra_cases(abfd, link_info, link_order,\ + reloc, data, src_ptr, dst_ptr)\ ((coff_backend_info (abfd)->_bfd_coff_reloc16_extra_cases)\ (abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)) @@ -919,7 +921,8 @@ typedef struct #define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\ ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\ (obfd, info, ibfd, sec, rel, adjustedp)) -#define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\ +#define bfd_coff_link_add_one_symbol(info, abfd, name, flags, section,\ + value, string, cp, coll, hashp)\ ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\ (info, abfd, name, flags, section, value, string, cp, coll, hashp)) @@ -1,5 +1,5 @@ /* BFD back-end for mmo objects (MMIX-specific object-format). - Copyright 2001, 2002 + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. Written by Hans-Peter Nilsson (hp@bitrange.com). Infrastructure and other bits originally copied from srec.c and @@ -335,6 +335,9 @@ struct mmo_section_data_struct mmo_data_list_type *tail; }; +#define mmo_section_data(sec) \ + ((struct mmo_section_data_struct *) (sec)->used_by_bfd) + /* These structures are used in bfd_map_over_sections constructs. */ /* Used when writing out sections; all but the register contents section @@ -1177,12 +1180,11 @@ mmo_get_spec_section (abfd, spec_data_number) } loc->next = NULL; - if (((struct mmo_section_data_struct *) (sec->used_by_bfd))->tail != NULL) - ((struct mmo_section_data_struct *) (sec->used_by_bfd))->tail->next - = loc; + if (mmo_section_data (sec)->tail != NULL) + mmo_section_data (sec)->tail->next = loc; else - ((struct mmo_section_data_struct *) (sec->used_by_bfd))->head = loc; - ((struct mmo_section_data_struct *) (sec->used_by_bfd))->tail = loc; + mmo_section_data (sec)->head = loc; + mmo_section_data (sec)->tail = loc; loc->where = section_vma; return sec; @@ -1517,8 +1519,7 @@ mmo_get_loc (sec, vma, size) int size; { bfd_size_type allocated_size; - struct mmo_section_data_struct *sdatap - = (struct mmo_section_data_struct *) sec->used_by_bfd; + struct mmo_section_data_struct *sdatap = mmo_section_data (sec); struct mmo_data_list_struct *datap = sdatap->head; struct mmo_data_list_struct *entry; @@ -2463,15 +2464,9 @@ mmo_internal_write_section (abfd, sec) if (strcmp (sec->name, MMO_TEXT_SECTION_NAME) == 0) /* FIXME: Output source file name and line number. */ - return - mmo_write_loc_chunk_list (abfd, - ((struct mmo_section_data_struct *) - (sec->used_by_bfd))->head); + return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head); else if (strcmp (sec->name, MMO_DATA_SECTION_NAME) == 0) - return - mmo_write_loc_chunk_list (abfd, - ((struct mmo_section_data_struct *) - (sec->used_by_bfd))->head); + return mmo_write_loc_chunk_list (abfd, mmo_section_data (sec)->head); else if (strcmp (sec->name, MMIX_REG_CONTENTS_SECTION_NAME) == 0) /* Not handled here. */ { @@ -2486,9 +2481,7 @@ mmo_internal_write_section (abfd, sec) int n = atoi (sec->name + strlen (MMIX_OTHER_SPEC_SECTION_PREFIX)); mmo_write_tetra_raw (abfd, (LOP << 24) | (LOP_SPEC << 16) | n); return (! abfd->tdata.mmo_data->have_error - && mmo_write_chunk_list (abfd, - ((struct mmo_section_data_struct *) - (sec->used_by_bfd))->head)); + && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head)); } /* Ignore sections that are just allocated or empty; we write out _contents_ here. */ @@ -2605,16 +2598,11 @@ EXAMPLE /* Writing a LOP_LOC ends the LOP_SPEC data, and makes data actually loaded. */ if (bfd_get_section_flags (abfd, sec) & SEC_LOAD) - return - ! abfd->tdata.mmo_data->have_error - && mmo_write_loc_chunk_list (abfd, - ((struct mmo_section_data_struct *) - (sec->used_by_bfd))->head); - return - ! abfd->tdata.mmo_data->have_error - && mmo_write_chunk_list (abfd, - ((struct mmo_section_data_struct *) - (sec->used_by_bfd))->head); + return (! abfd->tdata.mmo_data->have_error + && mmo_write_loc_chunk_list (abfd, + mmo_section_data (sec)->head)); + return (! abfd->tdata.mmo_data->have_error + && mmo_write_chunk_list (abfd, mmo_section_data (sec)->head)); } return TRUE; } diff --git a/bfd/oasys.c b/bfd/oasys.c index 494e155..3c39386 100644 --- a/bfd/oasys.c +++ b/bfd/oasys.c @@ -1,6 +1,6 @@ /* BFD back-end for oasys objects. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2002 - Free Software Foundation, Inc. + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, + 2002, 2003 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>. This file is part of BFD, the Binary File Descriptor library. @@ -864,7 +864,7 @@ oasys_get_section_contents (abfd, section, location, offset, count) file_ptr offset; bfd_size_type count; { - oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd; + oasys_per_section_type *p = oasys_per_section (section); oasys_slurp_section_data (abfd); if (! p->initialized) { diff --git a/bfd/po/da.po b/bfd/po/da.po index 89ed7d0..cf0121a 100644 --- a/bfd/po/da.po +++ b/bfd/po/da.po @@ -1,12 +1,12 @@ # Danish messages for bfd. # Copyright (C) 2001, 2002 Free Software Foundation, Inc. -# Keld Simonsen <keld@dkuug.dk>, 2002 +# Keld Simonsen <keld@dkuug.dk>, 2002-2003 # msgid "" msgstr "" "Project-Id-Version: bfd 2.12.91\n" "POT-Creation-Date: 2002-07-23 15:55-0400\n" -"PO-Revision-Date: 2002-11-09 23:25+0100\n" +"PO-Revision-Date: 2003-03-01 23:25+0100\n" "Last-Translator: Keld Simonsen <keld@dkuug.dk>\n" "Language-Team: Danish <dansk@klid.dk>\n" "MIME-Version: 1.0\n" @@ -1179,14 +1179,14 @@ msgid "%s: error: unaligned relocation type %d at %08x reloc %08x\n" msgstr "%s: fejl: ujusteret relokeringstype %d på %08x relokering %08x\n" #: elf32-sh64.c:677 -#, fuzzy, c-format +#, c-format msgid "%s: could not write out added .cranges entries" -msgstr "%s: kunne ikke udskrive tilføjede .crangives-poster" +msgstr "%s: kunne ikke udskrive tilføjede .cranges-poster" #: elf32-sh64.c:739 -#, fuzzy, c-format +#, c-format msgid "%s: could not write out sorted .cranges entries" -msgstr "%s: kunne ikke udskrive sorterede crangives-poster" +msgstr "%s: kunne ikke udskrive sorterede cranges-poster" #: elf32-sparc.c:1535 elf64-sparc.c:2224 #, c-format @@ -1204,22 +1204,22 @@ msgid "%s: linking little endian files with big endian files" msgstr "%s: lænker little endian-filer med big endian-filer" #: elf32-v850.c:682 -#, fuzzy, c-format +#, c-format msgid "Variable `%s' cannot occupy in multiple small data regions" msgstr "Variabel \"%s\" kan ikke befinde sig i flere små dataområder" #: elf32-v850.c:685 -#, fuzzy, c-format +#, c-format msgid "Variable `%s' can only be in one of the small, zero, and tiny data regions" -msgstr "Variabel \"%s\" kan kun være i et af de små, tomme og bittesmå dataområder" +msgstr "Variabel \"%s\" kan kun være i ét af de små, tomme og bittesmå dataområder" #: elf32-v850.c:688 -#, fuzzy, c-format +#, c-format msgid "Variable `%s' cannot be in both small and zero data regions simultaneously" msgstr "Variabel \"%s\" kan ikke være i både små og tomme dataområder samtidigt" #: elf32-v850.c:691 -#, fuzzy, c-format +#, c-format msgid "Variable `%s' cannot be in both small and tiny data regions simultaneously" msgstr "Variabel \"%s\" kan ikke være i både små og bittesmå dataområder samtidigt" diff --git a/bfd/reloc.c b/bfd/reloc.c index 147b746..45660c8 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -2080,7 +2080,10 @@ ENUM BFD_RELOC_PCREL_LO16 ENUMDOC Like BFD_RELOC_LO16, but PC relative. - +ENUM + BFD_RELOC_MIPSEMB_16_PCREL_S2 +ENUMDOC + Like BFD_RELOC_16_PCREL_S2, but for MIPS Embedded PIC. ENUM BFD_RELOC_MIPS_LITERAL ENUMDOC @@ -2150,7 +2153,6 @@ ENUMX ENUMDOC Fujitsu Frv Relocations. COMMENT -COMMENT ENUMDOC MIPS ELF relocations. @@ -2393,6 +2395,89 @@ ENUMDOC Power(rs6000) and PowerPC relocations. ENUM + BFD_RELOC_PPC_TLS +ENUMX + BFD_RELOC_PPC_DTPMOD +ENUMX + BFD_RELOC_PPC_TPREL16 +ENUMX + BFD_RELOC_PPC_TPREL16_LO +ENUMX + BFD_RELOC_PPC_TPREL16_HI +ENUMX + BFD_RELOC_PPC_TPREL16_HA +ENUMX + BFD_RELOC_PPC_TPREL +ENUMX + BFD_RELOC_PPC_DTPREL16 +ENUMX + BFD_RELOC_PPC_DTPREL16_LO +ENUMX + BFD_RELOC_PPC_DTPREL16_HI +ENUMX + BFD_RELOC_PPC_DTPREL16_HA +ENUMX + BFD_RELOC_PPC_DTPREL +ENUMX + BFD_RELOC_PPC_GOT_TLSGD16 +ENUMX + BFD_RELOC_PPC_GOT_TLSGD16_LO +ENUMX + BFD_RELOC_PPC_GOT_TLSGD16_HI +ENUMX + BFD_RELOC_PPC_GOT_TLSGD16_HA +ENUMX + BFD_RELOC_PPC_GOT_TLSLD16 +ENUMX + BFD_RELOC_PPC_GOT_TLSLD16_LO +ENUMX + BFD_RELOC_PPC_GOT_TLSLD16_HI +ENUMX + BFD_RELOC_PPC_GOT_TLSLD16_HA +ENUMX + BFD_RELOC_PPC_GOT_TPREL16 +ENUMX + BFD_RELOC_PPC_GOT_TPREL16_LO +ENUMX + BFD_RELOC_PPC_GOT_TPREL16_HI +ENUMX + BFD_RELOC_PPC_GOT_TPREL16_HA +ENUMX + BFD_RELOC_PPC_GOT_DTPREL16 +ENUMX + BFD_RELOC_PPC_GOT_DTPREL16_LO +ENUMX + BFD_RELOC_PPC_GOT_DTPREL16_HI +ENUMX + BFD_RELOC_PPC_GOT_DTPREL16_HA +ENUMX + BFD_RELOC_PPC64_TPREL16_DS +ENUMX + BFD_RELOC_PPC64_TPREL16_LO_DS +ENUMX + BFD_RELOC_PPC64_TPREL16_HIGHER +ENUMX + BFD_RELOC_PPC64_TPREL16_HIGHERA +ENUMX + BFD_RELOC_PPC64_TPREL16_HIGHEST +ENUMX + BFD_RELOC_PPC64_TPREL16_HIGHESTA +ENUMX + BFD_RELOC_PPC64_DTPREL16_DS +ENUMX + BFD_RELOC_PPC64_DTPREL16_LO_DS +ENUMX + BFD_RELOC_PPC64_DTPREL16_HIGHER +ENUMX + BFD_RELOC_PPC64_DTPREL16_HIGHERA +ENUMX + BFD_RELOC_PPC64_DTPREL16_HIGHEST +ENUMX + BFD_RELOC_PPC64_DTPREL16_HIGHESTA +ENUMDOC + PowerPC and PowerPC64 thread-local storage relocations. + +ENUM BFD_RELOC_I370_D12 ENUMDOC IBM 370/390 relocations diff --git a/bfd/section.c b/bfd/section.c index 35a0e5a..89f8126 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -1,6 +1,6 @@ /* Object file "section" support for the BFD library. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Cygnus Support. @@ -377,10 +377,35 @@ CODE_FRAGMENT . {* A mark flag used by some linker backends for garbage collection. *} . unsigned int gc_mark : 1; . -. {* Used by the ELF code to mark sections which have been allocated -. to segments. *} +. {* The following flags are used by the ELF linker. *} +. +. {* Mark sections which have been allocated to segments. *} . unsigned int segment_mark : 1; . +. {* Type of sec_info information. *} +. unsigned int sec_info_type:3; +.#define ELF_INFO_TYPE_NONE 0 +.#define ELF_INFO_TYPE_STABS 1 +.#define ELF_INFO_TYPE_MERGE 2 +.#define ELF_INFO_TYPE_EH_FRAME 3 +.#define ELF_INFO_TYPE_JUST_SYMS 4 +. +. {* Nonzero if this section uses RELA relocations, rather than REL. *} +. unsigned int use_rela_p:1; +. +. {* Bits used by various backends. *} +. unsigned int has_tls_reloc:1; +. +. {* Usused bits. *} +. unsigned int flag11:1; +. unsigned int flag12:1; +. unsigned int flag13:1; +. unsigned int flag14:1; +. unsigned int flag15:1; +. unsigned int flag16:4; +. unsigned int flag20:4; +. unsigned int flag24:8; +. . {* End of internal packed boolean fields. *} . . {* The virtual memory address of the section - where it will be @@ -590,6 +615,12 @@ static const asymbol global_syms[] = /* linker_mark, linker_has_input, gc_mark, segment_mark, */ \ 0, 0, 1, 0, \ \ + /* sec_info_type, use_rela_p, has_tls_reloc, flag11, flag12, */ \ + 0, 0, 0, 0, 0, \ + \ + /* flag13, flag14, flag15, flag16, flag20, flag24, */ \ + 0, 0, 0, 0, 0, 0, \ + \ /* vma, lma, _cooked_size, _raw_size, */ \ 0, 0, 0, 0, \ \ @@ -1,24 +1,24 @@ /* Generic symbol-table support for the BFD library. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Written by Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* SECTION @@ -74,9 +74,9 @@ SUBSECTION | if (storage_needed < 0) | FAIL | -| if (storage_needed == 0) { -| return ; -| } +| if (storage_needed == 0) +| return; +| | symbol_table = (asymbol **) xmalloc (storage_needed); | ... | number_of_symbols = @@ -85,9 +85,8 @@ SUBSECTION | if (number_of_symbols < 0) | FAIL | -| for (i = 0; i < number_of_symbols; i++) { -| process_symbol (symbol_table[i]); -| } +| for (i = 0; i < number_of_symbols; i++) +| process_symbol (symbol_table[i]); All storage for the symbols themselves is in an objalloc connected to the BFD; it is freed when the BFD is closed. @@ -108,25 +107,26 @@ SUBSECTION example showing the creation of a symbol table with only one element: | #include "bfd.h" -| main() +| int main (void) | { | bfd *abfd; | asymbol *ptrs[2]; | asymbol *new; | -| abfd = bfd_openw("foo","a.out-sunos-big"); -| bfd_set_format(abfd, bfd_object); -| new = bfd_make_empty_symbol(abfd); +| abfd = bfd_openw ("foo","a.out-sunos-big"); +| bfd_set_format (abfd, bfd_object); +| new = bfd_make_empty_symbol (abfd); | new->name = "dummy_symbol"; -| new->section = bfd_make_section_old_way(abfd, ".text"); +| new->section = bfd_make_section_old_way (abfd, ".text"); | new->flags = BSF_GLOBAL; | new->value = 0x12345; | | ptrs[0] = new; | ptrs[1] = (asymbol *)0; | -| bfd_set_symtab(abfd, ptrs, 1); -| bfd_close(abfd); +| bfd_set_symtab (abfd, ptrs, 1); +| bfd_close (abfd); +| return 0; | } | | ./makesym @@ -192,7 +192,7 @@ CODE_FRAGMENT . instead, except that some symbols point to the global sections . bfd_{abs,com,und}_section. This could be fixed by making . these globals be per-bfd (or per-target-flavor). FIXME. *} -. struct _bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *} +. struct bfd *the_bfd; {* Use bfd_asymbol_bfd(sym) to access this field. *} . . {* The text of the symbol. The name is left alone, and not copied; the . application may not alter it. *} @@ -346,7 +346,7 @@ FUNCTION bfd_is_local_label SYNOPSIS - bfd_boolean bfd_is_local_label(bfd *abfd, asymbol *sym); + bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym); DESCRIPTION Return TRUE if the given symbol @var{sym} in the BFD @var{abfd} is @@ -438,7 +438,7 @@ FUNCTION bfd_print_symbol_vandf SYNOPSIS - void bfd_print_symbol_vandf(bfd *abfd, PTR file, asymbol *symbol); + void bfd_print_symbol_vandf (bfd *abfd, PTR file, asymbol *symbol); DESCRIPTION Print the value and flags of the @var{symbol} supplied to the @@ -451,16 +451,14 @@ bfd_print_symbol_vandf (abfd, arg, symbol) asymbol *symbol; { FILE *file = (FILE *) arg; + flagword type = symbol->flags; + if (symbol->section != (asection *) NULL) - { - bfd_fprintf_vma (abfd, file, - symbol->value + symbol->section->vma); - } + bfd_fprintf_vma (abfd, file, + symbol->value + symbol->section->vma); else - { - bfd_fprintf_vma (abfd, file, symbol->value); - } + bfd_fprintf_vma (abfd, file, symbol->value); /* This presumes that a symbol can not be both BSF_DEBUGGING and BSF_DYNAMIC, nor more than one of BSF_FUNCTION, BSF_FILE, and @@ -504,7 +502,7 @@ FUNCTION _bfd_generic_make_empty_symbol SYNOPSIS - asymbol *_bfd_generic_make_empty_symbol (bfd *); + asymbol * _bfd_generic_make_empty_symbol (bfd *); DESCRIPTION Create a new <<asymbol>> structure for the BFD @var{abfd} @@ -634,7 +632,7 @@ DESCRIPTION class of @var{symbol}, or '?' for an unknown class. SYNOPSIS - int bfd_decode_symclass(asymbol *symbol); + int bfd_decode_symclass (asymbol *symbol); */ int bfd_decode_symclass (symbol) @@ -726,7 +724,7 @@ DESCRIPTION calling this function. SYNOPSIS - void bfd_symbol_info(asymbol *symbol, symbol_info *ret); + void bfd_symbol_info (asymbol *symbol, symbol_info *ret); */ void @@ -749,7 +747,7 @@ FUNCTION bfd_copy_private_symbol_data SYNOPSIS - bfd_boolean bfd_copy_private_symbol_data(bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); + bfd_boolean bfd_copy_private_symbol_data (bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); DESCRIPTION Copy private symbol information from @var{isym} in the BFD @@ -816,7 +814,6 @@ _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep) an asymbol. We don't worry about the sym argument we are passed; we just return the asymbol the minisymbol points to. */ -/*ARGSUSED*/ asymbol * _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym) bfd *abfd ATTRIBUTE_UNUSED; @@ -1245,12 +1242,11 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound, else #endif { - /* Cache non-existant or invalid. Do binary search on - indextable. */ - long low, high; long mid = -1; + /* Cache non-existant or invalid. Do binary search on + indextable. */ indexentry = NULL; low = 0; @@ -1305,9 +1301,11 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound, case N_SLINE: case N_DSLINE: case N_BSLINE: - /* A line number. The value is relative to the start of the - current function. */ - val = indexentry->val + bfd_get_32 (abfd, stab + VALOFF); + /* A line number. If the function was specified, then the value + is relative to the start of the function. Otherwise, the + value is an absolute address. */ + val = ((indexentry->function_name ? indexentry->val : 0) + + bfd_get_32 (abfd, stab + VALOFF)); /* If this line starts before our desired offset, or if it's the first line we've been able to find, use it. The !saw_line check works around a bug in GCC 2.95.3, which emits @@ -1376,7 +1374,6 @@ _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound, /* This will typically be something like main:F(0,1), so we want to clobber the colon. It's OK to change the name, since the string is in our own local storage anyhow. */ - s = strchr (indexentry->function_name, ':'); if (s != NULL) *s = '\0'; diff --git a/bfd/targets.c b/bfd/targets.c index c541c11..2211e12 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -763,7 +763,7 @@ static const bfd_target * const _bfd_target_vector[] = { #endif &aout0_big_vec, #if 0 - /* We have no way of distinguishing these from other a.out variants */ + /* We have no way of distinguishing these from other a.out variants. */ &aout_arm_big_vec, &aout_arm_little_vec, /* No one seems to use this. */ @@ -909,7 +909,7 @@ static const bfd_target * const _bfd_target_vector[] = { &bfd_powerpcle_pei_vec, &cris_aout_vec, #ifdef BFD64 - &demo_64_vec, /* Only compiled if host has long-long support */ + &demo_64_vec, /* Only compiled if host has long-long support. */ #endif &ecoff_big_vec, &ecoff_biglittle_vec, @@ -1011,7 +1011,7 @@ static const bfd_target * const _bfd_target_vector[] = { #endif &ppcboot_vec, #if 0 - /* We have no way of distinguishing these from other a.out variants */ + /* We have no way of distinguishing these from other a.out variants. */ &riscix_vec, #endif #ifdef BFD64 @@ -1221,7 +1221,7 @@ FUNCTION bfd_find_target SYNOPSIS - const bfd_target *bfd_find_target(const char *target_name, bfd *abfd); + const bfd_target *bfd_find_target (const char *target_name, bfd *abfd); DESCRIPTION Return a pointer to the transfer vector for the object target @@ -1274,7 +1274,7 @@ FUNCTION bfd_target_list SYNOPSIS - const char **bfd_target_list(void); + const char ** bfd_target_list (void); DESCRIPTION Return a freshly malloced NULL-terminated @@ -1319,7 +1319,9 @@ FUNCTION bfd_seach_for_target SYNOPSIS - const bfd_target * bfd_search_for_target (int (* search_func) (const bfd_target *, void *), void *); + const bfd_target * bfd_search_for_target (int (* search_func) + (const bfd_target *, void *), + void *); DESCRIPTION Return a pointer to the first transfer vector in the list of diff --git a/bfd/version.h b/bfd/version.h index 727b55b..3a264cb 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -1,3 +1,3 @@ -#define BFD_VERSION_DATE 20030203 +#define BFD_VERSION_DATE 20030303 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_string@ |