This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[committed] Ensure pc-relative calls can reach their target on hppa64
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: binutils at sourceware dot org
- Cc: r dot emrich at de dot tecosim dot com
- Date: Sun, 25 Jan 2009 18:20:59 -0500 (EST)
- Subject: [committed] Ensure pc-relative calls can reach their target on hppa64
GCC has put a little weight on over the years. It turns out GNU ld can
no longer link cc1plus or f951 on hppa64 because the branch distances for
some calls now exceed the maximum distance for branches using the
R_PARISC_PCREL22F relocation.
There is no long branch stub support and out of range branches are silently
accepted. We need to port the stub management code from elf32-hppa.c to
elf64-hppa.c. This is a bit tricky since the code has diverged in other
ways.
In the meantime, I have more or less copied the code to check for out of
range branches from elf32-hppa.c to elf-hppa.h.
Tested on hppa64-hp-hpux11.11:
/test/gnu/gcc/objdir/./prev-gcc/xgcc -B/test/gnu/gcc/objdir/./prev-gcc/ -B/opt/gnu64/gcc/gcc-4.4.0/hppa64-hp-hpux11.11/bin/ -g -O2 -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wold-style-definition -Wc++-compat -Wmissing-format-attribute -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror -fno-common -DHAVE_CONFIG_H -o cc1plus-dummy \
cp/cp-lang.o stub-objc.o cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o cp/class.o cp/decl2.o cp/error.o cp/lex.o cp/parser.o cp/ptree.o cp/rtti.o cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o cp/cp-gimplify.o tree-mudflap.o attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o c-dump.o c-pretty-print.o c-opts.o c-pch.o incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o c-gimplify.o c-omp.o tree-inline.o dummy-checksum.o main.o tree-browser.o libbackend.a ../libcpp/libcpp.a ../libdecnumber/libdecnumber.a ../libcpp/libcpp.a ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a -L/opt/gnu64/gcc/gcc-4.4.0/lib -lmpfr -lgmp
/opt/gnu64/bin/ld: /usr/ccs/lib/pa20_64/crt0.o(.text+0x7a4): cannot reach $$rem2I
/opt/gnu64/bin/ld: BFD (GNU Binutils) 2.19.51.20090125 internal error, aborting
at ../../src/bfd/elf-hppa.h line 2346 in elf64_hppa_relocate_section
/opt/gnu64/bin/ld: Please report this bug.
Committed to binutils trunk.
Dave
--
J. David Anglin dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
2009-01-25 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* elf-hppa.h (elf_hppa_final_link_relocate): Add check to ensure that
branch targets can be reached for R_PARISC_PCREL22F, R_PARISC_PCREL17F
and R_PARISC_PCREL12F relocations.
Index: elf-hppa.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-hppa.h,v
retrieving revision 1.89
diff -u -3 -p -r1.89 elf-hppa.h
--- elf-hppa.h 28 Aug 2008 02:33:44 -0000 1.89
+++ elf-hppa.h 25 Jan 2009 22:42:20 -0000
@@ -1606,10 +1606,11 @@ elf_hppa_final_link_relocate (Elf_Intern
bfd_vma value,
struct bfd_link_info *info,
asection *sym_sec,
- struct elf_link_hash_entry *h ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h,
struct elf64_hppa_dyn_hash_entry *dyn_h)
{
int insn;
+ bfd_vma max_branch_offset = 0;
bfd_vma offset = rel->r_offset;
bfd_signed_vma addend = rel->r_addend;
reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info);
@@ -1629,7 +1630,7 @@ elf_hppa_final_link_relocate (Elf_Intern
Note for a call to a function defined in another dynamic library
we want to redirect the call to a stub. */
- /* Random PC relative relocs. */
+ /* PC relative relocs without an implicit offset. */
case R_PARISC_PCREL21L:
case R_PARISC_PCREL14R:
case R_PARISC_PCREL14F:
@@ -1684,6 +1685,27 @@ elf_hppa_final_link_relocate (Elf_Intern
value -= (offset + input_section->output_offset
+ input_section->output_section->vma);
+ if (r_type == (unsigned int) R_PARISC_PCREL22F)
+ max_branch_offset = (1 << (22-1)) << 2;
+ else if (r_type == (unsigned int) R_PARISC_PCREL17F)
+ max_branch_offset = (1 << (17-1)) << 2;
+ else if (r_type == (unsigned int) R_PARISC_PCREL12F)
+ max_branch_offset = (1 << (12-1)) << 2;
+
+ /* Make sure we can reach the branch target. */
+ if (max_branch_offset != 0
+ && value + addend + max_branch_offset >= 2*max_branch_offset)
+ {
+ (*_bfd_error_handler)
+ (_("%B(%A+0x%lx): cannot reach %s"),
+ input_bfd,
+ input_section,
+ offset,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
+
/* Adjust for any field selectors. */
if (r_type == R_PARISC_PCREL17R)
value = hppa_field_adjust (value, -8 + addend, e_rsel);