aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF
diff options
context:
space:
mode:
authorwanglei <wanglei@loongson.cn>2024-06-14 15:11:59 +0800
committerGitHub <noreply@github.com>2024-06-14 15:11:59 +0800
commitc4a1440c149d3ea03f14fd6858b6be3a2faf9af6 (patch)
tree48bbbeeb5c7565b906dbd2bbfa96cedcc5fc9db9 /lld/ELF
parent4ab37e430d960b975bfdaf95516a39ea3468f7a1 (diff)
downloadllvm-c4a1440c149d3ea03f14fd6858b6be3a2faf9af6.zip
llvm-c4a1440c149d3ea03f14fd6858b6be3a2faf9af6.tar.gz
llvm-c4a1440c149d3ea03f14fd6858b6be3a2faf9af6.tar.bz2
[lld][ELF] Add basic TLSDESC support for LoongArch
LoongArch does not yet implement transition from TLSDESC to LE/IE, so TLSDESC dynamic relocation needs to be generated for each desc, which is ultimately handled by the dynamic linker. The test cases reference RISC-V: #79239 Reviewed By: MaskRay, SixWeining Pull Request: https://github.com/llvm/llvm-project/pull/94451
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Arch/LoongArch.cpp40
-rw-r--r--lld/ELF/InputSection.cpp2
-rw-r--r--lld/ELF/Relocations.cpp12
-rw-r--r--lld/ELF/Relocations.h1
4 files changed, 55 insertions, 0 deletions
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 2c5d5df..c6ee73f 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -98,11 +98,13 @@ uint64_t elf::getLoongArchPageDelta(uint64_t dest, uint64_t pc, RelType type) {
case R_LARCH_PCALA64_LO20:
case R_LARCH_GOT64_PC_LO20:
case R_LARCH_TLS_IE64_PC_LO20:
+ case R_LARCH_TLS_DESC64_PC_LO20:
pcalau12i_pc = pc - 8;
break;
case R_LARCH_PCALA64_HI12:
case R_LARCH_GOT64_PC_HI12:
case R_LARCH_TLS_IE64_PC_HI12:
+ case R_LARCH_TLS_DESC64_PC_HI12:
pcalau12i_pc = pc - 12;
break;
default:
@@ -190,11 +192,13 @@ LoongArch::LoongArch() {
tlsModuleIndexRel = R_LARCH_TLS_DTPMOD64;
tlsOffsetRel = R_LARCH_TLS_DTPREL64;
tlsGotRel = R_LARCH_TLS_TPREL64;
+ tlsDescRel = R_LARCH_TLS_DESC64;
} else {
symbolicRel = R_LARCH_32;
tlsModuleIndexRel = R_LARCH_TLS_DTPMOD32;
tlsOffsetRel = R_LARCH_TLS_DTPREL32;
tlsGotRel = R_LARCH_TLS_TPREL32;
+ tlsDescRel = R_LARCH_TLS_DESC32;
}
gotRel = symbolicRel;
@@ -294,6 +298,10 @@ int64_t LoongArch::getImplicitAddend(const uint8_t *buf, RelType type) const {
case R_LARCH_JUMP_SLOT:
// These relocations are defined as not having an implicit addend.
return 0;
+ case R_LARCH_TLS_DESC32:
+ return read32le(buf + 4);
+ case R_LARCH_TLS_DESC64:
+ return read64le(buf + 8);
}
}
@@ -486,6 +494,19 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
return config->relax ? R_RELAX_HINT : R_NONE;
case R_LARCH_ALIGN:
return R_RELAX_HINT;
+ case R_LARCH_TLS_DESC_PC_HI20:
+ case R_LARCH_TLS_DESC64_PC_LO20:
+ case R_LARCH_TLS_DESC64_PC_HI12:
+ return R_LOONGARCH_TLSDESC_PAGE_PC;
+ case R_LARCH_TLS_DESC_PC_LO12:
+ case R_LARCH_TLS_DESC_LD:
+ case R_LARCH_TLS_DESC_HI20:
+ case R_LARCH_TLS_DESC_LO12:
+ case R_LARCH_TLS_DESC64_LO20:
+ case R_LARCH_TLS_DESC64_HI12:
+ return R_TLSDESC;
+ case R_LARCH_TLS_DESC_CALL:
+ return R_TLSDESC_CALL;
// Other known relocs that are explicitly unimplemented:
//
@@ -510,6 +531,8 @@ bool LoongArch::usesOnlyLowPageBits(RelType type) const {
case R_LARCH_GOT_LO12:
case R_LARCH_GOT_PC_LO12:
case R_LARCH_TLS_IE_PC_LO12:
+ case R_LARCH_TLS_DESC_LO12:
+ case R_LARCH_TLS_DESC_PC_LO12:
return true;
}
}
@@ -594,6 +617,8 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_LE_LO12:
case R_LARCH_TLS_IE_PC_LO12:
case R_LARCH_TLS_IE_LO12:
+ case R_LARCH_TLS_DESC_PC_LO12:
+ case R_LARCH_TLS_DESC_LO12:
write32le(loc, setK12(read32le(loc), extractBits(val, 11, 0)));
return;
@@ -609,6 +634,8 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_LD_HI20:
case R_LARCH_TLS_GD_PC_HI20:
case R_LARCH_TLS_GD_HI20:
+ case R_LARCH_TLS_DESC_PC_HI20:
+ case R_LARCH_TLS_DESC_HI20:
write32le(loc, setJ20(read32le(loc), extractBits(val, 31, 12)));
return;
@@ -620,6 +647,8 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_LE64_LO20:
case R_LARCH_TLS_IE64_PC_LO20:
case R_LARCH_TLS_IE64_LO20:
+ case R_LARCH_TLS_DESC64_PC_LO20:
+ case R_LARCH_TLS_DESC64_LO20:
write32le(loc, setJ20(read32le(loc), extractBits(val, 51, 32)));
return;
@@ -631,6 +660,8 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_TLS_LE64_HI12:
case R_LARCH_TLS_IE64_PC_HI12:
case R_LARCH_TLS_IE64_HI12:
+ case R_LARCH_TLS_DESC64_PC_HI12:
+ case R_LARCH_TLS_DESC64_HI12:
write32le(loc, setK12(read32le(loc), extractBits(val, 63, 52)));
return;
@@ -679,6 +710,15 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_RELAX:
return; // Ignored (for now)
+ case R_LARCH_TLS_DESC_LD:
+ return; // nothing to do.
+ case R_LARCH_TLS_DESC32:
+ write32le(loc + 4, val);
+ return;
+ case R_LARCH_TLS_DESC64:
+ write64le(loc + 8, val);
+ return;
+
default:
llvm_unreachable("unknown relocation");
}
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index f4287bc..be12218 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -877,6 +877,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
return in.got->getTlsDescAddr(sym) + a - in.gotPlt->getVA();
case R_AARCH64_TLSDESC_PAGE:
return getAArch64Page(in.got->getTlsDescAddr(sym) + a) - getAArch64Page(p);
+ case R_LOONGARCH_TLSDESC_PAGE_PC:
+ return getLoongArchPageDelta(in.got->getTlsDescAddr(sym) + a, p, type);
case R_TLSGD_GOT:
return in.got->getGlobalDynOffset(sym) + a;
case R_TLSGD_GOTPLT:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 04db413..1b08339 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1297,6 +1297,18 @@ static unsigned handleTlsRelocation(RelType type, Symbol &sym,
if (config->emachine == EM_MIPS)
return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
+
+ // LoongArch does not yet implement transition from TLSDESC to LE/IE, so
+ // generate TLSDESC dynamic relocation for the dynamic linker to handle.
+ if (config->emachine == EM_LOONGARCH &&
+ oneof<R_LOONGARCH_TLSDESC_PAGE_PC, R_TLSDESC, R_TLSDESC_CALL>(expr)) {
+ if (expr != R_TLSDESC_CALL) {
+ sym.setFlags(NEEDS_TLSDESC);
+ c.addReloc({expr, type, offset, addend, &sym});
+ }
+ return 1;
+ }
+
bool isRISCV = config->emachine == EM_RISCV;
if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
diff --git a/lld/ELF/Relocations.h b/lld/ELF/Relocations.h
index b7b9c09..e299d23 100644
--- a/lld/ELF/Relocations.h
+++ b/lld/ELF/Relocations.h
@@ -116,6 +116,7 @@ enum RelExpr {
R_LOONGARCH_GOT,
R_LOONGARCH_GOT_PAGE_PC,
R_LOONGARCH_TLSGD_PAGE_PC,
+ R_LOONGARCH_TLSDESC_PAGE_PC,
};
// Architecture-neutral representation of relocation.