Bug 14603

Summary: no reloc emitted for ld generated veneers for ARM
Product: binutils Reporter: Marcin Bukat <marcin.bukat>
Component: ldAssignee: Not yet assigned to anyone <unassigned>
Status: REOPENED ---    
Severity: normal CC: mgretton, sam
Priority: P2    
Version: unspecified   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:
Attachments: testcase

Description Marcin Bukat 2012-09-21 08:43:49 UTC
Created attachment 6642 [details]
testcase

The simple test case provided shows that 0x80000000 constant used as jump address in veneer generated by ld has no reloc associated. I believe this is a bug (or inconsistency at least). I noticed this working on bFLT loader for the target with memory split - fast internal ram and regular dram. With current ld behavior runtime relocation is broken by this.

The workaround is to use -mlong-calls when compiling C sources but this imposes performance penalty as well as does not solve the problem of asm files.

Tested with 2.20.1 as well as with current snapshot.
Comment 1 Matthew Gretton-Dann 2012-09-21 09:13:48 UTC
The testcase doesn't mark the branch destination as a function.  The linker will only veneer function calls.

The test should work fine with the following source:

.text
.arm
.global _start
_start:
    bl far_foo

.section .far_text,"ax"
.arm
.global far_foo
.type far_foo, %function
@ For thumb you would instead do: .thumb_func
far_foo:
    nop
    bx lr 

For further examples see ld/testsuite/ld-arm/farcall-*.s source files.
Comment 2 Marcin Bukat 2012-09-21 09:19:32 UTC
Running provided testcase I get this:

test.elf:     file format elf32-littlearm


Disassembly of section .text:

00000000 <_start>:
   0:	eb000000 	bl	8 <__far_foo_veneer>
			0: R_ARM_CALL	far_foo
   4:	00000000 	andeq	r0, r0, r0

00000008 <__far_foo_veneer>:
   8:	e51ff004 	ldr	pc, [pc, #-4]	; c <__far_foo_veneer+0x4>
   c:	80000000 	.word	0x80000000

Disassembly of section .far_text:

80000000 <far_foo>:
80000000:	e1a00000 	nop			; (mov r0, r0)
80000004:	e12fff1e 	bx	lr
			80000004: R_ARM_V4BX	*ABS*


There is clearly veneer inserted as well as with your proposed change. But this is not the case. The bug is about lack of relocation in veneer jump address which still holds.
Comment 3 Matthew Gretton-Dann 2012-09-21 09:43:34 UTC
Surely as you have linked the image together and it is now fully relocated, the linker doesn't need to create relocations for veneers?

The test case you provide only contains static relocations.  These are applied once at static link time, and cannot - in general - be reapplied after linking (as if the relocations have been specified with .rel sections the necessary addend has been destroyed).

If you want to do runtime linking and relocation you need to use dynamic relocations which do not get fixed by the static linker.
Comment 4 Marcin Bukat 2012-09-21 11:09:02 UTC
elf2flt allows you to take fully resolved elf binary produced with --emit-relocs and produce flat file which is relocated at load time. I want to archive the same but with address space split. I do understand why usually it is not needed but veneer inserted by ld can be seen like any other code coming from object files. It does introduce new symbols, but does not create relocation for this symbols. I see this as inconsistency at least.