Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
181dd8561e
!12 [sync] PR-11: [Backport][LLD] Support relax feature on LoongArch
From: @openeuler-sync-bot 
Reviewed-by: @cf-zhao 
Signed-off-by: @cf-zhao
2024-04-12 07:24:41 +00:00
Ami-zhang
76fcccd0ef [Backport][LoongArch] Support relax feature
(cherry picked from commit c2c6c3baaa66ddb005a27824f861acbfa26fd8bd)
2024-04-11 09:30:29 +08:00
openeuler-ci-bot
0143bceffa
!10 Update to 17.0.6
From: @zj94 
Reviewed-by: @liyunfei33, @cf-zhao 
Signed-off-by: @cf-zhao
2024-01-04 07:57:19 +00:00
zhoujing
84aff0d930 Update to LLVM 17.0.6
1.Use llvm-cmake-utils package
2023-12-08 15:07:08 +08:00
openeuler-ci-bot
c95df9cfbd
!7 Make spec file support both system-version and multi-version
From: @cf-zhao 
Reviewed-by: @eastb233 
Signed-off-by: @eastb233
2023-07-17 01:26:10 +00:00
cf_zhao
7a7f526d00 Make spec file support both system-version and multi-version 2023-07-13 21:23:07 +08:00
openeuler-ci-bot
edd0e50379
!2 升级到15.0.7
From: @cf-zhao 
Reviewed-by: @zhongyunde, @eastb233 
Signed-off-by: @eastb233, @zhongyunde
2023-05-16 11:53:30 +00:00
cf_zhao
f44e6fa9fc Update to 15.0.7 2023-05-15 20:21:56 +08:00
openeuler-ci-bot
d81cf8022e
!1 引入llvm lld 12.0.1版本
From: @cf-zhao 
Reviewed-by: @eastb233 
Signed-off-by: @eastb233
2023-02-20 02:17:50 +00:00
cf_zhao
fe23fa4d5c Import lld 12.0.1` 2023-02-18 10:57:36 +08:00
9 changed files with 1726 additions and 35 deletions

View File

@ -0,0 +1,78 @@
From 7f14e7c1b116fc865ddebb78e67816bfc5216178 Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
Date: Wed, 15 Nov 2023 09:57:45 +0800
Subject: [PATCH 01/14] [lld][LoongArch] Support the R_LARCH_{ADD,SUB}6
relocation type (#72190)
The R_LARCH_{ADD,SUB}6 relocation type are usually used by DwarfCFA to
calculate a tiny offset. They appear after binutils 2.41, with GAS
enabling relaxation by default.
(cherry picked from commit 72accbfd0a1023b3182202276904120524ff9200)
Change-Id: Iad676e522f11c52e5dc381243f1df60edcef58f5
---
lld/ELF/Arch/LoongArch.cpp | 8 ++++++++
lld/test/ELF/loongarch-add-sub.s | 6 +++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 04ddb4682917..d3a538577a59 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -444,10 +444,12 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_TLS_LE64_LO20:
case R_LARCH_TLS_LE64_HI12:
return R_TPREL;
+ case R_LARCH_ADD6:
case R_LARCH_ADD8:
case R_LARCH_ADD16:
case R_LARCH_ADD32:
case R_LARCH_ADD64:
+ case R_LARCH_SUB6:
case R_LARCH_SUB8:
case R_LARCH_SUB16:
case R_LARCH_SUB32:
@@ -650,6 +652,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
write32le(loc, setK12(read32le(loc), extractBits(val, 63, 52)));
return;
+ case R_LARCH_ADD6:
+ *loc = (*loc & 0xc0) | ((*loc + val) & 0x3f);
+ return;
case R_LARCH_ADD8:
*loc += val;
return;
@@ -662,6 +667,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_ADD64:
write64le(loc, read64le(loc) + val);
return;
+ case R_LARCH_SUB6:
+ *loc = (*loc & 0xc0) | ((*loc - val) & 0x3f);
+ return;
case R_LARCH_SUB8:
*loc -= val;
return;
diff --git a/lld/test/ELF/loongarch-add-sub.s b/lld/test/ELF/loongarch-add-sub.s
index 63a3f7de179e..35f8a053d69c 100644
--- a/lld/test/ELF/loongarch-add-sub.s
+++ b/lld/test/ELF/loongarch-add-sub.s
@@ -6,7 +6,7 @@
# RUN: llvm-readelf -x .rodata %t.la64 | FileCheck --check-prefix=CHECK %s
# CHECK: section '.rodata':
# CHECK-NEXT: 0x9876543210 10325476 98badcfe 804602be 79ffffff
-# CHECK-NEXT: 0x9876543220 804602be 804680
+# CHECK-NEXT: 0x9876543220 804602be 80468097
.text
.global _start
@@ -34,3 +34,7 @@ quux:
.byte 0
.reloc quux, R_LARCH_ADD8, 1b
.reloc quux, R_LARCH_SUB8, 2b
+qux:
+ .byte 0b10000000
+ .reloc qux, R_LARCH_ADD6, qux
+ .reloc qux, R_LARCH_SUB6, 2b
--
2.20.1

View File

@ -0,0 +1,239 @@
From d53182c7fcc371f575fd71fa74e28220db6e9b82 Mon Sep 17 00:00:00 2001
From: Job Noorman <jnoorman@igalia.com>
Date: Sat, 9 Sep 2023 10:24:16 +0200
Subject: [PATCH 09/14] [ELF][RISCV] Implement --emit-relocs with relaxation
Linker relaxation may change relocations (offsets and types). However,
when --emit-relocs is used, relocations are simply copied from the input
section causing a mismatch with the corresponding (relaxed) code
section.
This patch fixes this as follows: for non-relocatable RISC-V binaries,
`InputSection::copyRelocations` reads relocations from the relocated
section's `relocations` array (since this gets updated by the relaxation
code). For all other cases, relocations are read from the input section
directly as before.
In order to reuse as much code as possible, and to keep the diff small,
the original `InputSection::copyRelocations` is changed to accept the
relocations as a range of `Relocation` objects. This means that, in the
general case when reading from the input section, raw relocations need
to be converted to `Relocation`s first, which introduces quite a bit of
boiler plate. It also means there's a slight code size increase due to
the extra instantiations of `copyRelocations` (for both range types).
Reviewed By: MaskRay
Differential Revision: https://reviews.llvm.org/D159082
(cherry picked from commit 649cac3b627fa3d466b8807536c8be970cc8c32f)
Change-Id: I53aeeeed4bea0d74c5571bc90405bcbd363781b2
---
lld/ELF/InputSection.cpp | 56 ++++++++++++++++-----
lld/ELF/InputSection.h | 6 ++-
lld/test/ELF/riscv-relax-emit-relocs.s | 69 ++++++++++++++++++++++++++
3 files changed, 117 insertions(+), 14 deletions(-)
create mode 100644 lld/test/ELF/riscv-relax-emit-relocs.s
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 2edaa2b40493..1aff6b968d86 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -349,29 +349,61 @@ InputSectionBase *InputSection::getRelocatedSection() const {
return sections[info];
}
+template <class ELFT, class RelTy>
+void InputSection::copyRelocations(uint8_t *buf) {
+ if (config->relax && !config->relocatable && config->emachine == EM_RISCV) {
+ // On RISC-V, relaxation might change relocations: copy from
+ // internal ones that are updated by relaxation.
+ InputSectionBase *sec = getRelocatedSection();
+ copyRelocations<ELFT, RelTy>(buf, llvm::make_range(sec->relocations.begin(),
+ sec->relocations.end()));
+ } else {
+ // Convert the raw relocations in the input section into Relocation objects
+ // suitable to be used by copyRelocations below.
+ struct MapRel {
+ const ObjFile<ELFT> &file;
+ Relocation operator()(const RelTy &rel) const {
+ // RelExpr is not used so set to a dummy value.
+ return Relocation{R_NONE, rel.getType(config->isMips64EL), rel.r_offset,
+ getAddend<ELFT>(rel), &file.getRelocTargetSym(rel)};
+ }
+ };
+
+ using RawRels = ArrayRef<RelTy>;
+ using MapRelIter =
+ llvm::mapped_iterator<typename RawRels::iterator, MapRel>;
+ auto mapRel = MapRel{*getFile<ELFT>()};
+ RawRels rawRels = getDataAs<RelTy>();
+ auto rels = llvm::make_range(MapRelIter(rawRels.begin(), mapRel),
+ MapRelIter(rawRels.end(), mapRel));
+ copyRelocations<ELFT, RelTy>(buf, rels);
+ }
+}
+
// This is used for -r and --emit-relocs. We can't use memcpy to copy
// relocations because we need to update symbol table offset and section index
// for each relocation. So we copy relocations one by one.
-template <class ELFT, class RelTy>
-void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
+template <class ELFT, class RelTy, class RelIt>
+void InputSection::copyRelocations(uint8_t *buf,
+ llvm::iterator_range<RelIt> rels) {
const TargetInfo &target = *elf::target;
InputSectionBase *sec = getRelocatedSection();
(void)sec->contentMaybeDecompress(); // uncompress if needed
- for (const RelTy &rel : rels) {
- RelType type = rel.getType(config->isMips64EL);
+ for (const Relocation &rel : rels) {
+ RelType type = rel.type;
const ObjFile<ELFT> *file = getFile<ELFT>();
- Symbol &sym = file->getRelocTargetSym(rel);
+ Symbol &sym = *rel.sym;
auto *p = reinterpret_cast<typename ELFT::Rela *>(buf);
buf += sizeof(RelTy);
if (RelTy::IsRela)
- p->r_addend = getAddend<ELFT>(rel);
+ p->r_addend = rel.addend;
// Output section VA is zero for -r, so r_offset is an offset within the
// section, but for --emit-relocs it is a virtual address.
- p->r_offset = sec->getVA(rel.r_offset);
+ p->r_offset = sec->getVA(rel.offset);
p->setSymbolAndType(in.symTab->getSymbolIndex(&sym), type,
config->isMips64EL);
@@ -408,8 +440,8 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
continue;
}
- int64_t addend = getAddend<ELFT>(rel);
- const uint8_t *bufLoc = sec->content().begin() + rel.r_offset;
+ int64_t addend = rel.addend;
+ const uint8_t *bufLoc = sec->content().begin() + rel.offset;
if (!RelTy::IsRela)
addend = target.getImplicitAddend(bufLoc, type);
@@ -432,7 +464,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
if (RelTy::IsRela)
p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr;
else if (config->relocatable && type != target.noneRel)
- sec->addReloc({R_ABS, type, rel.r_offset, addend, &sym});
+ sec->addReloc({R_ABS, type, rel.offset, addend, &sym});
} else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 &&
p->r_addend >= 0x8000 && sec->file->ppc32Got2) {
// Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24
@@ -1106,11 +1138,11 @@ template <class ELFT> void InputSection::writeTo(uint8_t *buf) {
// If -r or --emit-relocs is given, then an InputSection
// may be a relocation section.
if (LLVM_UNLIKELY(type == SHT_RELA)) {
- copyRelocations<ELFT>(buf, getDataAs<typename ELFT::Rela>());
+ copyRelocations<ELFT, typename ELFT::Rela>(buf);
return;
}
if (LLVM_UNLIKELY(type == SHT_REL)) {
- copyRelocations<ELFT>(buf, getDataAs<typename ELFT::Rel>());
+ copyRelocations<ELFT, typename ELFT::Rel>(buf);
return;
}
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 15122d6abd6b..2b91711abba3 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -396,8 +396,10 @@ public:
static InputSection discarded;
private:
- template <class ELFT, class RelTy>
- void copyRelocations(uint8_t *buf, llvm::ArrayRef<RelTy> rels);
+ template <class ELFT, class RelTy> void copyRelocations(uint8_t *buf);
+
+ template <class ELFT, class RelTy, class RelIt>
+ void copyRelocations(uint8_t *buf, llvm::iterator_range<RelIt> rels);
template <class ELFT> void copyShtGroup(uint8_t *buf);
};
diff --git a/lld/test/ELF/riscv-relax-emit-relocs.s b/lld/test/ELF/riscv-relax-emit-relocs.s
new file mode 100644
index 000000000000..ebd69b742d4f
--- /dev/null
+++ b/lld/test/ELF/riscv-relax-emit-relocs.s
@@ -0,0 +1,69 @@
+# REQUIRES: riscv
+## Test that we can handle --emit-relocs while relaxing.
+
+# RUN: rm -rf %t && mkdir %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax %s -o 32.o
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs 32.o -o 32
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases 32 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax %s -o 64.o
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs 64.o -o 64
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases 64 | FileCheck %s
+
+## -r should keep original relocations.
+# RUN: ld.lld -r 64.o -o 64.r
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases 64.r | FileCheck %s --check-prefix=CHECKR
+
+## --no-relax should keep original relocations.
+# RUN: ld.lld --emit-relocs --no-relax 64.o -o 64.norelax
+# RUN: llvm-objdump -dr --no-show-raw-insn -M no-aliases 64.norelax | FileCheck %s --check-prefix=CHECKNORELAX
+
+# CHECK: <_start>:
+# CHECK-NEXT: jal ra, 0x10008 <f>
+# CHECK-NEXT: R_RISCV_JAL f
+# CHECK-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-NEXT: jal ra, 0x10008 <f>
+# CHECK-NEXT: R_RISCV_JAL f
+# CHECK-NEXT: R_RISCV_RELAX *ABS*
+# CHECK-EMPTY:
+# CHECK-NEXT: <f>:
+# CHECK-NEXT: jalr zero, 0(ra)
+# CHECK-NEXT: R_RISCV_ALIGN *ABS*+0x4
+
+# CHECKR: <_start>:
+# CHECKR-NEXT: auipc ra, 0
+# CHECKR-NEXT: R_RISCV_CALL_PLT f
+# CHECKR-NEXT: R_RISCV_RELAX *ABS*
+# CHECKR-NEXT: jalr ra, 0(ra)
+# CHECKR-NEXT: auipc ra, 0
+# CHECKR-NEXT: R_RISCV_CALL_PLT f
+# CHECKR-NEXT: R_RISCV_RELAX *ABS*
+# CHECKR-NEXT: jalr ra, 0(ra)
+# CHECKR-NEXT: addi zero, zero, 0
+# CHECKR-NEXT: R_RISCV_ALIGN *ABS*+0x4
+# CHECKR-EMPTY:
+# CHECKR-NEXT: <f>:
+# CHECKR-NEXT: jalr zero, 0(ra)
+
+# CHECKNORELAX: <_start>:
+# CHECKNORELAX-NEXT: auipc ra, 0
+# CHECKNORELAX-NEXT: R_RISCV_CALL_PLT f
+# CHECKNORELAX-NEXT: R_RISCV_RELAX *ABS*
+# CHECKNORELAX-NEXT: jalr ra, 16(ra)
+# CHECKNORELAX-NEXT: auipc ra, 0
+# CHECKNORELAX-NEXT: R_RISCV_CALL_PLT f
+# CHECKNORELAX-NEXT: R_RISCV_RELAX *ABS*
+# CHECKNORELAX-NEXT: jalr ra, 8(ra)
+# CHECKNORELAX-EMPTY:
+# CHECKNORELAX-NEXT: <f>:
+# CHECKNORELAX-NEXT: jalr zero, 0(ra)
+# CHECKNORELAX-NEXT: R_RISCV_ALIGN *ABS*+0x4
+
+.global _start
+_start:
+ call f
+ call f
+ .balign 8
+f:
+ ret
--
2.20.1

View File

@ -0,0 +1,563 @@
From 80c56e85d742bb88533e4789c76ae2b55dc36835 Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
Date: Tue, 6 Feb 2024 09:09:13 +0800
Subject: [PATCH 10/14] [lld][ELF] Support relax R_LARCH_ALIGN (#78692)
Refer to commit 6611d58f5bbc ("Relax R_RISCV_ALIGN"), we can relax
R_LARCH_ALIGN by same way. Reuse `SymbolAnchor`, `RISCVRelaxAux` and
`initSymbolAnchors` to simplify codes. As `riscvFinalizeRelax` is an
arch-specific function, put it override on `TargetInfo::finalizeRelax`,
so that LoongArch can override it, too.
The flow of relax R_LARCH_ALIGN is almost consistent with RISCV. The
difference is that LoongArch only has 4-bytes NOP and all executable
insn is 4-bytes aligned. So LoongArch not need rewrite NOP sequence.
Alignment maxBytesEmit parameter is supported in psABI v2.30.
(cherry picked from commit 06a728f3feab876f9195738b5774e82dadc0f3a7)
(cherry picked from commit 60a8ec3a35c722a9eb8298c215321b89d0faf5b5)
Change-Id: I680e9a44f05fb2cc820736eee63ddd999e689daf
---
lld/ELF/Arch/LoongArch.cpp | 156 ++++++++++++++++++++-
lld/ELF/Arch/RISCV.cpp | 28 +---
lld/ELF/InputSection.cpp | 5 +-
lld/ELF/InputSection.h | 24 +++-
lld/ELF/Target.h | 3 +
lld/ELF/Writer.cpp | 4 +-
lld/test/ELF/loongarch-relax-align.s | 126 +++++++++++++++++
lld/test/ELF/loongarch-relax-emit-relocs.s | 49 +++++++
8 files changed, 362 insertions(+), 33 deletions(-)
create mode 100644 lld/test/ELF/loongarch-relax-align.s
create mode 100644 lld/test/ELF/loongarch-relax-emit-relocs.s
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index d3a538577a59..3f57a76873f9 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -36,6 +36,8 @@ public:
bool usesOnlyLowPageBits(RelType type) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
+ bool relaxOnce(int pass) const override;
+ void finalizeRelax(int passes) const override;
};
} // end anonymous namespace
@@ -521,8 +523,9 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_TLS_GD_HI20:
return R_TLSGD_GOT;
case R_LARCH_RELAX:
- // LoongArch linker relaxation is not implemented yet.
- return R_NONE;
+ return config->relax ? R_RELAX_HINT : R_NONE;
+ case R_LARCH_ALIGN:
+ return R_RELAX_HINT;
// Other known relocs that are explicitly unimplemented:
//
@@ -696,6 +699,155 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
}
}
+static bool relax(InputSection &sec) {
+ const uint64_t secAddr = sec.getVA();
+ const MutableArrayRef<Relocation> relocs = sec.relocs();
+ auto &aux = *sec.relaxAux;
+ bool changed = false;
+ ArrayRef<SymbolAnchor> sa = ArrayRef(aux.anchors);
+ uint64_t delta = 0;
+
+ std::fill_n(aux.relocTypes.get(), relocs.size(), R_LARCH_NONE);
+ aux.writes.clear();
+ for (auto [i, r] : llvm::enumerate(relocs)) {
+ const uint64_t loc = secAddr + r.offset - delta;
+ uint32_t &cur = aux.relocDeltas[i], remove = 0;
+ switch (r.type) {
+ case R_LARCH_ALIGN: {
+ const uint64_t addend =
+ r.sym->isUndefined() ? Log2_64(r.addend) + 1 : r.addend;
+ const uint64_t allBytes = (1 << (addend & 0xff)) - 4;
+ const uint64_t align = 1 << (addend & 0xff);
+ const uint64_t maxBytes = addend >> 8;
+ const uint64_t off = loc & (align - 1);
+ const uint64_t curBytes = off == 0 ? 0 : align - off;
+ // All bytes beyond the alignment boundary should be removed.
+ // If emit bytes more than max bytes to emit, remove all.
+ if (maxBytes != 0 && curBytes > maxBytes)
+ remove = allBytes;
+ else
+ remove = allBytes - curBytes;
+ // If we can't satisfy this alignment, we've found a bad input.
+ if (LLVM_UNLIKELY(static_cast<int32_t>(remove) < 0)) {
+ errorOrWarn(getErrorLocation((const uint8_t *)loc) +
+ "insufficient padding bytes for " + lld::toString(r.type) +
+ ": " + Twine(allBytes) + " bytes available for " +
+ "requested alignment of " + Twine(align) + " bytes");
+ remove = 0;
+ }
+ break;
+ }
+ }
+
+ // For all anchors whose offsets are <= r.offset, they are preceded by
+ // the previous relocation whose `relocDeltas` value equals `delta`.
+ // Decrease their st_value and update their st_size.
+ for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1)) {
+ if (sa[0].end)
+ sa[0].d->size = sa[0].offset - delta - sa[0].d->value;
+ else
+ sa[0].d->value = sa[0].offset - delta;
+ }
+ delta += remove;
+ if (delta != cur) {
+ cur = delta;
+ changed = true;
+ }
+ }
+
+ for (const SymbolAnchor &a : sa) {
+ if (a.end)
+ a.d->size = a.offset - delta - a.d->value;
+ else
+ a.d->value = a.offset - delta;
+ }
+ // Inform assignAddresses that the size has changed.
+ if (!isUInt<32>(delta))
+ fatal("section size decrease is too large: " + Twine(delta));
+ sec.bytesDropped = delta;
+ return changed;
+}
+
+// When relaxing just R_LARCH_ALIGN, relocDeltas is usually changed only once in
+// the absence of a linker script. For call and load/store R_LARCH_RELAX, code
+// shrinkage may reduce displacement and make more relocations eligible for
+// relaxation. Code shrinkage may increase displacement to a call/load/store
+// target at a higher fixed address, invalidating an earlier relaxation. Any
+// change in section sizes can have cascading effect and require another
+// relaxation pass.
+bool LoongArch::relaxOnce(int pass) const {
+ if (config->relocatable)
+ return false;
+
+ if (pass == 0)
+ initSymbolAnchors();
+
+ SmallVector<InputSection *, 0> storage;
+ bool changed = false;
+ for (OutputSection *osec : outputSections) {
+ if (!(osec->flags & SHF_EXECINSTR))
+ continue;
+ for (InputSection *sec : getInputSections(*osec, storage))
+ changed |= relax(*sec);
+ }
+ return changed;
+}
+
+void LoongArch::finalizeRelax(int passes) const {
+ log("relaxation passes: " + Twine(passes));
+ SmallVector<InputSection *, 0> storage;
+ for (OutputSection *osec : outputSections) {
+ if (!(osec->flags & SHF_EXECINSTR))
+ continue;
+ for (InputSection *sec : getInputSections(*osec, storage)) {
+ RelaxAux &aux = *sec->relaxAux;
+ if (!aux.relocDeltas)
+ continue;
+
+ MutableArrayRef<Relocation> rels = sec->relocs();
+ ArrayRef<uint8_t> old = sec->content();
+ size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1];
+ uint8_t *p = context().bAlloc.Allocate<uint8_t>(newSize);
+ uint64_t offset = 0;
+ int64_t delta = 0;
+ sec->content_ = p;
+ sec->size = newSize;
+ sec->bytesDropped = 0;
+
+ // Update section content: remove NOPs for R_LARCH_ALIGN and rewrite
+ // instructions for relaxed relocations.
+ for (size_t i = 0, e = rels.size(); i != e; ++i) {
+ uint32_t remove = aux.relocDeltas[i] - delta;
+ delta = aux.relocDeltas[i];
+ if (remove == 0 && aux.relocTypes[i] == R_LARCH_NONE)
+ continue;
+
+ // Copy from last location to the current relocated location.
+ const Relocation &r = rels[i];
+ uint64_t size = r.offset - offset;
+ memcpy(p, old.data() + offset, size);
+ p += size;
+ offset = r.offset + remove;
+ }
+ memcpy(p, old.data() + offset, old.size() - offset);
+
+ // Subtract the previous relocDeltas value from the relocation offset.
+ // For a pair of R_LARCH_XXX/R_LARCH_RELAX with the same offset, decrease
+ // their r_offset by the same delta.
+ delta = 0;
+ for (size_t i = 0, e = rels.size(); i != e;) {
+ uint64_t cur = rels[i].offset;
+ do {
+ rels[i].offset -= delta;
+ if (aux.relocTypes[i] != R_LARCH_NONE)
+ rels[i].type = aux.relocTypes[i];
+ } while (++i != e && rels[i].offset == cur);
+ delta = aux.relocDeltas[i - 1];
+ }
+ }
+ }
+}
+
TargetInfo *elf::getLoongArchTargetInfo() {
static LoongArch target;
return &target;
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index d0d75118e30d..06120cabc132 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -44,6 +44,7 @@ public:
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
bool relaxOnce(int pass) const override;
+ void finalizeRelax(int passes) const override;
};
} // end anonymous namespace
@@ -513,33 +514,14 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
-namespace {
-struct SymbolAnchor {
- uint64_t offset;
- Defined *d;
- bool end; // true for the anchor of st_value+st_size
-};
-} // namespace
-
-struct elf::RISCVRelaxAux {
- // This records symbol start and end offsets which will be adjusted according
- // to the nearest relocDeltas element.
- SmallVector<SymbolAnchor, 0> anchors;
- // For relocations[i], the actual offset is r_offset - (i ? relocDeltas[i-1] :
- // 0).
- std::unique_ptr<uint32_t[]> relocDeltas;
- // For relocations[i], the actual type is relocTypes[i].
- std::unique_ptr<RelType[]> relocTypes;
- SmallVector<uint32_t, 0> writes;
-};
-static void initSymbolAnchors() {
+void elf::initSymbolAnchors() {
SmallVector<InputSection *, 0> storage;
for (OutputSection *osec : outputSections) {
if (!(osec->flags & SHF_EXECINSTR))
continue;
for (InputSection *sec : getInputSections(*osec, storage)) {
- sec->relaxAux = make<RISCVRelaxAux>();
+ sec->relaxAux = make<RelaxAux>();
if (sec->relocs().size()) {
sec->relaxAux->relocDeltas =
std::make_unique<uint32_t[]>(sec->relocs().size());
@@ -766,7 +748,7 @@ bool RISCV::relaxOnce(int pass) const {
return changed;
}
-void elf::riscvFinalizeRelax(int passes) {
+void RISCV::finalizeRelax(int passes) const {
llvm::TimeTraceScope timeScope("Finalize RISC-V relaxation");
log("relaxation passes: " + Twine(passes));
SmallVector<InputSection *, 0> storage;
@@ -774,7 +756,7 @@ void elf::riscvFinalizeRelax(int passes) {
if (!(osec->flags & SHF_EXECINSTR))
continue;
for (InputSection *sec : getInputSections(*osec, storage)) {
- RISCVRelaxAux &aux = *sec->relaxAux;
+ RelaxAux &aux = *sec->relaxAux;
if (!aux.relocDeltas)
continue;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 1aff6b968d86..b178d82407e3 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -351,8 +351,9 @@ InputSectionBase *InputSection::getRelocatedSection() const {
template <class ELFT, class RelTy>
void InputSection::copyRelocations(uint8_t *buf) {
- if (config->relax && !config->relocatable && config->emachine == EM_RISCV) {
- // On RISC-V, relaxation might change relocations: copy from
+ if (config->relax && !config->relocatable &&
+ (config->emachine == EM_RISCV || config->emachine == EM_LOONGARCH)) {
+ // On LoongArch and RISC-V, relaxation might change relocations: copy from
// internal ones that are updated by relaxation.
InputSectionBase *sec = getRelocatedSection();
copyRelocations<ELFT, RelTy>(buf, llvm::make_range(sec->relocations.begin(),
diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h
index 2b91711abba3..842bc369909d 100644
--- a/lld/ELF/InputSection.h
+++ b/lld/ELF/InputSection.h
@@ -101,7 +101,23 @@ protected:
link(link), info(info) {}
};
-struct RISCVRelaxAux;
+struct SymbolAnchor {
+ uint64_t offset;
+ Defined *d;
+ bool end; // true for the anchor of st_value+st_size
+};
+
+struct RelaxAux {
+ // This records symbol start and end offsets which will be adjusted according
+ // to the nearest relocDeltas element.
+ SmallVector<SymbolAnchor, 0> anchors;
+ // For relocations[i], the actual offset is
+ // r_offset - (i ? relocDeltas[i-1] : 0).
+ std::unique_ptr<uint32_t[]> relocDeltas;
+ // For relocations[i], the actual type is relocTypes[i].
+ std::unique_ptr<RelType[]> relocTypes;
+ SmallVector<uint32_t, 0> writes;
+};
// This corresponds to a section of an input file.
class InputSectionBase : public SectionBase {
@@ -222,9 +238,9 @@ public:
// basic blocks.
JumpInstrMod *jumpInstrMod = nullptr;
- // Auxiliary information for RISC-V linker relaxation. RISC-V does not use
- // jumpInstrMod.
- RISCVRelaxAux *relaxAux;
+ // Auxiliary information for RISC-V and LoongArch linker relaxation.
+ // They do not use jumpInstrMod.
+ RelaxAux *relaxAux;
// The compressed content size when `compressed` is true.
size_t compressedSize;
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 47dbe6b4d1c6..bf831afa1793 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -94,6 +94,8 @@ public:
// Do a linker relaxation pass and return true if we changed something.
virtual bool relaxOnce(int pass) const { return false; }
+ // Do finalize relaxation after collecting relaxation infos.
+ virtual void finalizeRelax(int passes) const {}
virtual void applyJumpInstrMod(uint8_t *loc, JumpModType type,
JumpModType val) const {}
@@ -234,6 +236,7 @@ void addArmInputSectionMappingSymbols();
void addArmSyntheticSectionMappingSymbol(Defined *);
void sortArmMappingSymbols();
void convertArmInstructionstoBE8(InputSection *sec, uint8_t *buf);
+void initSymbolAnchors();
LLVM_LIBRARY_VISIBILITY extern const TargetInfo *target;
TargetInfo *getTarget();
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 368c9aabceae..dd37bbbf76c1 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1668,8 +1668,8 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
}
}
}
- if (!config->relocatable && config->emachine == EM_RISCV)
- riscvFinalizeRelax(pass);
+ if (!config->relocatable)
+ target->finalizeRelax(pass);
if (config->relocatable)
for (OutputSection *sec : outputSections)
diff --git a/lld/test/ELF/loongarch-relax-align.s b/lld/test/ELF/loongarch-relax-align.s
new file mode 100644
index 000000000000..ab61e15d5cac
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-align.s
@@ -0,0 +1,126 @@
+# REQUIRES: loongarch
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o -o %t.32
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o -o %t.64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.32.o --no-relax -o %t.32n
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.64.o --no-relax -o %t.64n
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32 | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64 | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.32n | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.64n | FileCheck %s
+
+## Test the R_LARCH_ALIGN without symbol index.
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.o64.o --defsym=old=1
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o -o %t.o64
+# RUN: ld.lld --section-start=.text=0x10000 --section-start=.text2=0x20000 -e 0 %t.o64.o --no-relax -o %t.o64n
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64 | FileCheck %s
+# RUN: llvm-objdump -td --no-show-raw-insn %t.o64n | FileCheck %s
+
+## -r keeps section contents unchanged.
+# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: llvm-objdump -dr --no-show-raw-insn %t.64.r | FileCheck %s --check-prefix=CHECKR
+
+# CHECK-DAG: {{0*}}10000 l .text {{0*}}44 .Ltext_start
+# CHECK-DAG: {{0*}}10038 l .text {{0*}}0c .L1
+# CHECK-DAG: {{0*}}10040 l .text {{0*}}04 .L2
+# CHECK-DAG: {{0*}}20000 l .text2 {{0*}}14 .Ltext2_start
+
+# CHECK: <.Ltext_start>:
+# CHECK-NEXT: break 1
+# CHECK-NEXT: break 2
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: break 3
+# CHECK-NEXT: break 4
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: pcalau12i $a0, 0
+# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# CHECK-NEXT: pcalau12i $a0, 0
+# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 56
+# CHECK-NEXT: pcalau12i $a0, 0
+# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 64
+# CHECK-EMPTY:
+# CHECK-NEXT: <.L1>:
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-EMPTY:
+# CHECK-NEXT: <.L2>:
+# CHECK-NEXT: break 5
+
+# CHECK: <.Ltext2_start>:
+# CHECK-NEXT: pcalau12i $a0, 0
+# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# CHECK-NEXT: nop
+# CHECK-NEXT: nop
+# CHECK-NEXT: break 6
+
+# CHECKR: <.Ltext2_start>:
+# CHECKR-NEXT: pcalau12i $a0, 0
+# CHECKR-NEXT: {{0*}}00: R_LARCH_PCALA_HI20 .Ltext2_start
+# CHECKR-NEXT: {{0*}}00: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: {{0*}}04: R_LARCH_PCALA_LO12 .Ltext2_start
+# CHECKR-NEXT: {{0*}}04: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: {{0*}}08: R_LARCH_ALIGN .Lalign_symbol+0x4
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: break 6
+
+.macro .fake_p2align_4 max=0
+ .ifdef old
+ .if \max==0
+ .reloc ., R_LARCH_ALIGN, 0xc
+ nop; nop; nop
+ .endif
+ .else
+ .reloc ., R_LARCH_ALIGN, .Lalign_symbol + 0x4 + (\max << 8)
+ nop; nop; nop
+ .endif
+.endm
+
+ .text
+.Lalign_symbol:
+.Ltext_start:
+ break 1
+ break 2
+## +0x8: Emit 2 nops, delete 1 nop.
+ .fake_p2align_4
+
+ break 3
+## +0x14: Emit 3 nops > 8 bytes, not emit.
+ .fake_p2align_4 8
+
+ break 4
+ .fake_p2align_4 8
+## +0x18: Emit 2 nops <= 8 bytes.
+
+## Compensate
+.ifdef old
+ nop; nop
+.endif
+
+## +0x20: Test symbol value and symbol size can be handled.
+ la.pcrel $a0, .Ltext_start
+ la.pcrel $a0, .L1
+ la.pcrel $a0, .L2
+
+## +0x38: Emit 2 nops, delete 1 nop.
+.L1:
+ .fake_p2align_4
+.L2:
+ break 5
+ .size .L1, . - .L1
+ .size .L2, . - .L2
+ .size .Ltext_start, . - .Ltext_start
+
+## Test another text section.
+ .section .text2,"ax",@progbits
+.Ltext2_start:
+ la.pcrel $a0, .Ltext2_start
+ .fake_p2align_4
+ break 6
+ .size .Ltext2_start, . - .Ltext2_start
diff --git a/lld/test/ELF/loongarch-relax-emit-relocs.s b/lld/test/ELF/loongarch-relax-emit-relocs.s
new file mode 100644
index 000000000000..581fce8c95ca
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-emit-relocs.s
@@ -0,0 +1,49 @@
+# REQUIRES: loongarch
+## Test that we can handle --emit-relocs while relaxing.
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax %s -o %t.32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax %s -o %t.64.o
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.32.o -o %t.32
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs %t.64.o -o %t.64
+# RUN: llvm-objdump -dr %t.32 | FileCheck %s
+# RUN: llvm-objdump -dr %t.64 | FileCheck %s
+
+## -r should keep original relocations.
+# RUN: ld.lld -r %t.64.o -o %t.64.r
+# RUN: llvm-objdump -dr %t.64.r | FileCheck %s --check-prefix=CHECKR
+
+## --no-relax should keep original relocations.
+## TODO Due to R_LARCH_RELAX is not relaxed, it plays same as --relax now.
+# RUN: ld.lld -Ttext=0x10000 --emit-relocs --no-relax %t.64.o -o %t.64.norelax
+# RUN: llvm-objdump -dr %t.64.norelax | FileCheck %s
+
+# CHECK: 00010000 <_start>:
+# CHECK-NEXT: pcalau12i $a0, 0
+# CHECK-NEXT: R_LARCH_PCALA_HI20 _start
+# CHECK-NEXT: R_LARCH_RELAX *ABS*
+# CHECK-NEXT: addi.{{[dw]}} $a0, $a0, 0
+# CHECK-NEXT: R_LARCH_PCALA_LO12 _start
+# CHECK-NEXT: R_LARCH_RELAX *ABS*
+# CHECK-NEXT: nop
+# CHECK-NEXT: R_LARCH_ALIGN .Lla-relax-align0+0x4
+# CHECK-NEXT: nop
+# CHECK-NEXT: ret
+
+# CHECKR: <_start>:
+# CHECKR-NEXT: pcalau12i $a0, 0
+# CHECKR-NEXT: R_LARCH_PCALA_HI20 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: addi.d $a0, $a0, 0
+# CHECKR-NEXT: R_LARCH_PCALA_LO12 _start
+# CHECKR-NEXT: R_LARCH_RELAX *ABS*
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: R_LARCH_ALIGN .Lla-relax-align0+0x4
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: nop
+# CHECKR-NEXT: ret
+
+.global _start
+_start:
+ la.pcrel $a0, _start
+ .p2align 4
+ ret
--
2.20.1

View File

@ -0,0 +1,199 @@
From a5c1174c902a9dc7fb15aa047ca31e012aea6af9 Mon Sep 17 00:00:00 2001
From: Jinyang He <hejinyang@loongson.cn>
Date: Tue, 5 Mar 2024 15:50:14 +0800
Subject: [PATCH 12/14] [lld][LoongArch] Support the R_LARCH_{ADD,SUB}_ULEB128
relocation types (#81133)
For a label difference like `.uleb128 A-B`, MC generates a pair of
R_LARCH_{ADD,SUB}_ULEB128 if A-B cannot be folded as a constant. GNU
assembler generates a pair of relocations in more cases (when A or B is
in a code section with linker relaxation). It is similar to RISCV.
R_LARCH_{ADD,SUB}_ULEB128 relocations are created by Clang and GCC in
`.gcc_except_table` and other debug sections with linker relaxation
enabled. On LoongArch, first read the buf and count the available space.
Then add or sub the value. Finally truncate the expected value and fill
it into the available space.
(cherry picked from commit eaa9ef678c63bf392ec2d5b736605db7ea7e7338)
Change-Id: Ic49d34146e47eeeabbbba00ef70b76a13322d80e
---
lld/ELF/Arch/LoongArch.cpp | 19 +++++
lld/test/ELF/loongarch-reloc-leb128.s | 102 ++++++++++++++++++++++++++
2 files changed, 121 insertions(+)
create mode 100644 lld/test/ELF/loongarch-reloc-leb128.s
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 3f57a76873f9..160fab4aeba9 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -11,6 +11,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
+#include "llvm/Support/LEB128.h"
using namespace llvm;
using namespace llvm::object;
@@ -210,6 +211,16 @@ static bool isJirl(uint32_t insn) {
return (insn & 0xfc000000) == JIRL;
}
+static void handleUleb128(uint8_t *loc, uint64_t val) {
+ const uint32_t maxcount = 1 + 64 / 7;
+ uint32_t count;
+ uint64_t orig = decodeULEB128(loc, &count);
+ if (count > maxcount)
+ errorOrWarn(getErrorLocation(loc) + "extra space for uleb128");
+ uint64_t mask = count < maxcount ? (1ULL << 7 * count) - 1 : -1ULL;
+ encodeULEB128((orig + val) & mask, loc, count);
+}
+
LoongArch::LoongArch() {
// The LoongArch ISA itself does not have a limit on page sizes. According to
// the ISA manual, the PS (page size) field in MTLB entries and CSR.STLBPS is
@@ -451,11 +462,13 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
case R_LARCH_ADD16:
case R_LARCH_ADD32:
case R_LARCH_ADD64:
+ case R_LARCH_ADD_ULEB128:
case R_LARCH_SUB6:
case R_LARCH_SUB8:
case R_LARCH_SUB16:
case R_LARCH_SUB32:
case R_LARCH_SUB64:
+ case R_LARCH_SUB_ULEB128:
// The LoongArch add/sub relocs behave like the RISCV counterparts; reuse
// the RelExpr to avoid code duplication.
return R_RISCV_ADD;
@@ -670,6 +683,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_ADD64:
write64le(loc, read64le(loc) + val);
return;
+ case R_LARCH_ADD_ULEB128:
+ handleUleb128(loc, val);
+ return;
case R_LARCH_SUB6:
*loc = (*loc & 0xc0) | ((*loc - val) & 0x3f);
return;
@@ -685,6 +701,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
case R_LARCH_SUB64:
write64le(loc, read64le(loc) - val);
return;
+ case R_LARCH_SUB_ULEB128:
+ handleUleb128(loc, -val);
+ return;
case R_LARCH_MARK_LA:
case R_LARCH_MARK_PCREL:
diff --git a/lld/test/ELF/loongarch-reloc-leb128.s b/lld/test/ELF/loongarch-reloc-leb128.s
new file mode 100644
index 000000000000..7740ca797fca
--- /dev/null
+++ b/lld/test/ELF/loongarch-reloc-leb128.s
@@ -0,0 +1,102 @@
+# REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax a.s -o a.o
+# RUN: llvm-readobj -r -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.o | FileCheck %s --check-prefix=REL
+# RUN: ld.lld -shared --gc-sections a.o -o a.so
+# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.so | FileCheck %s
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax a.s -o a32.o
+# RUN: llvm-readobj -r -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a32.o | FileCheck %s --check-prefix=REL
+# RUN: ld.lld -shared --gc-sections a32.o -o a32.so
+# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a32.so | FileCheck %s
+
+# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax extraspace.s -o extraspace32.o
+# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax extraspace.s -o extraspace64.o
+# RUN: not ld.lld -shared extraspace32.o 2>&1 | FileCheck %s --check-prefix=ERROR
+# RUN: not ld.lld -shared extraspace64.o 2>&1 | FileCheck %s --check-prefix=ERROR
+# ERROR: error: extraspace{{.*}}.o:(.rodata+0x0): extra space for uleb128
+
+#--- a.s
+.cfi_startproc
+.cfi_lsda 0x1b,.LLSDA0
+.cfi_endproc
+
+.section .text.w,"axR"
+break 0; break 0; break 0; w1:
+ .p2align 4 # 4 bytes after relaxation
+w2: break 0
+
+.section .text.x,"ax"
+break 0; break 0; break 0; x1:
+ .p2align 4 # 4 bytes after relaxation
+x2: break 0
+
+.section .gcc_except_table,"a"
+.LLSDA0:
+.uleb128 w2-w1+116 # initial value: 0x0080
+.uleb128 w1-w2+141 # initial value: 0x0080
+.uleb128 w2-w1+16372 # initial value: 0x008080
+.uleb128 w1-w2+16397 # initial value: 0x008080
+.uleb128 w2-w1+2097140 # initial value: 0x00808080
+.uleb128 w1-w2+2097165 # initial value: 0x00808080
+
+.section .debug_rnglists
+.uleb128 w2-w1+116 # initial value: 0x0080
+.uleb128 w1-w2+141 # initial value: 0x0080
+.uleb128 w2-w1+16372 # initial value: 0x008080
+.uleb128 w1-w2+16397 # initial value: 0x008080
+.uleb128 w2-w1+2097140 # initial value: 0x00808080
+.uleb128 w1-w2+2097165 # initial value: 0x00808080
+
+.section .debug_loclists
+.uleb128 x2-x1 # references discarded symbols
+
+# REL: Section ({{.*}}) .rela.debug_rnglists {
+# REL-NEXT: 0x0 R_LARCH_ADD_ULEB128 w2 0x74
+# REL-NEXT: 0x0 R_LARCH_SUB_ULEB128 w1 0x0
+# REL-NEXT: 0x2 R_LARCH_ADD_ULEB128 w1 0x8D
+# REL-NEXT: 0x2 R_LARCH_SUB_ULEB128 w2 0x0
+# REL-NEXT: 0x4 R_LARCH_ADD_ULEB128 w2 0x3FF4
+# REL-NEXT: 0x4 R_LARCH_SUB_ULEB128 w1 0x0
+# REL-NEXT: 0x7 R_LARCH_ADD_ULEB128 w1 0x400D
+# REL-NEXT: 0x7 R_LARCH_SUB_ULEB128 w2 0x0
+# REL-NEXT: 0xA R_LARCH_ADD_ULEB128 w2 0x1FFFF4
+# REL-NEXT: 0xA R_LARCH_SUB_ULEB128 w1 0x0
+# REL-NEXT: 0xE R_LARCH_ADD_ULEB128 w1 0x20000D
+# REL-NEXT: 0xE R_LARCH_SUB_ULEB128 w2 0x0
+# REL-NEXT: }
+# REL: Section ({{.*}}) .rela.debug_loclists {
+# REL-NEXT: 0x0 R_LARCH_ADD_ULEB128 x2 0x0
+# REL-NEXT: 0x0 R_LARCH_SUB_ULEB128 x1 0x0
+# REL-NEXT: }
+
+# REL: Hex dump of section '.gcc_except_table':
+# REL-NEXT: 0x00000000 80008000 80800080 80008080 80008080 .
+# REL-NEXT: 0x00000010 8000 .
+# REL: Hex dump of section '.debug_rnglists':
+# REL-NEXT: 0x00000000 80008000 80800080 80008080 80008080 .
+# REL-NEXT: 0x00000010 8000 .
+# REL: Hex dump of section '.debug_loclists':
+# REL-NEXT: 0x00000000 00 .
+
+# CHECK: Hex dump of section '.gcc_except_table':
+# CHECK-NEXT: 0x[[#%x,]] f8008901 f8ff0089 8001f8ff ff008980 .
+# CHECK-NEXT: 0x[[#%x,]] 8001 .
+# CHECK: Hex dump of section '.debug_rnglists':
+# CHECK-NEXT: 0x00000000 f8008901 f8ff0089 8001f8ff ff008980 .
+# CHECK-NEXT: 0x00000010 8001 .
+# CHECK: Hex dump of section '.debug_loclists':
+# CHECK-NEXT: 0x00000000 0c .
+
+#--- extraspace.s
+.text
+w1:
+ la.pcrel $t0, w1
+w2:
+
+.rodata
+.reloc ., R_LARCH_ADD_ULEB128, w2
+.reloc ., R_LARCH_SUB_ULEB128, w1
+.fill 10, 1, 0x80
+.byte 0
--
2.20.1

View File

@ -1,22 +1,8 @@
# lld
#### Description
LLVM Linker
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
This package contains library and header files needed to develop new native
programs that use the LLD infrastructure.
#### Contribution

View File

@ -1,23 +1,8 @@
# lld
#### 介绍
LLVM Linker
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
This package contains library and header files needed to develop new native
programs that use the LLD infrastructure.
#### 参与贡献

View File

@ -0,0 +1,500 @@
From 43dfe54ce017c8d37eaec480a2f13a492bbc4203 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton@redhat.com>
Date: Thu, 25 Feb 2021 14:24:14 +0100
Subject: [PATCH 2/2] [PATCH][lld] Import compact_unwind_encoding.h from
libunwind
This avoids an implicit cross package dependency
Signed-off-by: Chenxi Mao <chenxi.mao@suse.com>
---
lld/include/mach-o/compact_unwind_encoding.h | 477 +++++++++++++++++++++++++++
1 file changed, 477 insertions(+)
create mode 100644 lld/include/mach-o/compact_unwind_encoding.h
diff --git a/lld/include/mach-o/compact_unwind_encoding.h b/lld/include/mach-o/compact_unwind_encoding.h
new file mode 100644
index 0000000..5301b10
--- /dev/null
+++ b/lld/include/mach-o/compact_unwind_encoding.h
@@ -0,0 +1,477 @@
+//===------------------ mach-o/compact_unwind_encoding.h ------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//
+// Darwin's alternative to DWARF based unwind encodings.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef __COMPACT_UNWIND_ENCODING__
+#define __COMPACT_UNWIND_ENCODING__
+
+#include <stdint.h>
+
+//
+// Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
+// of object files. Or compilers can emit compact unwind information in
+// the __LD,__compact_unwind section.
+//
+// When the linker creates a final linked image, it will create a
+// __TEXT,__unwind_info section. This section is a small and fast way for the
+// runtime to access unwind info for any given function. If the compiler
+// emitted compact unwind info for the function, that compact unwind info will
+// be encoded in the __TEXT,__unwind_info section. If the compiler emitted
+// DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
+// of the FDE in the __TEXT,__eh_frame section in the final linked image.
+//
+// Note: Previously, the linker would transform some DWARF unwind infos into
+// compact unwind info. But that is fragile and no longer done.
+
+
+//
+// The compact unwind endoding is a 32-bit value which encoded in an
+// architecture specific way, which registers to restore from where, and how
+// to unwind out of the function.
+//
+typedef uint32_t compact_unwind_encoding_t;
+
+
+// architecture independent bits
+enum {
+ UNWIND_IS_NOT_FUNCTION_START = 0x80000000,
+ UNWIND_HAS_LSDA = 0x40000000,
+ UNWIND_PERSONALITY_MASK = 0x30000000,
+};
+
+
+
+
+//
+// x86
+//
+// 1-bit: start
+// 1-bit: has lsda
+// 2-bit: personality index
+//
+// 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
+// ebp based:
+// 15-bits (5*3-bits per reg) register permutation
+// 8-bits for stack offset
+// frameless:
+// 8-bits stack size
+// 3-bits stack adjust
+// 3-bits register count
+// 10-bits register permutation
+//
+enum {
+ UNWIND_X86_MODE_MASK = 0x0F000000,
+ UNWIND_X86_MODE_EBP_FRAME = 0x01000000,
+ UNWIND_X86_MODE_STACK_IMMD = 0x02000000,
+ UNWIND_X86_MODE_STACK_IND = 0x03000000,
+ UNWIND_X86_MODE_DWARF = 0x04000000,
+
+ UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF,
+ UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000,
+
+ UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000,
+ UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000,
+ UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
+ UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
+
+ UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF,
+};
+
+enum {
+ UNWIND_X86_REG_NONE = 0,
+ UNWIND_X86_REG_EBX = 1,
+ UNWIND_X86_REG_ECX = 2,
+ UNWIND_X86_REG_EDX = 3,
+ UNWIND_X86_REG_EDI = 4,
+ UNWIND_X86_REG_ESI = 5,
+ UNWIND_X86_REG_EBP = 6,
+};
+
+//
+// For x86 there are four modes for the compact unwind encoding:
+// UNWIND_X86_MODE_EBP_FRAME:
+// EBP based frame where EBP is push on stack immediately after return address,
+// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
+// EPB value, then EBP is restored by popping off the stack, and the return
+// is done by popping the stack once more into the pc.
+// All non-volatile registers that need to be restored must have been saved
+// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4
+// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved
+// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
+// Each entry contains which register to restore.
+// UNWIND_X86_MODE_STACK_IMMD:
+// A "frameless" (EBP not used as frame pointer) function with a small
+// constant stack size. To return, a constant (encoded in the compact
+// unwind encoding) is added to the ESP. Then the return is done by
+// popping the stack into the pc.
+// All non-volatile registers that need to be restored must have been saved
+// on the stack immediately after the return address. The stack_size/4 is
+// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
+// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
+// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
+// saved and their order.
+// UNWIND_X86_MODE_STACK_IND:
+// A "frameless" (EBP not used as frame pointer) function large constant
+// stack size. This case is like the previous, except the stack size is too
+// large to encode in the compact unwind encoding. Instead it requires that
+// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact
+// encoding contains the offset to the nnnnnnnn value in the function in
+// UNWIND_X86_FRAMELESS_STACK_SIZE.
+// UNWIND_X86_MODE_DWARF:
+// No compact unwind encoding is available. Instead the low 24-bits of the
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+// This mode is never used in object files. It is only generated by the
+// linker in final linked images which have only DWARF unwind info for a
+// function.
+//
+// The permutation encoding is a Lehmer code sequence encoded into a
+// single variable-base number so we can encode the ordering of up to
+// six registers in a 10-bit space.
+//
+// The following is the algorithm used to create the permutation encoding used
+// with frameless stacks. It is passed the number of registers to be saved and
+// an array of the register numbers saved.
+//
+//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
+//{
+// uint32_t renumregs[6];
+// for (int i=6-registerCount; i < 6; ++i) {
+// int countless = 0;
+// for (int j=6-registerCount; j < i; ++j) {
+// if ( registers[j] < registers[i] )
+// ++countless;
+// }
+// renumregs[i] = registers[i] - countless -1;
+// }
+// uint32_t permutationEncoding = 0;
+// switch ( registerCount ) {
+// case 6:
+// permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
+// + 6*renumregs[2] + 2*renumregs[3]
+// + renumregs[4]);
+// break;
+// case 5:
+// permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
+// + 6*renumregs[3] + 2*renumregs[4]
+// + renumregs[5]);
+// break;
+// case 4:
+// permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
+// + 3*renumregs[4] + renumregs[5]);
+// break;
+// case 3:
+// permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
+// + renumregs[5]);
+// break;
+// case 2:
+// permutationEncoding |= (5*renumregs[4] + renumregs[5]);
+// break;
+// case 1:
+// permutationEncoding |= (renumregs[5]);
+// break;
+// }
+// return permutationEncoding;
+//}
+//
+
+
+
+
+//
+// x86_64
+//
+// 1-bit: start
+// 1-bit: has lsda
+// 2-bit: personality index
+//
+// 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
+// rbp based:
+// 15-bits (5*3-bits per reg) register permutation
+// 8-bits for stack offset
+// frameless:
+// 8-bits stack size
+// 3-bits stack adjust
+// 3-bits register count
+// 10-bits register permutation
+//
+enum {
+ UNWIND_X86_64_MODE_MASK = 0x0F000000,
+ UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000,
+ UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000,
+ UNWIND_X86_64_MODE_STACK_IND = 0x03000000,
+ UNWIND_X86_64_MODE_DWARF = 0x04000000,
+
+ UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF,
+ UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000,
+
+ UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000,
+ UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000,
+ UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00,
+ UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF,
+
+ UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
+};
+
+enum {
+ UNWIND_X86_64_REG_NONE = 0,
+ UNWIND_X86_64_REG_RBX = 1,
+ UNWIND_X86_64_REG_R12 = 2,
+ UNWIND_X86_64_REG_R13 = 3,
+ UNWIND_X86_64_REG_R14 = 4,
+ UNWIND_X86_64_REG_R15 = 5,
+ UNWIND_X86_64_REG_RBP = 6,
+};
+//
+// For x86_64 there are four modes for the compact unwind encoding:
+// UNWIND_X86_64_MODE_RBP_FRAME:
+// RBP based frame where RBP is push on stack immediately after return address,
+// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
+// EPB value, then RBP is restored by popping off the stack, and the return
+// is done by popping the stack once more into the pc.
+// All non-volatile registers that need to be restored must have been saved
+// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8
+// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved
+// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
+// Each entry contains which register to restore.
+// UNWIND_X86_64_MODE_STACK_IMMD:
+// A "frameless" (RBP not used as frame pointer) function with a small
+// constant stack size. To return, a constant (encoded in the compact
+// unwind encoding) is added to the RSP. Then the return is done by
+// popping the stack into the pc.
+// All non-volatile registers that need to be restored must have been saved
+// on the stack immediately after the return address. The stack_size/8 is
+// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
+// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
+// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
+// saved and their order.
+// UNWIND_X86_64_MODE_STACK_IND:
+// A "frameless" (RBP not used as frame pointer) function large constant
+// stack size. This case is like the previous, except the stack size is too
+// large to encode in the compact unwind encoding. Instead it requires that
+// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact
+// encoding contains the offset to the nnnnnnnn value in the function in
+// UNWIND_X86_64_FRAMELESS_STACK_SIZE.
+// UNWIND_X86_64_MODE_DWARF:
+// No compact unwind encoding is available. Instead the low 24-bits of the
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+// This mode is never used in object files. It is only generated by the
+// linker in final linked images which have only DWARF unwind info for a
+// function.
+//
+
+
+// ARM64
+//
+// 1-bit: start
+// 1-bit: has lsda
+// 2-bit: personality index
+//
+// 4-bits: 4=frame-based, 3=DWARF, 2=frameless
+// frameless:
+// 12-bits of stack size
+// frame-based:
+// 4-bits D reg pairs saved
+// 5-bits X reg pairs saved
+// DWARF:
+// 24-bits offset of DWARF FDE in __eh_frame section
+//
+enum {
+ UNWIND_ARM64_MODE_MASK = 0x0F000000,
+ UNWIND_ARM64_MODE_FRAMELESS = 0x02000000,
+ UNWIND_ARM64_MODE_DWARF = 0x03000000,
+ UNWIND_ARM64_MODE_FRAME = 0x04000000,
+
+ UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001,
+ UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002,
+ UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004,
+ UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008,
+ UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010,
+ UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100,
+ UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200,
+ UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400,
+ UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800,
+
+ UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000,
+ UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF,
+};
+// For arm64 there are three modes for the compact unwind encoding:
+// UNWIND_ARM64_MODE_FRAME:
+// This is a standard arm64 prolog where FP/LR are immediately pushed on the
+// stack, then SP is copied to FP. If there are any non-volatile registers
+// saved, then are copied into the stack frame in pairs in a contiguous
+// range right below the saved FP/LR pair. Any subset of the five X pairs
+// and four D pairs can be saved, but the memory layout must be in register
+// number order.
+// UNWIND_ARM64_MODE_FRAMELESS:
+// A "frameless" leaf function, where FP/LR are not saved. The return address
+// remains in LR throughout the function. If any non-volatile registers
+// are saved, they must be pushed onto the stack before any stack space is
+// allocated for local variables. The stack sized (including any saved
+// non-volatile registers) divided by 16 is encoded in the bits
+// UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
+// UNWIND_ARM64_MODE_DWARF:
+// No compact unwind encoding is available. Instead the low 24-bits of the
+// compact encoding is the offset of the DWARF FDE in the __eh_frame section.
+// This mode is never used in object files. It is only generated by the
+// linker in final linked images which have only DWARF unwind info for a
+// function.
+//
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Relocatable Object Files: __LD,__compact_unwind
+//
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// A compiler can generated compact unwind information for a function by adding
+// a "row" to the __LD,__compact_unwind section. This section has the
+// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
+// It is removed by the new linker, so never ends up in final executables.
+// This section is a table, initially with one row per function (that needs
+// unwind info). The table columns and some conceptual entries are:
+//
+// range-start pointer to start of function/range
+// range-length
+// compact-unwind-encoding 32-bit encoding
+// personality-function or zero if no personality function
+// lsda or zero if no LSDA data
+//
+// The length and encoding fields are 32-bits. The other are all pointer sized.
+//
+// In x86_64 assembly, these entry would look like:
+//
+// .section __LD,__compact_unwind,regular,debug
+//
+// #compact unwind for _foo
+// .quad _foo
+// .set L1,LfooEnd-_foo
+// .long L1
+// .long 0x01010001
+// .quad 0
+// .quad 0
+//
+// #compact unwind for _bar
+// .quad _bar
+// .set L2,LbarEnd-_bar
+// .long L2
+// .long 0x01020011
+// .quad __gxx_personality
+// .quad except_tab1
+//
+//
+// Notes: There is no need for any labels in the the __compact_unwind section.
+// The use of the .set directive is to force the evaluation of the
+// range-length at assembly time, instead of generating relocations.
+//
+// To support future compiler optimizations where which non-volatile registers
+// are saved changes within a function (e.g. delay saving non-volatiles until
+// necessary), there can by multiple lines in the __compact_unwind table for one
+// function, each with a different (non-overlapping) range and each with
+// different compact unwind encodings that correspond to the non-volatiles
+// saved at that range of the function.
+//
+// If a particular function is so wacky that there is no compact unwind way
+// to encode it, then the compiler can emit traditional DWARF unwind info.
+// The runtime will use which ever is available.
+//
+// Runtime support for compact unwind encodings are only available on 10.6
+// and later. So, the compiler should not generate it when targeting pre-10.6.
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Final Linked Images: __TEXT,__unwind_info
+//
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
+// The header of the section contains a coarse index that maps function address
+// to the page (4096 byte block) containing the unwind info for that function.
+//
+
+#define UNWIND_SECTION_VERSION 1
+struct unwind_info_section_header
+{
+ uint32_t version; // UNWIND_SECTION_VERSION
+ uint32_t commonEncodingsArraySectionOffset;
+ uint32_t commonEncodingsArrayCount;
+ uint32_t personalityArraySectionOffset;
+ uint32_t personalityArrayCount;
+ uint32_t indexSectionOffset;
+ uint32_t indexCount;
+ // compact_unwind_encoding_t[]
+ // uint32_t personalities[]
+ // unwind_info_section_header_index_entry[]
+ // unwind_info_section_header_lsda_index_entry[]
+};
+
+struct unwind_info_section_header_index_entry
+{
+ uint32_t functionOffset;
+ uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page
+ uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range
+};
+
+struct unwind_info_section_header_lsda_index_entry
+{
+ uint32_t functionOffset;
+ uint32_t lsdaOffset;
+};
+
+//
+// There are two kinds of second level index pages: regular and compressed.
+// A compressed page can hold up to 1021 entries, but it cannot be used
+// if too many different encoding types are used. The regular page holds
+// 511 entries.
+//
+
+struct unwind_info_regular_second_level_entry
+{
+ uint32_t functionOffset;
+ compact_unwind_encoding_t encoding;
+};
+
+#define UNWIND_SECOND_LEVEL_REGULAR 2
+struct unwind_info_regular_second_level_page_header
+{
+ uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR
+ uint16_t entryPageOffset;
+ uint16_t entryCount;
+ // entry array
+};
+
+#define UNWIND_SECOND_LEVEL_COMPRESSED 3
+struct unwind_info_compressed_second_level_page_header
+{
+ uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED
+ uint16_t entryPageOffset;
+ uint16_t entryCount;
+ uint16_t encodingsPageOffset;
+ uint16_t encodingsCount;
+ // 32-bit entry array
+ // encodings array
+};
+
+#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF)
+#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF)
+
+
+
+#endif
+
--
1.8.3.1

BIN
lld-17.0.6.src.tar.xz Normal file

Binary file not shown.

141
lld.spec Normal file
View File

@ -0,0 +1,141 @@
%bcond_without sys_llvm
%bcond_without check
%global maj_ver 17
%global min_ver 0
%global patch_ver 6
%if %{with sys_llvm}
%global pkg_name lld
%global install_prefix %{_prefix}
%global install_datadir %{_datadir}
%else
%global pkg_name lld%{maj_ver}
%global install_prefix %{_libdir}/llvm%{maj_ver}
%global install_datadir %{install_prefix}/share
%endif
%global install_bindir %{install_prefix}/bin
%if 0%{?__isa_bits} == 64
%global install_libdir %{install_prefix}/lib64
%else
%global install_libdir %{install_prefix}/lib
%endif
%global install_includedir %{install_prefix}/include
# Don't include unittests in automatic generation of provides or requires.
%global __provides_exclude_from ^%{_libdir}/lld/.*$
%global __requires_exclude ^libgtest.*$
# Disable LTO as this causes crash if gcc lto enabled.
%define _lto_cflags %{nil}
Name: %{pkg_name}
Version: %{maj_ver}.%{min_ver}.%{patch_ver}
Release: 2
Summary: The LLVM Linker
License: NCSA
URL: http://llvm.org
Source0: https://github.com/llvm/llvm-project/releases/download/llvmorg-%{version}/lld-%{version}.src.tar.xz
Patch1: fedora-PATCH-lld-Import-compact_unwind_encoding.h-from-libu.patch
Patch2: 0002-Backport-lld-LoongArch-Support-the-R_LARCH_-ADD-SUB-6-relocation-type.patch
Patch3: 0003-Backport-ELF-RISCV-Implement-emit-relocs-with-relaxation.patch
Patch4: 0004-Backport-lld-ELF-Support-relax-R_LARCH_ALIGN.patch
Patch5: 0005-Backport-lld-LoongArch-Support-the-R_LARCH_-ADD-SUB-_ULEB128-relocation-types.patch
BuildRequires: clang
BuildRequires: cmake
%if %{with sys_llvm}
BuildRequires: llvm-devel = %{version}
BuildRequires: llvm-googletest = %{version}
BuildRequires: llvm-test = %{version}
BuildRequires: llvm-cmake-utils = %{version}
%else
BuildRequires: llvm%{maj_ver}-devel = %{version}
BuildRequires: llvm%{maj_ver}-googletest = %{version}
BuildRequires: llvm%{maj_ver}-test = %{version}
BuildRequires: llvm%{maj_ver}-cmake-utils = %{version}
%endif
BuildRequires: ncurses-devel
BuildRequires: ninja-build
BuildRequires: python3-rpm-macros
BuildRequires: python3-lit >= %{version}
BuildRequires: zlib-devel
Requires(post): %{_sbindir}/update-alternatives
Requires(preun): %{_sbindir}/update-alternatives
Requires: %{name}-libs = %{version}-%{release}
%description
The LLVM project linker.
%package devel
Summary: Libraries and header files for LLD
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
%description devel
This package contains library and header files needed to develop new native
programs that use the LLD infrastructure.
%package libs
Summary: LLD shared libraries
%description libs
Shared libraries for LLD.
%prep
%autosetup -n lld-%{version}.src -p2
%build
mkdir -p _build
cd _build
%cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=%{install_prefix} \
-DLLVM_LINK_LLVM_DYLIB:BOOL=ON \
-DLLVM_DYLIB_COMPONENTS="all" \
-DCMAKE_SKIP_RPATH:BOOL=ON \
-DPYTHON_EXECUTABLE=%{__python3} \
-DLLVM_INCLUDE_TESTS=ON \
-DLLVM_EXTERNAL_LIT=%{_bindir}/lit \
-DLLVM_LIT_ARGS="-sv \
--path %{install_prefix}" \
-DLLVM_COMMON_CMAKE_UTILS=%{install_datadir}/llvm/cmake \
-DLLVM_MAIN_SRC_DIR=%{install_prefix}/src
%ninja_build
%install
%ninja_install -C _build
rm %{buildroot}%{install_includedir}/mach-o/compact_unwind_encoding.h
%check
%if %{with check}
%ninja_build check-lld -C _build
%endif
%files
%license LICENSE.TXT
%{install_bindir}/*
%files devel
%{install_includedir}/lld
%{install_libdir}/liblld*.so
%{install_libdir}/cmake/lld/
%files libs
%{install_libdir}/liblld*.so.*
%changelog
* Mon Mar 25 2024 zhanglimin <zhanglimin@loongson.cn> - 17.0.6-2
- Supoort `relax` feature on LoongArch
* Fri Dec 1 2023 zhoujing <zhoujing106@huawei.com> - 17.0.6-1
- Update to 17.0.6
* Thu May 25 2023 cf-zhao <zhaochuanfeng@huawei.com> - 12.0.1-1
- Package init