[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
Thu Sep 14 20:19:04 PDT 2017


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/





More information about the llvm-dev mailing list