Bug 16177

Summary: R_ARM_COPY reloc generated for reference in writable section
Product: binutils Reporter: Roland McGrath <roland>
Component: binutilsAssignee: Not yet assigned to anyone <unassigned>
Status: ASSIGNED ---    
Severity: normal CC: bgamari, dmueller, John.Ericson, jrtc27, mjtruog, nbowler, nickc, rguenth, sam, slyich, sourceware
Priority: P2    
Version: 2.25   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: Proposed patch
Rebased patch
Updated/fixed patch
Updated patch against master

Description Roland McGrath 2013-11-15 20:51:34 UTC
When a writable input section (i.e. data) refers to a symbol defined in an
ET_DYN object, BFD ld for ARM targets generates a COPY dynamic reloc.  For
other targets like x86, this situation generates a plain data dynamic
reloc.  Gold for ARM also generates the plain data dynamic reloc.

I can't understand any rationale for generating a synthetic data object and
copy reloc for it in this situation.  A copy reloc is only appropriate when
the reference is from a read-only input section (e.g. from an instruction).

	$ cat data-ref.s
	.globl _start
		.p2align 4
	_start:
		bkpt

	.data
		.globl data_object
	object_reference:
		.long data_object
		.size object_reference,4
	$ cat libdata.s
		.data
		.globl data_object
		.type data_object, %object
		.size data_object, 4
	data_object:
		  .long 123
	$ ./gas/as-new -o data-ref.o data-ref.s 
	$ ./gas/as-new -o libdata.o libdata.s
	$ ./ld/ld-new -shared -o libdata.so libdata.o
	$ ./ld/ld-new -o data-ref data-ref.o libdata.so
	$ readelf -r data-ref

	Relocation section '.rel.dyn' at offset 0x224 contains 1 entries:
	 Offset     Info    Type            Sym.Value  Sym. Name
	100302bc  00000314 R_ARM_COPY        100302bc   data_object
	$ ./gold/ld-new -o data-ref-gold data-ref.o libdata.so
	$ readelf -r data-ref-gold

	Relocation section '.rel.dyn' at offset 0x190 contains 1 entries:
	 Offset     Info    Type            Sym.Value  Sym. Name
	00009230  00000102 R_ARM_ABS32       00000000   data_object
	$
Comment 1 Ben Gamari 2014-01-20 18:19:58 UTC
This appears to be responsible for brokenness on ARM when the Glasgow Haskell Compiler is used to produce dynamically linked executables https://ghc.haskell.org/trac/ghc/ticket/4210#comment:29.
Comment 2 Nick Clifton 2016-04-20 13:00:19 UTC
Created attachment 9207 [details]
Proposed patch

Hi Ben,

  Please try this patch.

Cheers
  Nick
Comment 3 Nick Clifton 2016-04-20 13:01:45 UTC
Ben or Roland that is...
Comment 4 Ben Gamari 2017-04-07 00:23:53 UTC
Unfortunately my ARM hardware bit the dust. I'm waiting to take shipment of a new board and will test when it arrives.
Comment 5 Ben Gamari 2017-07-01 22:57:34 UTC
My new hardware arrived. Naturally the patch required a bit of rebasing. My guess can be found here, https://github.com/bgamari/binutils-gdb/commit/539f59256dd8b503b1188eecb30a338ee38616f8. I've started a GHC build linking with the linker from this commit. I'll let you know when it's finished and I've verified that it works.
Comment 6 John Ericson 2018-01-10 02:55:57 UTC
Created attachment 10727 [details]
Rebased patch

This is Ben Gamari's rebase of the original patch, included here for posterity.
Comment 7 Nick Clifton 2018-01-10 09:17:14 UTC
The question is - does the patch work ?

I am happy to apply it, provided that it can be confirmed that it works
in a real ARM-based system.

Cheers
  Nick
Comment 8 John Ericson 2018-01-12 23:03:40 UTC
I just copied it, but think I'll be able to confirm that for you by end of next week.

Thanks,

John
Comment 9 Jessica Clarke 2018-07-12 22:17:06 UTC
Created attachment 11124 [details]
Updated/fixed patch

The original patch on this bug report looks at whether the symbol in question is in a read-only section, but that should have no effect on whether this symbol needs to be copied into the executable. Instead, it should be checking whether there are any relocations in read-only sections referring to the symbol, as that determines whether we are able to leave in dynamic relocations. Ben's rebased version also has the issue of messing with the SEC_READONLY check currently present; that should stay, as SEC_READONLY determines where the copied symbol should go, but only matters if we are doing a copy in the first place. This patch hasn't even been compile tested, but I'm 90% confident it works!
Comment 10 Joe Hermaszewski 2020-11-08 13:56:25 UTC
Hi Jessica, I tried out the patch, thank you! It still applies cleanly, however
when building ncurses it fails, here are the last few lines:

    armv7l-unknown-linux-musleabihf-ranlib ../lib/libncurses++w.a
    compiling demo (obj_s)
    armv7l-unknown-linux-musleabihf-g++  -o demo ../obj_s/demo.o -L../lib -lncurses++w -L../lib -lformw -lmenuw -lpanelw -lncursesw    -lutil     -DHAVE_CONFIG_H -I../c++ -I. -I../include  -DNDEBUG -O2  -fPIC
    armv7l-unknown-linux-musleabihf-ld: ../obj_s/demo.o(.data.rel.ro._ZTI16NCursesFieldType[_ZTI16NCursesFieldType]+0): unresolvable R_ARM_ABS32 relocation against symbol `_ZTVN10__cxxabiv117__class_type_infoE@@CXXABI_1.3'
    armv7l-unknown-linux-musleabihf-ld: final link failed: nonrepresentable section on output
    collect2: error: ld returned 1 exit status

The complete log (against musl) is here: https://gist.github.com/2dcd79254db6a00e9d9b99f7f556e56e
And against glibc: https://gist.github.com/3d744762e20df5bad9652f20d8f1a06e
Comment 11 Joe Hermaszewski 2020-11-08 14:53:00 UTC
To reproduce,

- Get a copy of the ncurses 6.2 source
- With binutils (with the patch), and gcc in PATH (both cross compiling to armv7l-unknown-linux-gnueabihf)
- CXX=armv7l-unknown-linux-gnueabihf-g++ CC=armv7l-unknown-linux-gnueabihf-gcc ...
- ./configure --build=x86_64-unknown-linux-gnu --host=armv7l-unknown-linux-gnueabihf
- make all -j
- Observe the mentioned failure
Comment 12 Joe Hermaszewski 2020-11-08 16:03:55 UTC
A much more simple reproducer for the error message I mentioned (from GHC's configure script):

cat >actest.s <<-EOF
  .globl _start
  .p2align 4
_start:
  bkpt

.data
  .globl data_object
object_reference:
  .long data_object
  .size object_reference, 4
EOF

cat >aclib.s <<-EOF
  .data
  .globl data_object
  .type data_object, %object
  .size data_object, 4
data_object:
    .long 123
EOF

$AS -o aclib.o aclib.s
$LD -shared -o aclib.so aclib.o

$AS -o actest.o actest.s
$LD -o actest actest.o aclib.so
Comment 13 Dirk Mueller 2022-10-14 15:25:11 UTC
Created attachment 14399 [details]
Updated patch against master

Updated patch with the changes necessary to build against binutils 2.39
Comment 14 Nick Clifton 2022-10-17 10:34:16 UTC
(In reply to Dirk Mueller from comment #13)
> Updated patch with the changes necessary to build against binutils 2.39

The patch still suffers from the problem triggered by the example in comment #12.
Comment 15 Richard Biener 2023-01-24 12:58:25 UTC
It also seems to cause

extern void *stderr;
int main()
{
  volatile void *x = stderr;
}

failing to link with

/usr/lib/gcc/armv7hl-suse-linux-gnueabi/12/../../../../armv7hl-suse-linux-gnueabi/bin/ld: /tmp/ccyhHiPR.o(.text+0x8): unresolvable R_ARM_MOVW_ABS_NC relocation against symbol `stderr@@GLIBC_2.4'
Comment 16 Nick Clifton 2023-01-27 12:10:33 UTC
(In reply to Richard Biener from comment #15)
Hi Richard,

> It also seems to cause

Is there any chance that you could create a reproducer that does not need a compiler or  the standard libraries ?  I do not have an arm cross compiler (or native compiler) available to me...

Cheers
  Nick