Bug 15904 - ia64, ELF, 'Can't relax br (PCREL21B)' error message on --no-keep-memory
Summary: ia64, ELF, 'Can't relax br (PCREL21B)' error message on --no-keep-memory
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.23
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2013-08-28 20:47 UTC by Stephan Schreiber
Modified: 2020-04-01 10:38 UTC (History)
8 users (show)

See Also:
Last reconfirmed:

A patch proposal for the bug. (676 bytes, patch)
2013-08-28 20:47 UTC, Stephan Schreiber
Details | Diff
updated untested patch (453 bytes, patch)
2018-02-26 21:36 UTC, Jim Wilson
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stephan Schreiber 2013-08-28 20:47:36 UTC
Created attachment 7174 [details]
A patch proposal for the bug.

Debian Linux on ia64 (Itanium), sid (unstable).

The binutils build is the Debian package binutils

The build of the Iceweasel 17.0.8esr-1 package (a renamed Firefox) fails:

/«PKGBUILDDIR»/build-xulrunner/_virtualenv/bin/python ../../../config/pythonpath.py -I../../config ../../../config/expandlibs_exec.py --depend .deps/libxul.so.pp --target libxul.so --uselist --  g++ -D_FORTIFY_SOURCE=2 -Wall -Wpointer-arith -Woverloaded-virtual -Werror=return-type -Wtype-limits -Wempty-body -Wno-ctor-dtor-privacy -Wno-overlength-strings -Wno-invalid-offsetof -Wno-variadic-macros -Wformat -Werror=format-security -fno-exceptions -fno-strict-aliasing -fno-rtti -ffunction-sections -fdata-sections -fno-exceptions -std=gnu++0x -pthread -pipe  -DNDEBUG -DTRIMMED -g -O2 -fomit-frame-pointer -fPIC -shared -Wl,-z,defs -Wl,--gc-sections -Wl,-h,libxul.so -o libxul.so  nsStaticXULComponents.o nsUnicharUtils.o nsBidiUtils.o nsSpecialCasingData.o nsUnicodeProperties.o nsRDFResource.o    -Wl,--as-needed -Wl,--no-keep-memory -Wl,--reduce-memory-overheads -Wl,--stats -lpthread  -Wl,-z,noexecstack   -Wl,-rpath-link,/«PKGBUILDDIR»/build-xulrunner/dist/bin -Wl,-rpath-link,/usr/lib   ../../toolkit/components/osfile/libosfile_s.a ../../toolkit/xre/libxulapp_s.a  ../../staticlib/components/libnecko.a ../../staticlib/components/libuconv.a ../../staticlib/components/libi18n.a ../../staticlib/components/libchardet.a ../../staticlib/components/libjar50.a ../../staticlib/components/libstartupcache.a ../../staticlib/components/libpref.a ../../staticlib/components/libhtmlpars.a ../../staticlib/components/libidentity.a ../../staticlib/components/libimglib2.a ../../staticlib/components/libgkgfx.a ../../staticlib/components/libgklayout.a ../../staticlib/components/libdocshell.a ../../staticlib/components/libembedcomponents.a ../../staticlib/components/libwebbrwsr.a ../../staticlib/components/libnsappshell.a ../../staticlib/components/libtxmgr.a ../../staticlib/components/libcommandlines.a ../../staticlib/components/libtoolkitcomps.a ../../staticlib/components/libpipboot.a ../../staticlib/components/libpipnss.a ../../staticlib/components/libappcomps.a ../../staticlib/components/libjsreflect.a ../../staticlib/components/libcomposer.a ../../staticlib/components/libtelemetry.a ../../staticlib/components/libjsinspector.a ../../staticlib/components/libjsdebugger.a ../../staticlib/components/libstoragecomps.a ../../staticlib/components/librdf.a ../../staticlib/components/libwindowds.a ../../staticlib/components/libjsctypes.a ../../staticlib/components/libjsperf.a ../../staticlib/components/libgkplugin.a ../../staticlib/components/libunixproxy.a ../../staticlib/components/libjsd.a ../../staticlib/components/libautoconfig.a ../../staticlib/components/libauth.a ../../staticlib/components/libcookie.a ../../staticlib/components/libpermissions.a ../../staticlib/components/libuniversalchardet.a ../../staticlib/components/libfileview.a ../../staticlib/components/libplaces.a ../../staticlib/components/libtkautocomplete.a ../../staticlib/components/libsatchel.a ../../staticlib/components/libpippki.a ../../staticlib/components/libwidget_gtk2.a ../../staticlib/components/libimgicon.a ../../staticlib/components/libaccessibility.a ../../staticlib/components/libremoteservice.a ../../staticlib/components/libspellchecker.a ../../staticlib/components/libzipwriter.a ../../staticlib/components/libservices-crypto.a ../../staticlib/components/libnkgio.a ../../staticlib/libjsipc_s.a ../../staticlib/libdomipc_s.a ../../staticlib/libdomplugins_s.a ../../staticlib/libmozipc_s.a ../../staticlib/libmozipdlgen_s.a ../../staticlib/libipcshell_s.a ../../staticlib/libgfxipc_s.a ../../staticlib/libhal_s.a ../../staticlib/libdombindings_s.a ../../staticlib/libxpcom_core.a ../../staticlib/libucvutil_s.a ../../staticlib/libchromium_s.a ../../staticlib/libsnappy_s.a ../../staticlib/libgtkxtbin.a ../../staticlib/libthebes.a ../../staticlib/libgl.a ../../staticlib/libycbcr.a  -L../../dist/bin -L../../dist/lib /«PKGBUILDDIR»/build-xulrunner/dist/lib/libmozjs.a -L/usr/lib/ia64-linux-gnu -lssl3 -lsmime3 -lnss3 -lnssutil3 -lcrmf -lcairo    -lXrender -lcairo -lXext -lX11    -lsqlite3    -ljpeg -lz -lhunspell-1.3   -L/usr/lib -levent -lvpx   -lpixman-1   ../../dist/lib/libgkmedias.a  -lasound    -L../../dist/bin -L../../dist/lib  -L/usr/lib/ia64-linux-gnu -lplds4 -lplc4 -lnspr4 -lpthread -ldl ../../dist/lib/libmozalloc.a -ldbus-glib-1 -ldbus-1 -lgobject-2.0 -lglib-2.0    -lX11  -lXext  -lpangoft2-1.0 -lfreetype -lfontconfig -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0   -lfontconfig   -lgtk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lfreetype -lfontconfig -lgdk-x11-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0   -lXt -lgthread-2.0 -lfreetype   -lstartup-notification-1    -ldl  -lrt    
/usr/bin/ld: Warning: gc-sections option ignored
/usr/bin/ld: ../xre/nsAppRunner.o: Can't relax br (PCREL21B) to `nsCOMPtr_base::begin_assignment()' at 0x32 in section `.text._ZL32ProfileServiceFactoryConstructorRKN7mozilla6ModuleERKNS0_8CIDEntryE' with size 0x80 (> 0x1000000).
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: ld returned 1 exit status
make[5]: *** [libxul.so] Error 1
make[5]: Leaving directory `/«PKGBUILDDIR»/build-xulrunner/toolkit/library'
make[4]: *** [libs_tier_platform] Error 2
make[3]: *** [tier_platform] Error 2
make[2]: *** [default] Error 2
make[4]: Leaving directory `/«PKGBUILDDIR»/build-xulrunner'
make[3]: Leaving directory `/«PKGBUILDDIR»/build-xulrunner'
make[2]: Leaving directory `/«PKGBUILDDIR»/build-xulrunner'
dh_auto_build: make -j2 JS_READLINE=1 returned exit code 2
make[1]: *** [stamps/build-xulrunner] Error 2
make[1]: Leaving directory `/«PKGBUILDDIR»'
make: *** [build] Error 2

In toolkit/xre/nsAppRunner.cpp you can read:

static already_AddRefed<nsIFactory>
ProfileServiceFactoryConstructor(const mozilla::Module& module, const mozilla::Module::CIDEntry& entry)
  nsCOMPtr<nsIFactory> factory;
  return factory.forget();

objdump -d build-xulrunner/toolkit/xre/nsAppRunner.o

0000000000000000 <_ZL32ProfileServiceFactoryConstructorRKN7mozilla6ModuleERKNS0_8CIDEntryE>:
   0:	18 08 11 06 80 05 	[MMB]       alloc r33=ar.pfs,4,3,0
   6:	c0 80 33 7e 46 00 	            adds r12=-16,r12
   c:	00 00 00 20       	            nop.b 0x0
  10:	03 10 01 02 00 21 	[MII]       mov r34=r1
  16:	00 02 00 62 00 c0 	            mov r32=b0;;
  1c:	01 61 00 84       	            adds r14=16,r12;;
  20:	08 00 00 00 01 00 	[MMI]       nop.m 0x0
  26:	30 02 38 00 42 00 	            mov r35=r14
  2c:	00 00 04 00       	            nop.i 0x0
  30:	19 00 00 1c 98 11 	[MMB]       st8 [r14]=r0
  36:	00 00 00 02 00 00 	            nop.m 0x0
  3c:	08 00 00 50       	            br.call.sptk.many b0=30 <_ZL32ProfileServiceFactoryConstructorRKN7mozilla6ModuleERKNS0_8CIDEntryE+0x30>;;
  40:	11 08 00 44 00 21 	[MIB]       mov r1=r34
  46:	30 02 20 00 42 00 	            mov r35=r8
  4c:	08 00 00 50       	            br.call.sptk.many b0=40 <_ZL32ProfileServiceFactoryConstructorRKN7mozilla6ModuleERKNS0_8CIDEntryE+0x40>;;
  50:	09 70 40 18 00 21 	[MMI]       adds r14=16,r12
  56:	00 00 00 02 00 20 	            nop.m 0x0
  5c:	00 10 01 84       	            mov r1=r34;;
  60:	02 40 00 1c 18 10 	[MII]       ld8 r8=[r14]
  66:	00 08 01 55 00 00 	            mov.i ar.pfs=r33;;
  6c:	00 0a 00 07       	            mov b0=r32
  70:	19 00 00 00 01 00 	[MMB]       nop.m 0x0
  76:	c0 80 30 00 42 80 	            adds r12=16,r12
  7c:	08 00 84 00       	            br.ret.sptk.many b0;;


There isn't any reference to a symbol `nsCOMPtr_base::begin_assignment()'; there is neither `nsCOMPtr_base' nor `begin_assignment()' in the entire output of objdump.
The error message of ld is nonsense, it's a bug of ld.

It turned out that the --no-keep-memory makes the difference. The problem doesn't occur when the --no-keep-memory switch is removed.

The error message "Can't relax br (PCREL21B) to .." just means that ld failed to calculate the 21-bits relocation of a br instruction because the target of br was out of the address range of the relative 21-bits address mode.
It turned out that it occurs because ld took a wrong external symbol when it attempted to relocate the mentioned section. It was caused by erroneous dropping some modified relocation data due to the --no-keep-memory switch; ld read the relocation data from the input file again after that and continued working with stale relocation data.

The problem is in bfd/elfnn-ia64.c in the function elfNN_ia64_relax_section():
It reads the relocs from a file if necessary:

  internal_relocs = (_bfd_elf_link_read_relocs
		     (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,

If keep_memory is true, _bfd_elf_link_read_relocs() allocates the memory for internal_relocs once and stores the pointer at elf_section_data (sec)->relocs; it returns that pointer as well.
If keep_memory is false, _bfd_elf_link_read_relocs() returns either existing memory/data - if elf_section_data (sec)->relocs is *not* NULL. Otherwise it allocates new memory and fills it out (by reading in a file); elf_section_data (sec)->relocs remains unchanged (is still NULL).

Some processing follows in elfNN_ia64_relax_section(), which may modify the data in the internal_relocs[] array.
When it modifies anything, it sets a local variable changed_relocs to TRUE.

Finally the memory is freed if it is neither kept memory nor modified (indicated by changed_relocs).

  if (elf_section_data (sec)->relocs != internal_relocs)
      if (!changed_relocs)
	free (internal_relocs);
	elf_section_data (sec)->relocs = internal_relocs;

The bug is that changed_relocs was not set correctly to TRUE on some condition in elfNN_ia64_relax_section().

This is Debian bug#720404 (http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=720404).

A proposal for a patch is attached. Of course I have tested it; it fixes the problem.

Comment 1 Jessica Clarke 2018-02-26 13:30:46 UTC
I just ran into this when compiling qtwebkit, and can confirm that this patch fixed the issue for me. Stephan, if you're still interested in this bug, could you please add a suitable ChangeLog-style commit message and submit this to the mailing list?
Comment 2 Jim Wilson 2018-02-26 21:36:02 UTC
Created attachment 10855 [details]
updated untested patch
Comment 3 Jim Wilson 2018-02-26 21:37:07 UTC
The patch looks mostly correct, but we should be setting changed_contents also.  The patch looks small enough and obvious enough that I don't think that we need a copyright assignment for the provided patch.

Unfortunately, I don't have access to ia64 hardware, so I can't easily test the patch with anything other than the binutils testsuite.
Comment 4 cvs-commit@gcc.gnu.org 2018-02-26 22:06:46 UTC
The master branch has been updated by Jim Wilson <wilson@sourceware.org>:


commit 6f6372fadcfffc89ef511d51323678f88624be5c
Author: Jim Wilson <jimw@sifive.com>
Date:   Mon Feb 26 14:05:13 2018 -0800

    IA-64: Fix linker error with --no-keep-memory.
    	PR 15904
    	* elfnn-ia64.c (elfNN_ia64_relax_section): After ia64_elf_relax_brl
    	call, set changed_contents and changed_relocs.  Likewise after
    	successful ia64_elf_relax_br call.
Comment 5 Jim Wilson 2018-02-26 22:10:04 UTC
Updated patch committed.
Comment 6 Jim Wilson 2018-02-26 22:11:07 UTC
Updated patch committed.
Comment 7 Jessica Clarke 2018-02-26 22:11:39 UTC
(In reply to Jim Wilson from comment #5)
> Updated patch committed.

Great, thanks! Could you please consider backporting it to the 2.30 branch?
Comment 8 cvs-commit@gcc.gnu.org 2018-02-28 18:04:41 UTC
The binutils-2_30-branch branch has been updated by Jim Wilson <wilson@sourceware.org>:


commit 309c6330b67af549963b2b34986b2dd08baa5ba6
Author: Jim Wilson <jimw@sifive.com>
Date:   Wed Feb 28 10:03:31 2018 -0800

    IA-64: Fix linker error with --no-keep-memory.
    	Import patch from mainline:
    	2018-02-26  Jim Wilson  <jimw@sifive.com>
    	Stephan Schreiber <info@fs-driver.org>
    	PR 15904
    	* elfnn-ia64.c (elfNN_ia64_relax_section): After ia64_elf_relax_brl
    	call, set changed_contents and changed_relocs.  Likewise after
    	successful ia64_elf_relax_br call.
Comment 9 Alex Victor 2020-03-16 05:13:21 UTC Comment hidden (spam)
Comment 10 Ezra Dagan 2020-04-01 10:38:42 UTC Comment hidden (spam)