-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[ELF] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 in SHF_ALLOC sections #77261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ELF] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 in SHF_ALLOC sections #77261
Conversation
Created using spr 1.3.4
@llvm/pr-subscribers-lld Author: Fangrui Song (MaskRay) ChangesComplement #72610 (non-SHF_ALLOC sections). GCC-generated Full diff: https://github.com/llvm/llvm-project/pull/77261.diff 5 Files Affected:
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 898e3e45b9e724..1d3d179e5d6fb5 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -43,6 +43,7 @@ class RISCV final : public TargetInfo {
const uint8_t *loc) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
+ void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
bool relaxOnce(int pass) const override;
};
@@ -307,6 +308,7 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
case R_RISCV_RELAX:
return config->relax ? R_RELAX_HINT : R_NONE;
case R_RISCV_SET_ULEB128:
+ case R_RISCV_SUB_ULEB128:
return R_RISCV_LEB128;
default:
error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
@@ -515,6 +517,46 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
+void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+ uint64_t secAddr = sec.getOutputSection()->addr;
+ if (auto *s = dyn_cast<InputSection>(&sec))
+ secAddr += s->outSecOff;
+ else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
+ secAddr += ehIn->getParent()->outSecOff;
+ for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
+ const Relocation &rel = sec.relocs()[i];
+ uint8_t *loc = buf + rel.offset;
+ const uint64_t val =
+ sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+ secAddr + rel.offset, *rel.sym, rel.expr);
+
+ switch (rel.expr) {
+ case R_RELAX_HINT:
+ break;
+ case R_RISCV_LEB128:
+ if (i + 1 < size) {
+ const Relocation &rel1 = sec.relocs()[i + 1];
+ if (rel.type == R_RISCV_SET_ULEB128 &&
+ rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) {
+ auto val = rel.sym->getVA(rel.addend) - rel1.sym->getVA(rel1.addend);
+ if (overwriteULEB128(loc, val) >= 0x80)
+ errorOrWarn(sec.getLocation(rel.offset) + ": ULEB128 value " +
+ Twine(val) + " exceeds available space; references '" +
+ lld::toString(*rel.sym) + "'");
+ ++i;
+ continue;
+ }
+ }
+ errorOrWarn(sec.getLocation(rel.offset) +
+ ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128");
+ return;
+ default:
+ relocate(loc, rel, val);
+ break;
+ }
+ }
+}
+
namespace {
struct SymbolAnchor {
uint64_t offset;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 5dfb57fda432e0..53b496bd084258 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -671,6 +671,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
case R_RISCV_ADD:
+ case R_RISCV_LEB128:
return sym.getVA(a);
case R_ADDEND:
return a;
@@ -875,16 +876,6 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
}
}
-// Overwrite a ULEB128 value and keep the original length.
-static uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
- while (*bufLoc & 0x80) {
- *bufLoc++ = 0x80 | (val & 0x7f);
- val >>= 7;
- }
- *bufLoc = val;
- return val;
-}
-
// This function applies relocations to sections without SHF_ALLOC bit.
// Such sections are never mapped to memory at runtime. Debug sections are
// an example. Relocations in non-alloc sections are much easier to
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 210b4d1eb1a7a6..9eb2e82542d3d4 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -988,8 +988,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
if (!config->isPic)
return true;
- // The size of a non preemptible symbol is a constant.
- if (e == R_SIZE)
+ // Constant when referencing a non-preemptible symbol.
+ if (e == R_SIZE || e == R_RISCV_LEB128)
return true;
// For the target and the relocation, we want to know if they are
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6264ab1a3da74a..af7aaff8a4c03b 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -301,6 +301,16 @@ inline void write32(void *p, uint32_t v) {
inline void write64(void *p, uint64_t v) {
llvm::support::endian::write64(p, v, config->endianness);
}
+
+// Overwrite a ULEB128 value and keep the original length.
+inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
+ while (*bufLoc & 0x80) {
+ *bufLoc++ = 0x80 | (val & 0x7f);
+ val >>= 7;
+ }
+ *bufLoc = val;
+ return val;
+}
} // namespace elf
} // namespace lld
diff --git a/lld/test/ELF/riscv-reloc-leb128.s b/lld/test/ELF/riscv-reloc-leb128.s
index 8198819686c3c8..0bdc1eb18269dd 100644
--- a/lld/test/ELF/riscv-reloc-leb128.s
+++ b/lld/test/ELF/riscv-reloc-leb128.s
@@ -1,13 +1,13 @@
# REQUIRES: riscv
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax a.s -o a.o
-# RUN: llvm-readobj -r -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 .debug_rnglists -x .debug_loclists a.so | FileCheck %s
+# 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 --noinhibit-exec a.o -o a.so
+# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.so | FileCheck %s
# REL: .rela.debug_rnglists {
-# REL-NEXT: 0x0 R_RISCV_SET_ULEB128 w1 0x83
-# REL-NEXT: 0x0 R_RISCV_SUB_ULEB128 w2 0x0
+# REL-NEXT: 0x0 R_RISCV_SET_ULEB128 w1 0x82
+# REL-NEXT: 0x0 R_RISCV_SUB_ULEB128 w2 0xFFFFFFFFFFFFFFFF
# REL-NEXT: 0x1 R_RISCV_SET_ULEB128 w2 0x78
# REL-NEXT: 0x1 R_RISCV_SUB_ULEB128 w1 0x0
# REL-NEXT: 0x3 R_RISCV_SET_ULEB128 w1 0x89
@@ -28,12 +28,18 @@
# REL-NEXT: 0x1 R_RISCV_SUB_ULEB128 x1 0x0
# REL-NEXT: }
+# REL: Hex dump of section '.gcc_except_table':
+# REL-NEXT: 0x00000000 7b800181 01808001 81800180 80800181 {
+# REL-NEXT: 0x00000010 808001 .
# REL: Hex dump of section '.debug_rnglists':
# REL-NEXT: 0x00000000 7b800181 01808001 81800180 80800181 {
# REL-NEXT: 0x00000010 808001 .
# REL: Hex dump of section '.debug_loclists':
# REL-NEXT: 0x00000000 0008 .
+# CHECK: Hex dump of section '.gcc_except_table':
+# CHECK-NEXT: 0x[[#%x,]] 7ffc0085 01fcff00 858001fc ffff0085 .
+# CHECK-NEXT: 0x[[#%x,]] 808001 .
# CHECK: Hex dump of section '.debug_rnglists':
# CHECK-NEXT: 0x00000000 7ffc0085 01fcff00 858001fc ffff0085 .
# CHECK-NEXT: 0x00000010 808001 .
@@ -50,21 +56,32 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax sub.s -o sub.o
# RUN: not ld.lld -shared sub.o 2>&1 | FileCheck %s --check-prefix=SUB
-# SUB: error: sub.o:(.debug_rnglists+0x8): unknown relocation (61) against symbol w2
+# SUB: error: sub.o:(.debug_rnglists+0x8): has non-ABS relocation R_RISCV_SUB_ULEB128 against symbol 'w2'
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired1.s -o unpaired1.o
-# RUN: not ld.lld -shared unpaired1.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired1.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired2.s -o unpaired2.o
-# RUN: not ld.lld -shared unpaired2.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired2.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired3.s -o unpaired3.o
-# RUN: not ld.lld -shared unpaired3.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired3.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# UNPAIRED: error: {{.*}}.o:(.alloc+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128
# UNPAIRED: error: {{.*}}.o:(.debug_rnglists+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax overflow.s -o overflow.o
-# RUN: not ld.lld -shared overflow.o 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+# RUN: not ld.lld -shared --threads=1 overflow.o 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+# OVERFLOW: error: overflow.o:(.alloc+0x8): ULEB128 value 128 exceeds available space; references 'w2'
# OVERFLOW: error: overflow.o:(.debug_rnglists+0x8): ULEB128 value 128 exceeds available space; references 'w2'
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax preemptable.s -o preemptable.o
+# RUN: not ld.lld -shared --threads=1 preemptable.o 2>&1 | FileCheck %s --check-prefix=PREEMPTABLE --implicit-check-not=error:
+# PREEMPTABLE: error: relocation R_RISCV_SET_ULEB128 cannot be used against symbol 'w2'; recompile with -fPIC
+# PREEMPTABLE: error: relocation R_RISCV_SUB_ULEB128 cannot be used against symbol 'w1'; recompile with -fPIC
+
#--- a.s
+.cfi_startproc
+.cfi_lsda 0x1b,.LLSDA0
+.cfi_endproc
+
.section .text.w,"axR"
w1:
call foo # 4 bytes after relaxation
@@ -75,8 +92,22 @@ x1:
call foo # 4 bytes after relaxation
x2:
+.section .gcc_except_table,"a"
+.LLSDA0:
+.reloc ., R_RISCV_SET_ULEB128, w1+130
+.reloc ., R_RISCV_SUB_ULEB128, w2-1 # non-zero addend for SUB
+.byte 0x7b
+.uleb128 w2-w1+120 # initial value: 0x0180
+.uleb128 w1-w2+137 # initial value: 0x0181
+.uleb128 w2-w1+16376 # initial value: 0x018080
+.uleb128 w1-w2+16393 # initial value: 0x018081
+.uleb128 w2-w1+2097144 # initial value: 0x01808080
+.uleb128 w1-w2+2097161 # initial value: 0x01808081
+
.section .debug_rnglists
-.uleb128 w1-w2+131 # initial value: 0x7b
+.reloc ., R_RISCV_SET_ULEB128, w1+130
+.reloc ., R_RISCV_SUB_ULEB128, w2-1 # non-zero addend for SUB
+.byte 0x7b
.uleb128 w2-w1+120 # initial value: 0x0180
.uleb128 w1-w2+137 # initial value: 0x0181
.uleb128 w2-w1+16376 # initial value: 0x018080
@@ -99,6 +130,10 @@ w1: call foo; w2:
#--- unpaired1.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.byte 0x7f
.section .debug_rnglists
.quad 0;
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -106,6 +141,11 @@ w1: call foo; w2:
#--- unpaired2.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.reloc .+1, R_RISCV_SUB_ULEB128, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -114,6 +154,11 @@ w1: call foo; w2:
#--- unpaired3.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.reloc ., R_RISCV_SUB64, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -122,8 +167,21 @@ w1: call foo; w2:
#--- overflow.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+124
+.reloc ., R_RISCV_SUB_ULEB128, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+124
.reloc ., R_RISCV_SUB_ULEB128, w1
.byte 0x7f
+
+#--- preemptable.s
+.globl w1, w2
+w1: call foo; w2:
+.section .alloc,"a"
+.uleb128 w2-w1
+.section .debug_rnglists
+.uleb128 w2-w1
|
@llvm/pr-subscribers-lld-elf Author: Fangrui Song (MaskRay) ChangesComplement #72610 (non-SHF_ALLOC sections). GCC-generated Full diff: https://github.com/llvm/llvm-project/pull/77261.diff 5 Files Affected:
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 898e3e45b9e724..1d3d179e5d6fb5 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -43,6 +43,7 @@ class RISCV final : public TargetInfo {
const uint8_t *loc) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
+ void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
bool relaxOnce(int pass) const override;
};
@@ -307,6 +308,7 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
case R_RISCV_RELAX:
return config->relax ? R_RELAX_HINT : R_NONE;
case R_RISCV_SET_ULEB128:
+ case R_RISCV_SUB_ULEB128:
return R_RISCV_LEB128;
default:
error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
@@ -515,6 +517,46 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}
+void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
+ uint64_t secAddr = sec.getOutputSection()->addr;
+ if (auto *s = dyn_cast<InputSection>(&sec))
+ secAddr += s->outSecOff;
+ else if (auto *ehIn = dyn_cast<EhInputSection>(&sec))
+ secAddr += ehIn->getParent()->outSecOff;
+ for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
+ const Relocation &rel = sec.relocs()[i];
+ uint8_t *loc = buf + rel.offset;
+ const uint64_t val =
+ sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
+ secAddr + rel.offset, *rel.sym, rel.expr);
+
+ switch (rel.expr) {
+ case R_RELAX_HINT:
+ break;
+ case R_RISCV_LEB128:
+ if (i + 1 < size) {
+ const Relocation &rel1 = sec.relocs()[i + 1];
+ if (rel.type == R_RISCV_SET_ULEB128 &&
+ rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) {
+ auto val = rel.sym->getVA(rel.addend) - rel1.sym->getVA(rel1.addend);
+ if (overwriteULEB128(loc, val) >= 0x80)
+ errorOrWarn(sec.getLocation(rel.offset) + ": ULEB128 value " +
+ Twine(val) + " exceeds available space; references '" +
+ lld::toString(*rel.sym) + "'");
+ ++i;
+ continue;
+ }
+ }
+ errorOrWarn(sec.getLocation(rel.offset) +
+ ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128");
+ return;
+ default:
+ relocate(loc, rel, val);
+ break;
+ }
+ }
+}
+
namespace {
struct SymbolAnchor {
uint64_t offset;
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 5dfb57fda432e0..53b496bd084258 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -671,6 +671,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
case R_RISCV_ADD:
+ case R_RISCV_LEB128:
return sym.getVA(a);
case R_ADDEND:
return a;
@@ -875,16 +876,6 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
}
}
-// Overwrite a ULEB128 value and keep the original length.
-static uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
- while (*bufLoc & 0x80) {
- *bufLoc++ = 0x80 | (val & 0x7f);
- val >>= 7;
- }
- *bufLoc = val;
- return val;
-}
-
// This function applies relocations to sections without SHF_ALLOC bit.
// Such sections are never mapped to memory at runtime. Debug sections are
// an example. Relocations in non-alloc sections are much easier to
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 210b4d1eb1a7a6..9eb2e82542d3d4 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -988,8 +988,8 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
if (!config->isPic)
return true;
- // The size of a non preemptible symbol is a constant.
- if (e == R_SIZE)
+ // Constant when referencing a non-preemptible symbol.
+ if (e == R_SIZE || e == R_RISCV_LEB128)
return true;
// For the target and the relocation, we want to know if they are
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6264ab1a3da74a..af7aaff8a4c03b 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -301,6 +301,16 @@ inline void write32(void *p, uint32_t v) {
inline void write64(void *p, uint64_t v) {
llvm::support::endian::write64(p, v, config->endianness);
}
+
+// Overwrite a ULEB128 value and keep the original length.
+inline uint64_t overwriteULEB128(uint8_t *bufLoc, uint64_t val) {
+ while (*bufLoc & 0x80) {
+ *bufLoc++ = 0x80 | (val & 0x7f);
+ val >>= 7;
+ }
+ *bufLoc = val;
+ return val;
+}
} // namespace elf
} // namespace lld
diff --git a/lld/test/ELF/riscv-reloc-leb128.s b/lld/test/ELF/riscv-reloc-leb128.s
index 8198819686c3c8..0bdc1eb18269dd 100644
--- a/lld/test/ELF/riscv-reloc-leb128.s
+++ b/lld/test/ELF/riscv-reloc-leb128.s
@@ -1,13 +1,13 @@
# REQUIRES: riscv
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax a.s -o a.o
-# RUN: llvm-readobj -r -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 .debug_rnglists -x .debug_loclists a.so | FileCheck %s
+# 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 --noinhibit-exec a.o -o a.so
+# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.so | FileCheck %s
# REL: .rela.debug_rnglists {
-# REL-NEXT: 0x0 R_RISCV_SET_ULEB128 w1 0x83
-# REL-NEXT: 0x0 R_RISCV_SUB_ULEB128 w2 0x0
+# REL-NEXT: 0x0 R_RISCV_SET_ULEB128 w1 0x82
+# REL-NEXT: 0x0 R_RISCV_SUB_ULEB128 w2 0xFFFFFFFFFFFFFFFF
# REL-NEXT: 0x1 R_RISCV_SET_ULEB128 w2 0x78
# REL-NEXT: 0x1 R_RISCV_SUB_ULEB128 w1 0x0
# REL-NEXT: 0x3 R_RISCV_SET_ULEB128 w1 0x89
@@ -28,12 +28,18 @@
# REL-NEXT: 0x1 R_RISCV_SUB_ULEB128 x1 0x0
# REL-NEXT: }
+# REL: Hex dump of section '.gcc_except_table':
+# REL-NEXT: 0x00000000 7b800181 01808001 81800180 80800181 {
+# REL-NEXT: 0x00000010 808001 .
# REL: Hex dump of section '.debug_rnglists':
# REL-NEXT: 0x00000000 7b800181 01808001 81800180 80800181 {
# REL-NEXT: 0x00000010 808001 .
# REL: Hex dump of section '.debug_loclists':
# REL-NEXT: 0x00000000 0008 .
+# CHECK: Hex dump of section '.gcc_except_table':
+# CHECK-NEXT: 0x[[#%x,]] 7ffc0085 01fcff00 858001fc ffff0085 .
+# CHECK-NEXT: 0x[[#%x,]] 808001 .
# CHECK: Hex dump of section '.debug_rnglists':
# CHECK-NEXT: 0x00000000 7ffc0085 01fcff00 858001fc ffff0085 .
# CHECK-NEXT: 0x00000010 808001 .
@@ -50,21 +56,32 @@
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax sub.s -o sub.o
# RUN: not ld.lld -shared sub.o 2>&1 | FileCheck %s --check-prefix=SUB
-# SUB: error: sub.o:(.debug_rnglists+0x8): unknown relocation (61) against symbol w2
+# SUB: error: sub.o:(.debug_rnglists+0x8): has non-ABS relocation R_RISCV_SUB_ULEB128 against symbol 'w2'
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired1.s -o unpaired1.o
-# RUN: not ld.lld -shared unpaired1.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired1.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired2.s -o unpaired2.o
-# RUN: not ld.lld -shared unpaired2.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired2.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax unpaired3.s -o unpaired3.o
-# RUN: not ld.lld -shared unpaired3.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# RUN: not ld.lld -shared --threads=1 unpaired3.o 2>&1 | FileCheck %s --check-prefix=UNPAIRED
+# UNPAIRED: error: {{.*}}.o:(.alloc+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128
# UNPAIRED: error: {{.*}}.o:(.debug_rnglists+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax overflow.s -o overflow.o
-# RUN: not ld.lld -shared overflow.o 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+# RUN: not ld.lld -shared --threads=1 overflow.o 2>&1 | FileCheck %s --check-prefix=OVERFLOW
+# OVERFLOW: error: overflow.o:(.alloc+0x8): ULEB128 value 128 exceeds available space; references 'w2'
# OVERFLOW: error: overflow.o:(.debug_rnglists+0x8): ULEB128 value 128 exceeds available space; references 'w2'
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax preemptable.s -o preemptable.o
+# RUN: not ld.lld -shared --threads=1 preemptable.o 2>&1 | FileCheck %s --check-prefix=PREEMPTABLE --implicit-check-not=error:
+# PREEMPTABLE: error: relocation R_RISCV_SET_ULEB128 cannot be used against symbol 'w2'; recompile with -fPIC
+# PREEMPTABLE: error: relocation R_RISCV_SUB_ULEB128 cannot be used against symbol 'w1'; recompile with -fPIC
+
#--- a.s
+.cfi_startproc
+.cfi_lsda 0x1b,.LLSDA0
+.cfi_endproc
+
.section .text.w,"axR"
w1:
call foo # 4 bytes after relaxation
@@ -75,8 +92,22 @@ x1:
call foo # 4 bytes after relaxation
x2:
+.section .gcc_except_table,"a"
+.LLSDA0:
+.reloc ., R_RISCV_SET_ULEB128, w1+130
+.reloc ., R_RISCV_SUB_ULEB128, w2-1 # non-zero addend for SUB
+.byte 0x7b
+.uleb128 w2-w1+120 # initial value: 0x0180
+.uleb128 w1-w2+137 # initial value: 0x0181
+.uleb128 w2-w1+16376 # initial value: 0x018080
+.uleb128 w1-w2+16393 # initial value: 0x018081
+.uleb128 w2-w1+2097144 # initial value: 0x01808080
+.uleb128 w1-w2+2097161 # initial value: 0x01808081
+
.section .debug_rnglists
-.uleb128 w1-w2+131 # initial value: 0x7b
+.reloc ., R_RISCV_SET_ULEB128, w1+130
+.reloc ., R_RISCV_SUB_ULEB128, w2-1 # non-zero addend for SUB
+.byte 0x7b
.uleb128 w2-w1+120 # initial value: 0x0180
.uleb128 w1-w2+137 # initial value: 0x0181
.uleb128 w2-w1+16376 # initial value: 0x018080
@@ -99,6 +130,10 @@ w1: call foo; w2:
#--- unpaired1.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.byte 0x7f
.section .debug_rnglists
.quad 0;
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -106,6 +141,11 @@ w1: call foo; w2:
#--- unpaired2.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.reloc .+1, R_RISCV_SUB_ULEB128, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -114,6 +154,11 @@ w1: call foo; w2:
#--- unpaired3.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+120
+.reloc ., R_RISCV_SUB64, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+120
@@ -122,8 +167,21 @@ w1: call foo; w2:
#--- overflow.s
w1: call foo; w2:
+.section .alloc,"a"
+.quad 0
+.reloc ., R_RISCV_SET_ULEB128, w2+124
+.reloc ., R_RISCV_SUB_ULEB128, w1
+.byte 0x7f
.section .debug_rnglists
.quad 0
.reloc ., R_RISCV_SET_ULEB128, w2+124
.reloc ., R_RISCV_SUB_ULEB128, w1
.byte 0x7f
+
+#--- preemptable.s
+.globl w1, w2
+w1: call foo; w2:
+.section .alloc,"a"
+.uleb128 w2-w1
+.section .debug_rnglists
+.uleb128 w2-w1
|
.byte 0x7f | ||
|
||
#--- preemptable.s | ||
.globl w1, w2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the future, I'll consider making R_RISCV_ADD
a constant only if !isPreemptible
like R_RISCV_LEB128
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, LGTM :)
switch (rel.expr) { | ||
case R_RELAX_HINT: | ||
break; | ||
case R_RISCV_LEB128: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll merge this soon. relocateAlloc
is needed for TLSDESC relaxation as well.
…ctions (llvm#77261) Complement llvm#72610 (non-SHF_ALLOC sections). GCC-generated .gcc_exception_table has the SHF_ALLOC flag and may contain R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations.
…ctions (llvm#77261) Complement llvm#72610 (non-SHF_ALLOC sections). GCC-generated .gcc_exception_table has the SHF_ALLOC flag and may contain R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations.
…ctions (llvm#77261) Complement llvm#72610 (non-SHF_ALLOC sections). GCC-generated .gcc_exception_table has the SHF_ALLOC flag and may contain R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations.
…ctions (llvm#77261) Complement llvm#72610 (non-SHF_ALLOC sections). GCC-generated .gcc_exception_table has the SHF_ALLOC flag and may contain R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations.
…able Call site records in .gcc_except_table reference text sections. https://reviews.llvm.org/D63415 switched the encoding to DW_EH_PE_udata4 so that `.uleb128 A-B`, which requires relocations in the generic case in presence of linker relaxation, can be avoided. binutils 2.41 and latest lld (llvm#77261) support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128. This patch restores DW_EH_PE_uleb128 to make .gcc_except_table smaller. Sparc is restored as well, which was incorrectly changed by https://reviews.llvm.org/D63415 . emitCallSiteOffset/emitCallSiteValue should be preserved as now AIX uses the DW_EH_PE_udata4 code path. Pull Request: llvm#77276
Backported from: commit 7ffabb6 Author: Fangrui Song <i@maskray.me> Date: Tue Nov 21 07:43:29 2023 -0800 [ELF] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 in non-SHF_ALLOC sections (llvm#72610) commit 3fa1795 Author: Fangrui Song <i@maskray.me> Date: Mon Jan 8 20:24:00 2024 -0800 [ELF] Support R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 in SHF_ALLOC sections (llvm#77261)
Complement #72610 (non-SHF_ALLOC sections). GCC-generated
.gcc_exception_table has the SHF_ALLOC flag and may contain
R_RISCV_SET_ULEB128/R_RISCV_SUB_ULEB128 relocations.