[llvm-dev] Do I need to modify the AddrLoc of LLD for ARC target?
Leslie Zhai via llvm-dev
llvm-dev at lists.llvm.org
Sun Sep 17 19:28:27 PDT 2017
Hi Peter,
Map file about LD for ARC target
https://drive.google.com/open?id=0ByE8c-y74l_uRWpQdUh2c0VXZ1k
LLD for ARC https://drive.google.com/open?id=0ByE8c-y74l_ueGVuYkR0a3RSWjQ
arm-thumb-undefined-weak.s
https://github.com/llvm-mirror/lld/blob/master/test/ELF/arm-thumb-undefined-weak.s
$ llvm/build/bin/llvm-mc -filetype=obj
-triple=thumbv7a-none-linux-gnueabi arm-thumb-undefined-weak.s -o
arm-thumb-undefined-weak.o
$ llvm/build/bin/ld.lld -o arm-thumb-undefined-weak-lld
arm-thumb-undefined-weak.o -Ttext=11006
$ arm-linux-gnu-ld -o arm-thumb-undefined-weak-ld
arm-thumb-undefined-weak.o -Ttext=11006
$ arm-linux-gnu-readelf -r arm-thumb-undefined-weak.o
Relocation section '.rel.text' at offset 0x8c contains 6 entries:
Offset Info Type Sym.Value Sym. Name
00000000 00000333 R_ARM_THM_JUMP19 00000000 target
00000004 0000031e R_ARM_THM_JUMP24 00000000 target
00000008 0000030a R_ARM_THM_CALL 00000000 target
0000000c 0000030a R_ARM_THM_CALL 00000000 target
00000010 00000332 R_ARM_THM_MOVT_PR 00000000 target
00000014 00000331 R_ARM_THM_MOVW_PR 00000000 target
DEBUG: lld: R_ARM_THM_JUMP19 TargetVA: 0 A: -4 P: 69640 Align: 4 VMA:
69640 Output Offset: 0 Reloc Offset: 0
DEBUG: lld: R_ARM_THM_JUMP24 TargetVA: 0 A: -4 P: 69644 Align: 4 VMA:
69640 Output Offset: 0 Reloc Offset: 4
DEBUG: lld: R_ARM_THM_CALL TargetVA: 1 A: -4 P: 69648 Align: 4 VMA:
69640 Output Offset: 0 Reloc Offset: 8
DEBUG: lld: R_ARM_THM_CALL TargetVA: 1 A: -4 P: 69652 Align: 4 VMA:
69640 Output Offset: 0 Reloc Offset: 12
DEBUG: lld: R_ARM_THM_MOVT_PREL TargetVA: 0 A: 0 P: 69656 Align: 4 VMA:
69640 Output Offset: 0 Reloc Offset: 16
DEBUG: lld: R_ARM_THM_MOVW_PREL_NC TargetVA: 0 A: 0 P: 69660 Align: 4
VMA: 69640 Output Offset: 0 Reloc Offset: 20
DEBUG: arm-linux-gnu-ld: R_ARM_THM_JUMP19: VMA: 69638 Output Offset: 2
Reloc Offset: 0
DEBUG: arm-linux-gnu-ld: R_ARM_THM_JUMP24: VMA: 69638 Output Offset: 2
Reloc Offset: 4
DEBUG: arm-linux-gnu-ld: R_ARM_THM_CALL: VMA: 69638 Output Offset: 2
Reloc Offset: 8
DEBUG: arm-linux-gnu-ld: R_ARM_THM_CALL: VMA: 69638 Output Offset: 2
Reloc Offset: 12
DEBUG: arm-linux-gnu-ld: R_ARM_THM_MOVT_PREL: VMA: 69638 Output Offset:
2 Reloc Offset: 16
DEBUG: arm-linux-gnu-ld: R_ARM_THM_MOVW_PREL_NC: VMA: 69638 Output
Offset: 2 Reloc Offset: 20
$ llvm/build/bin/llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d
arm-thumb-undefined-weak-lld
arm-thumb-undefined-weak-lld: file format ELF32-arm-little
Disassembly of section .text:
_start:
11008: 00 f0 00 80 beq.w #0 <_start+0x4>
1100c: 00 f0 00 b8 b.w #0 <_start+0x8>
11010: 00 f0 00 f8 bl #0
11014: 00 f0 00 f8 bl #0
11018: c0 f2 00 00 movt r0, #0
1101c: 40 f2 00 00 movw r0, #0
$ llvm/build/bin/llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d
arm-thumb-undefined-weak-ld
arm-thumb-undefined-weak-ld: file format ELF32-arm-little
Disassembly of section .text:
.text:
11006: 00 00 movs r0, r0
_start:
11008: 2e f4 fa af beq.w #-69644
1100c: 00 e0 b #0 <_start+0x8>
1100e: 00 bf nop
11010: 00 e0 b #0 <_start+0xC>
11012: 00 bf nop
11014: 00 e0 b #0 <_start+0x10>
11016: 00 bf nop
11018: cf f6 fe 70 movt r0, #65534
1101c: 4e f6 e4 70 movw r0, #61412
在 2017年09月15日 20:49, Peter Smith 写道:
> Just a thought I had about the calculation of P. I think that
> following the ld approach too closely may be a mistake.
>
> I'm speculating that the reason for this change in the value of P is
> similar to the situation in Arm for a Thumb BLX immediate instruction
> (Branch Link and Exchange with the immediate an offset from the PC).
> When calculating the target address the immediate is added to
> Align(PC, 4) where Align rounds down to nearest 4-byte boundary. The
> linker needs to account for this when resolving the relocation
> R_ARM_THM_CALL.
>
> To handle the alignment difference for this one special case in lld I
> accounted for the alignment difference in relocateOne. You may be able
> to use a similar method for Arc rather than writing modifyARCAddrLoc.
> Again I know nothing about Arc so you'll need to look at the
> Architecture reference manual to understand what the instruction the
> relocation applies to works.
>
> Peter
>
>
> On 15 September 2017 at 04:19, Leslie Zhai <lesliezhai at llvm.org.cn> wrote:
>> Hi Peter,
>>
>> Thanks for your kind response!
>>
>>
>> 在 2017年09月14日 17:36, Peter Smith 写道:
>>> Hello Leslie,
>>>
>>> I think we are going to need to know a bit more about the ELF ABI for
>>> what looks like the ArcCompact before we can help you.
>> https://github.com/foss-for-synopsys-dwc-arc-processors/arc-ABI-manual
>>
>> But I prefer to read bfd linker's source code about ARC instead:
>> 1. Specific e_flags
>> https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/blob/arc-2017.09/include/elf/arc.h
>> 2. Relocation define
>> https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/blob/arc-2017.09/include/elf/arc-reloc.def
>> 3. Relocation replace function
>> https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/blob/arc-2017.09/include/opcode/arc-func.h
>> 4. Calculation of S, A, P, PDATA, GOT, etc.
>> https://github.com/foss-for-synopsys-dwc-arc-processors/binutils-gdb/blob/arc-2017.09/bfd/elf32-arc.c#L1156
>>
>>
>>> LLD's calculation of P (the place to be relocated) is as it is in the
>>> generic ELF specification. The Rel.Offset corresponds to the ELF
>>> r_offset field. This is covered by: "For a relocatable file, the value
>>> is the byte offset from the beginning of the section to the storage
>>> unit affected by the relocation."
>>>
>>> For LLD we are calculating the virtual address (VA) of P, as I
>>> understand it this is equivalent to the vma used in BFD. Assuming that
>>> the relocation is relocating a regular InputSection from the
>>> basic-arc.o object then the LLD calculation of P =
>>> getOutputSection()->Addr + getOffset(Rel.Offset); translates to: (VA
>>> of OutputSection) + (Offset of InputSection within OutputSection) +
>>> (Offset within InputSection given by r_offset)
>>>
>>> The BFD linker seems to be doing the equivalent calculation with an
>>> extra modification of the (Offset within InputSection given by
>>> r_offset) and is rounding down the result to the nearest 4-byte
>>> boundary. This looks unfamiliar to me, and could well be specific to
>>> ArcCompact. I think that you will need to refer to the ELF ABI
>>> documentation as this should tell you if there are any processor
>>> specific modifications to generic ELF that you have to follow.
>> I implemented the MOD P for ARC:
>>
>> static void modifyARCAddrLoc(uint64_t &AddrLoc, const uint16_t EMachine,
>> RelExpr Expr, uint32_t Type, uint64_t VMA,
>> uint64_t OutSecOff, uint64_t RelOff) {
>> if (EMachine != EM_ARC_COMPACT || EMachine != EM_ARC_COMPACT2 ||
>> Expr != R_PC || Expr != R_GOT_PC) {
>> return;
>> }
>>
>> uint64_t M = 0;
>> if (Type == R_ARC_32_PCREL || Type == R_ARC_PC32 || Type == R_ARC_GOTPC32
>> ||
>> Type == R_ARC_GOTPC) {
>> M = 4; // bitsize >= 32 ? 4 : 0
>> }
>> AddrLoc = (VMA + OutSecOff + RelOff - M) & ~0x3;
>> }
>>
>> modifyARCAddrLoc(AddrLoc, Config->EMachine, Expr, Type,
>> getOutputSection()->Addr, <-- VMA is important!
>> cast<InputSection>(this)->OutSecOff, Rel.Offset);
>>
>>
>>> The other thing that you should do is try and work out why the VA
>>> (vma) is 6 in LD and 8 in LLD and whether this is actually a problem.
>>> The VA of the OutputSection is not guaranteed to be the same between
>>> different linkers so it may have just been that differences in order
>>> of InputSections or alignment has caused a different VA. I would check
>>> the output of the linker map file to see where it placed the Output
>>> and Input Sections to see what the answer should be.
>> LLD's getOutputSection()->Addr =
>> https://github.com/llvm-mirror/lld/blob/master/ELF/LinkerScript.cpp#L530
>>
>>
>>
>>> In summary:
>>> It looks like there are some Arc specific things that might need to be
>>> done. Unfortunately I don't have any experience with Arc, and I'm not
>>> sure the other people that work on LLD do either. I suggest looking at
>>> the public ABI documentation and making any arguments for changes
>>> based on that documentation, it is worth assuming that we know nothing
>>> about Arc, don't have the documentation to hand and don't know where
>>> to find it!
>>>
>>> Hope that is of some help, with a bit more context I might be able to
>>> help a bit more, unfortunately I can't spend a lot of time learning
>>> about Arc.
>>>
>>> Peter
>>>
>>>
>>> On 14 September 2017 at 07:16, Leslie Zhai via llvm-dev
>>> <llvm-dev at lists.llvm.org> wrote:
>>>> Hi LLVM developers,
>>>>
>>>> basic-arc.s:
>>>>
>>>> main:
>>>> bl memset
>>>>
>>>> $ arc-elf32-gcc -mcpu=arc600 -o basic-arc.o -c
>>>>
>>>> $ arc-elf32-readelf -r basic-arc.o
>>>>
>>>> Relocation section '.rela.text' at offset 0xd4 contains 1 entries:
>>>> Offset Info Type Sym.Value Sym. Name + Addend
>>>> 00000000 00000611 R_ARC_S25W_PCREL 00000000 memset + 0
>>>>
>>>> High address: 0x0
>>>>
>>>> $ arc-elf32-ld -o basic-arc basic-arc.o
>>>> -L/opt/arc-gnu/lib/gcc/arc-elf32/7.1.1/arc600
>>>> -L/opt/arc-gnu/lib/gcc/arc-elf32/7.1.1/../../../../arc-elf32/lib/arc600
>>>> -L/opt/arc-gnu/lib/gcc/arc-elf32/7.1.1
>>>> -L/opt/arc-gnu/lib/gcc/arc-elf32/7.1.1/../../../../arc-elf32/lib
>>>> --start-group -lgcc -lc -lnosys --end-group -Ttext=0
>>>>
>>>> DEBUG: arc-ld: R_ARC_S25W_PCREL relocation: 1 S: 4 A: 0 P: 0 = (vma: 0 +
>>>> output_offset: 0 + reloc_offset: 0 - 0) & ~0x3
>>>> DEBUG: arc-ld: type: R_ARC_S25W_PCREL insn: 2054
>>>>
>>>> $ ld.lld -o basic-arc-lld basic-arc.o $ARC_LINKER_LIB -Ttext=0
>>>>
>>>> DEBUG: lld: R_ARC_S25W_PCREL TargetVA: 4 A: 0 P: 0 <-- same P as arc-ld
>>>> DEBUG: lld: R_ARC_S25W_PCREL: Insn: 2050 Rel: 1
>>>> DEBUG: lld: R_ARC_S25W_PCREL: Insn: 2054 <-- same relocation value as
>>>> arc-ld
>>>>
>>>> But with several different high address *not* 0x0, such as 0x6:
>>>>
>>>> DEBUG: arc-ld: R_ARC_S25W_PCREL relocation: 2 S: 12 A: 0 P: 4 = (vma: 6 +
>>>> output_offset: 0 + reloc_offset: 0 - 0) & ~0x3
>>>> DEBUG: arc-ld: type: R_ARC_S25W_PCREL insn: 2058
>>>>
>>>> DEBUG: lld: R_ARC_S25W_PCREL TargetVA: 4 A: 0 P: 8 <-- different P?
>>>> DEBUG: lld: R_ARC_S25W_PCREL: Insn: 2050 Rel: 1
>>>> DEBUG: lld: R_ARC_S25W_PCREL: Insn: 2054 <-- different relocation value
>>>>
>>>> How arc-ld calculates P?
>>>>
>>>> P = ((reloc_data.input_section->output_section ?
>>>> reloc_data.input_section->output_section->vma : 0) +
>>>> reloc_data.input_section->output_offset + (reloc_data.reloc_offset -
>>>> (reloc_data.bitsize >= 32 ? 4 : 0))) & ~0x3;
>>>>
>>>> for example, R_ARC_S25W_PCREL's bitsize < 32, P = (6 + 0 + 0 - 0) & ~0x3
>>>> =
>>>> 4, when vma is 6, output and reloc offset is 0.
>>>>
>>>> How LLD calculates P (AddrLoc)?
>>>>
>>>> P = getOutputSection()->Addr + getOffset(Rel.Offset);
>>>>
>>>> for example, the same high address 0x6, LLD's P is 8, different with
>>>> arc-ld?
>>>> so do I need to modify the value of P for R_PC case in the
>>>> getRelocTargetVA?
>>>> please give me some hints, thanks a lot!
>>>>
>>>>
>>>> PS: arc-ld R_ARC_S25W_PCREL's FORMULA is: ( S + A ) - P ) >> 2, and it
>>>> needs
>>>> middle endian convert, so:
>>>>
>>>> Insn = middleEndianConvert (insn, TRUE);
>>>>
>>>> Insn = replaceDisp25w(Insn, ( S + A ) - P ) >> 2);
>>>>
>>>> Insn = middleEndianConvert (insn, TRUE);
>>>>
>>>> write32le(Loc, Insn);
>>>>
>>>> --
>>>> Regards,
>>>> Leslie Zhai - https://reviews.llvm.org/p/xiangzhai/
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> LLVM Developers mailing list
>>>> llvm-dev at lists.llvm.org
>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>> --
>> Regards,
>> Leslie Zhai - https://reviews.llvm.org/p/xiangzhai/
>>
>>
>>
--
Regards,
Leslie Zhai - https://reviews.llvm.org/p/xiangzhai/
More information about the llvm-dev
mailing list