diff options
author | Rui Ueyama <ruiu@google.com> | 2018-08-09 17:59:56 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2018-08-09 17:59:56 +0000 |
commit | d731f7efd3b0c74951c4c657116e69d883386798 (patch) | |
tree | 04af570d191c75468c53128bb7b117e116942057 /lld/ELF/InputSection.cpp | |
parent | 5ccc4543303f9a490233075f2083d8fa04459a53 (diff) |
Support RISC-V
Patch by PkmX.
This patch makes lld recognize RISC-V target and implements basic
relocation for RV32/RV64 (and RVC). This should be necessary for static
linking ELF applications.
The ABI documentation for RISC-V can be found at:
https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md.
Note that the documentation is far from complete so we had to figure out
some details from bfd.
The patch should be pretty straightforward. Some highlights:
- A new relocation Expr R_RISCV_PC_INDIRECT is added. This is needed as
the low part of a PC-relative relocation is linked to the corresponding
high part (auipc), see:
https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#pc-relative-symbol-addresses
- LLVM's MC support for RISC-V is very incomplete (we are working on
this), so tests are given in objectyaml format with the original
assembly included in the comments. Once we have complete support for
RISC-V in MC, we can switch to llvm-as/llvm-objdump.
- We don't support linker relaxation for now as it requires greater
changes to lld that is beyond the scope of this patch. Once this is
accepted we can start to work on adding relaxation to lld.
Differential Revision: https://reviews.llvm.org/D39322
Diffstat (limited to 'lld/ELF/InputSection.cpp')
-rw-r--r-- | lld/ELF/InputSection.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 597e8227217..48603a30e6a 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -481,6 +481,33 @@ static uint64_t getARMStaticBase(const Symbol &Sym) { return OS->PtLoad->FirstSec->Addr; } +// For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually +// points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA +// is calculated using PCREL_HI20's symbol. +// +// This function returns the R_RISCV_PCREL_HI20 relocation from +// R_RISCV_PCREL_LO12's symbol and addend. +Relocation *lld::elf::getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) { + const Defined *D = cast<Defined>(Sym); + InputSection *IS = cast<InputSection>(D->Section); + + if (Addend != 0) + warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " + + IS->getObjMsg(D->Value) + " is ignored"); + + // Relocations are sorted by offset, so we can use std::equal_range to do + // binary search. + auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), + D->Value, RelocationOffsetComparator{}); + for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It) + if (isRelExprOneOf<R_PC>(It->Expr)) + return &*It; + + error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + + " without an associated R_RISCV_PCREL_HI20 relocation"); + return nullptr; +} + static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, uint64_t P, const Symbol &Sym, RelExpr Expr) { switch (Expr) { @@ -567,6 +594,13 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, Dest = getAArch64Page(Sym.getVA(A)); return Dest - getAArch64Page(P); } + case R_RISCV_PC_INDIRECT: { + const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A); + if (!HiRel) + return 0; + return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), + *HiRel->Sym, HiRel->Expr); + } case R_PC: { uint64_t Dest; if (Sym.isUndefWeak()) { |