[ELF] Add target-specific relocation scanning for RISC-V (#181332)
Implement RISCV::scanSectionImpl, following the pattern established for x86 (#178846) and AArch64 (#181099). This merges the getRelExpr and TLS handling for SHF_ALLOC sections into the target-specific scanner, enabling devirtualization and eliminating abstraction overhead. - Inline relocation classification into scanSectionImpl with a switch on relocation type, replacing the generic rs.scan() path. - Use processR_PC/processR_PLT_PC for common PC-relative and PLT relocations. - Handle TLS IE and GD directly (RISC-V does not optimize GD/LD/IE). - Replace TLS-optimization-specific expressions for TLSDESC, following the x86 pattern: R_RELAX_TLS_GD_TO_IE -> R_GOT_PC, R_RELAX_TLS_GD_TO_LE -> R_TPREL. Update relocateAlloc and relax() to dispatch on relocation type instead of RelExpr for TLSDESC. - Simplify getRelExpr to only handle relocations needed by relocateNonAlloc and preprocessRelocs. - Remove RISC-V-specific checks from handleTlsRelocation (isRISCV variable, TLSDESC label special cases). - Move R_RISCV_VENDOR handling into the relocation type switch. An undefined vendor symbol now gets the standard undefined symbol error instead of a vendor-specific diagnostic.
This commit is contained in:
parent
f7ca74f600
commit
4ea72c1e8c
@ -278,17 +278,15 @@ RelType RISCV::getDynRel(RelType type) const {
|
||||
: static_cast<RelType>(R_RISCV_NONE);
|
||||
}
|
||||
|
||||
// Only needed to support relocations used by relocateNonAlloc and
|
||||
// preprocessRelocs.
|
||||
RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
|
||||
const uint8_t *loc) const {
|
||||
switch (type) {
|
||||
case R_RISCV_NONE:
|
||||
case R_RISCV_VENDOR:
|
||||
return R_NONE;
|
||||
case R_RISCV_32:
|
||||
case R_RISCV_64:
|
||||
case R_RISCV_HI20:
|
||||
case R_RISCV_LO12_I:
|
||||
case R_RISCV_LO12_S:
|
||||
return R_ABS;
|
||||
case R_RISCV_ADD8:
|
||||
case R_RISCV_ADD16:
|
||||
@ -304,42 +302,8 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
|
||||
case R_RISCV_SUB32:
|
||||
case R_RISCV_SUB64:
|
||||
return RE_RISCV_ADD;
|
||||
case R_RISCV_JAL:
|
||||
case R_RISCV_BRANCH:
|
||||
case R_RISCV_PCREL_HI20:
|
||||
case R_RISCV_RVC_BRANCH:
|
||||
case R_RISCV_RVC_JUMP:
|
||||
case R_RISCV_32_PCREL:
|
||||
return R_PC;
|
||||
case R_RISCV_CALL:
|
||||
case R_RISCV_CALL_PLT:
|
||||
case R_RISCV_PLT32:
|
||||
return R_PLT_PC;
|
||||
case R_RISCV_GOT_HI20:
|
||||
case R_RISCV_GOT32_PCREL:
|
||||
return R_GOT_PC;
|
||||
case R_RISCV_PCREL_LO12_I:
|
||||
case R_RISCV_PCREL_LO12_S:
|
||||
return RE_RISCV_PC_INDIRECT;
|
||||
case R_RISCV_TLSDESC_HI20:
|
||||
case R_RISCV_TLSDESC_LOAD_LO12:
|
||||
case R_RISCV_TLSDESC_ADD_LO12:
|
||||
return R_TLSDESC_PC;
|
||||
case R_RISCV_TLSDESC_CALL:
|
||||
return R_TLSDESC_CALL;
|
||||
case R_RISCV_TLS_GD_HI20:
|
||||
return R_TLSGD_PC;
|
||||
case R_RISCV_TLS_GOT_HI20:
|
||||
return R_GOT_PC;
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_TPREL_LO12_I:
|
||||
case R_RISCV_TPREL_LO12_S:
|
||||
return R_TPREL;
|
||||
case R_RISCV_ALIGN:
|
||||
return R_RELAX_HINT;
|
||||
case R_RISCV_TPREL_ADD:
|
||||
case R_RISCV_RELAX:
|
||||
return ctx.arg.relax ? R_RELAX_HINT : R_NONE;
|
||||
case R_RISCV_SET_ULEB128:
|
||||
case R_RISCV_SUB_ULEB128:
|
||||
return RE_RISCV_LEB128;
|
||||
@ -356,29 +320,152 @@ void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
|
||||
// Many relocations end up in sec.relocations.
|
||||
sec.relocations.reserve(rels.size());
|
||||
|
||||
StringRef rvVendor;
|
||||
StringRef vendor;
|
||||
for (auto it = rels.begin(); it != rels.end(); ++it) {
|
||||
RelType type = it->getType(false);
|
||||
uint32_t symIndex = it->getSymbol(false);
|
||||
Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
|
||||
const uint8_t *loc = sec.content().data() + it->r_offset;
|
||||
|
||||
if (type == R_RISCV_VENDOR) {
|
||||
if (!rvVendor.empty())
|
||||
Err(ctx) << getErrorLoc(ctx, loc)
|
||||
<< "malformed consecutive R_RISCV_VENDOR relocations";
|
||||
rvVendor = sym.getName();
|
||||
uint64_t offset = it->r_offset;
|
||||
if (sym.isUndefined() && symIndex != 0 &&
|
||||
rs.maybeReportUndefined(cast<Undefined>(sym), offset))
|
||||
continue;
|
||||
} else if (!rvVendor.empty()) {
|
||||
Err(ctx) << getErrorLoc(ctx, loc)
|
||||
<< "unknown vendor-specific relocation (" << type.v
|
||||
<< ") in namespace '" << rvVendor << "' against symbol '" << &sym
|
||||
<< "'";
|
||||
rvVendor = "";
|
||||
int64_t addend = rs.getAddend<ELFT>(*it, type);
|
||||
RelExpr expr;
|
||||
// Relocation types that only need a RelExpr set `expr` and break out of
|
||||
// the switch to reach rs.process(). Types that need special handling
|
||||
// (fast-path helpers, TLS) call a handler and use `continue`.
|
||||
switch (type) {
|
||||
case R_RISCV_NONE:
|
||||
continue;
|
||||
|
||||
// Absolute relocations:
|
||||
case R_RISCV_32:
|
||||
case R_RISCV_64:
|
||||
case R_RISCV_HI20:
|
||||
case R_RISCV_LO12_I:
|
||||
case R_RISCV_LO12_S:
|
||||
expr = R_ABS;
|
||||
break;
|
||||
|
||||
// PC-relative relocations:
|
||||
case R_RISCV_JAL:
|
||||
case R_RISCV_BRANCH:
|
||||
case R_RISCV_PCREL_HI20:
|
||||
case R_RISCV_RVC_BRANCH:
|
||||
case R_RISCV_RVC_JUMP:
|
||||
case R_RISCV_32_PCREL:
|
||||
rs.processR_PC(type, offset, addend, sym);
|
||||
continue;
|
||||
case R_RISCV_PCREL_LO12_I:
|
||||
case R_RISCV_PCREL_LO12_S:
|
||||
expr = RE_RISCV_PC_INDIRECT;
|
||||
break;
|
||||
|
||||
// PLT-generating relocations:
|
||||
case R_RISCV_CALL:
|
||||
case R_RISCV_CALL_PLT:
|
||||
case R_RISCV_PLT32:
|
||||
rs.processR_PLT_PC(type, offset, addend, sym);
|
||||
continue;
|
||||
|
||||
// GOT-generating relocations:
|
||||
case R_RISCV_GOT_HI20:
|
||||
case R_RISCV_GOT32_PCREL:
|
||||
expr = R_GOT_PC;
|
||||
break;
|
||||
|
||||
// TLS relocations:
|
||||
case R_RISCV_TPREL_HI20:
|
||||
case R_RISCV_TPREL_LO12_I:
|
||||
case R_RISCV_TPREL_LO12_S:
|
||||
if (rs.checkTlsLe(offset, sym, type))
|
||||
continue;
|
||||
expr = R_TPREL;
|
||||
break;
|
||||
case R_RISCV_TLS_GOT_HI20:
|
||||
// There is no IE to LE optimization.
|
||||
rs.handleTlsIe<false>(R_GOT_PC, type, offset, addend, sym);
|
||||
continue;
|
||||
case R_RISCV_TLS_GD_HI20:
|
||||
// There is no GD to IE/LE optimization.
|
||||
rs.handleTlsGd(R_TLSGD_PC, R_NONE, R_NONE, type, offset, addend, sym);
|
||||
continue;
|
||||
|
||||
// TLSDESC relocations:
|
||||
case R_RISCV_TLSDESC_HI20:
|
||||
rs.handleTlsDesc(R_TLSDESC_PC, R_GOT_PC, type, offset, addend, sym);
|
||||
continue;
|
||||
case R_RISCV_TLSDESC_LOAD_LO12:
|
||||
case R_RISCV_TLSDESC_ADD_LO12:
|
||||
// R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} reference a label, not the
|
||||
// TLS symbol, so we cannot use handleTlsDesc (which sets NEEDS_TLSDESC).
|
||||
// For TLSDESC->IE, use R_TPREL as well, but relocateAlloc uses isToLe
|
||||
// (from HI20) to select the correct transform.
|
||||
sec.addReloc({ctx.arg.shared ? R_TLSDESC_PC : R_TPREL, type, offset,
|
||||
addend, &sym});
|
||||
continue;
|
||||
case R_RISCV_TLSDESC_CALL:
|
||||
if (!ctx.arg.shared)
|
||||
sec.addReloc({R_TPREL, type, offset, addend, &sym});
|
||||
continue;
|
||||
|
||||
// Relaxation hints:
|
||||
case R_RISCV_ALIGN:
|
||||
sec.addReloc({R_RELAX_HINT, type, offset, addend, &sym});
|
||||
continue;
|
||||
case R_RISCV_TPREL_ADD:
|
||||
case R_RISCV_RELAX:
|
||||
if (ctx.arg.relax)
|
||||
sec.addReloc({R_RELAX_HINT, type, offset, addend, &sym});
|
||||
continue;
|
||||
|
||||
// Misc relocations:
|
||||
case R_RISCV_ADD8:
|
||||
case R_RISCV_ADD16:
|
||||
case R_RISCV_ADD32:
|
||||
case R_RISCV_ADD64:
|
||||
case R_RISCV_SET6:
|
||||
case R_RISCV_SET8:
|
||||
case R_RISCV_SET16:
|
||||
case R_RISCV_SET32:
|
||||
case R_RISCV_SUB6:
|
||||
case R_RISCV_SUB8:
|
||||
case R_RISCV_SUB16:
|
||||
case R_RISCV_SUB32:
|
||||
case R_RISCV_SUB64:
|
||||
expr = RE_RISCV_ADD;
|
||||
break;
|
||||
case R_RISCV_SET_ULEB128:
|
||||
case R_RISCV_SUB_ULEB128:
|
||||
expr = RE_RISCV_LEB128;
|
||||
break;
|
||||
|
||||
case R_RISCV_VENDOR: {
|
||||
auto it1 = it;
|
||||
++it1;
|
||||
if (it1 == rels.end() || it1->getType(false) - 192u > 63u) {
|
||||
Err(ctx) << getErrorLoc(ctx, sec.content().data() + offset)
|
||||
<< "R_RISCV_VENDOR is not followed by a relocation of code "
|
||||
"192 to 255";
|
||||
continue;
|
||||
}
|
||||
vendor = sym.getName();
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
auto diag = Err(ctx);
|
||||
diag << getErrorLoc(ctx, sec.content().data() + offset);
|
||||
if (!vendor.empty()) {
|
||||
diag << "unknown vendor-specific relocation (" << type.v
|
||||
<< ") in namespace '" << vendor << "' against symbol '" << &sym
|
||||
<< "'";
|
||||
vendor = "";
|
||||
} else {
|
||||
diag << "unknown relocation (" << type.v << ") against symbol " << &sym;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
|
||||
rs.process(expr, type, offset, sym, addend);
|
||||
}
|
||||
|
||||
// Sort relocations by offset for more efficient searching for
|
||||
@ -664,47 +751,52 @@ void RISCV::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
uint8_t *loc = buf + rel.offset;
|
||||
uint64_t val = sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset);
|
||||
|
||||
switch (rel.expr) {
|
||||
case R_RELAX_HINT:
|
||||
switch (rel.type) {
|
||||
case R_RISCV_ALIGN:
|
||||
case R_RISCV_RELAX:
|
||||
case R_RISCV_TPREL_ADD:
|
||||
continue;
|
||||
case R_TLSDESC_PC:
|
||||
// For R_RISCV_TLSDESC_HI20, store &got(sym)-PC to be used by the
|
||||
// following two instructions L[DW] and ADDI.
|
||||
if (rel.type == R_RISCV_TLSDESC_HI20)
|
||||
case R_RISCV_TLSDESC_HI20:
|
||||
if (rel.expr == R_TLSDESC_PC) {
|
||||
// Shared object: store &got(sym)-PC for the following L[DW]/ADDI.
|
||||
tlsdescVal = val;
|
||||
else
|
||||
val = tlsdescVal;
|
||||
break;
|
||||
case R_RELAX_TLS_GD_TO_IE:
|
||||
// Only R_RISCV_TLSDESC_HI20 reaches here. tlsdescVal will be finalized
|
||||
// after we see R_RISCV_TLSDESC_ADD_LO12 in the R_RELAX_TLS_GD_TO_LE case.
|
||||
// The net effect is that tlsdescVal will be smaller than `val` to take
|
||||
// into account of NOP instructions (in the absence of R_RISCV_RELAX)
|
||||
// before AUIPC.
|
||||
tlsdescVal = val + rel.offset;
|
||||
isToLe = false;
|
||||
tlsdescRelax = relaxable(relocs, i);
|
||||
if (!tlsdescRelax)
|
||||
tlsdescToIe(ctx, loc, rel, val);
|
||||
continue;
|
||||
case R_RELAX_TLS_GD_TO_LE:
|
||||
// See the comment in handleTlsRelocation. For TLSDESC=>IE,
|
||||
// R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12,CALL} also reach here. If isToLe is
|
||||
// false, this is actually TLSDESC=>IE optimization.
|
||||
if (rel.type == R_RISCV_TLSDESC_HI20) {
|
||||
tlsdescVal = val;
|
||||
isToLe = true;
|
||||
tlsdescRelax = relaxable(relocs, i);
|
||||
} else {
|
||||
if (!isToLe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
|
||||
tlsdescVal -= rel.offset;
|
||||
val = tlsdescVal;
|
||||
break;
|
||||
}
|
||||
// Executable: TLSDESC->LE (R_TPREL) or TLSDESC->IE (R_GOT_PC).
|
||||
isToLe = rel.expr == R_TPREL;
|
||||
if (isToLe) {
|
||||
tlsdescVal = val;
|
||||
} else {
|
||||
// tlsdescVal will be finalized after we see R_RISCV_TLSDESC_ADD_LO12.
|
||||
// The net effect is that tlsdescVal will be smaller than `val` to
|
||||
// take into account of NOP instructions (in the absence of
|
||||
// R_RISCV_RELAX) before AUIPC.
|
||||
tlsdescVal = val + rel.offset;
|
||||
}
|
||||
tlsdescRelax = relaxable(relocs, i);
|
||||
if (!tlsdescRelax) {
|
||||
if (isToLe)
|
||||
tlsdescToLe(loc, rel, val);
|
||||
else
|
||||
tlsdescToIe(ctx, loc, rel, val);
|
||||
}
|
||||
continue;
|
||||
case R_RISCV_TLSDESC_LOAD_LO12:
|
||||
case R_RISCV_TLSDESC_ADD_LO12:
|
||||
case R_RISCV_TLSDESC_CALL:
|
||||
if (rel.expr == R_TLSDESC_PC) {
|
||||
// Shared object: propagate the stored GOT value.
|
||||
val = tlsdescVal;
|
||||
break;
|
||||
}
|
||||
// Executable: IE or LE instruction rewrite.
|
||||
if (!isToLe && rel.type == R_RISCV_TLSDESC_ADD_LO12)
|
||||
tlsdescVal -= rel.offset;
|
||||
val = tlsdescVal;
|
||||
// When NOP conversion is eligible and relaxation applies, don't write a
|
||||
// NOP in case an unrelated instruction follows the current instruction.
|
||||
if (tlsdescRelax &&
|
||||
(rel.type == R_RISCV_TLSDESC_HI20 ||
|
||||
rel.type == R_RISCV_TLSDESC_LOAD_LO12 ||
|
||||
(rel.type == R_RISCV_TLSDESC_LOAD_LO12 ||
|
||||
(rel.type == R_RISCV_TLSDESC_ADD_LO12 && isToLe && !hi20(val))))
|
||||
continue;
|
||||
if (isToLe)
|
||||
@ -712,11 +804,10 @@ void RISCV::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
else
|
||||
tlsdescToIe(ctx, loc, rel, val);
|
||||
continue;
|
||||
case RE_RISCV_LEB128:
|
||||
case R_RISCV_SET_ULEB128:
|
||||
if (i + 1 < size) {
|
||||
const Relocation &rel1 = relocs[i + 1];
|
||||
if (rel.type == R_RISCV_SET_ULEB128 &&
|
||||
rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) {
|
||||
if (rel1.type == R_RISCV_SUB_ULEB128 && rel.offset == rel1.offset) {
|
||||
auto val = rel.sym->getVA(ctx, rel.addend) -
|
||||
rel1.sym->getVA(ctx, rel1.addend);
|
||||
if (overwriteULEB128(loc, val) >= 0x80)
|
||||
@ -728,7 +819,7 @@ void RISCV::relocateAlloc(InputSection &sec, uint8_t *buf) const {
|
||||
}
|
||||
}
|
||||
Err(ctx) << sec.getLocation(rel.offset)
|
||||
<< ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128";
|
||||
<< ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_ULEB128";
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
@ -956,7 +1047,7 @@ static bool relax(Ctx &ctx, int pass, InputSection &sec) {
|
||||
case R_RISCV_TLSDESC_HI20:
|
||||
// For TLSDESC=>LE, we can use the short form if hi20 is zero.
|
||||
tlsdescRelax = relaxable(relocs, i);
|
||||
toLeShortForm = tlsdescRelax && r.expr == R_RELAX_TLS_GD_TO_LE &&
|
||||
toLeShortForm = tlsdescRelax && r.expr == R_TPREL &&
|
||||
!hi20(r.sym->getVA(ctx, r.addend));
|
||||
[[fallthrough]];
|
||||
case R_RISCV_TLSDESC_LOAD_LO12:
|
||||
|
||||
@ -1101,7 +1101,7 @@ void InputSection::relocateNonAlloc(Ctx &ctx, uint8_t *buf,
|
||||
continue;
|
||||
}
|
||||
Err(ctx) << getLocation(offset)
|
||||
<< ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_SET128";
|
||||
<< ": R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_ULEB128";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -1136,35 +1136,24 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type,
|
||||
if (expr == R_TPREL || expr == R_TPREL_NEG)
|
||||
return checkTlsLe(offset, sym, type) ? 1 : 0;
|
||||
|
||||
bool isRISCV = ctx.arg.emachine == EM_RISCV;
|
||||
|
||||
if (oneof<R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC, R_TLSDESC_GOTPLT>(expr) &&
|
||||
ctx.arg.shared) {
|
||||
// R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} reference a label. Do not
|
||||
// set NEEDS_TLSDESC on the label.
|
||||
if (expr != R_TLSDESC_CALL) {
|
||||
if (!isRISCV || type == R_RISCV_TLSDESC_HI20)
|
||||
sym.setFlags(NEEDS_TLSDESC);
|
||||
sym.setFlags(NEEDS_TLSDESC);
|
||||
sec->addReloc({expr, type, offset, addend, &sym});
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// RISC-V does not support GD/LD to IE/LE optimizations.
|
||||
// RISC-V supports TLSDESC to IE/LE optimizations.
|
||||
// For PPC64, if the file has missing R_PPC64_TLSGD/R_PPC64_TLSLD, disable
|
||||
// optimization as well.
|
||||
bool execOptimize =
|
||||
!ctx.arg.shared &&
|
||||
!(isRISCV && expr != R_TLSDESC_PC && expr != R_TLSDESC_CALL);
|
||||
bool execOptimize = !ctx.arg.shared;
|
||||
|
||||
// If we are producing an executable and the symbol is non-preemptable, it
|
||||
// must be defined and the code sequence can be optimized to use Local-Exec.
|
||||
//
|
||||
// RISC-V does not support any relaxations for TLS relocations, however, we
|
||||
// can omit the DTPMOD dynamic relocations and resolve them at link time
|
||||
// because them are always 1. This may be necessary for static linking as
|
||||
// DTPMOD may not be expected at load time.
|
||||
// While some targets do not have TLS optimizations, we can omit the
|
||||
// DTPMOD dynamic relocations and resolve them at link time because them
|
||||
// are always 1. This may be necessary for static linking as DTPMOD may
|
||||
// not be expected at load time.
|
||||
bool isLocalInExecutable = !sym.isPreemptible && !ctx.arg.shared;
|
||||
|
||||
// Local Dynamic is for access to module local TLS variables, while still
|
||||
@ -1203,10 +1192,6 @@ unsigned RelocScan::handleTlsRelocation(RelExpr expr, RelType type,
|
||||
|
||||
// Global-Dynamic/TLSDESC can be optimized to Initial-Exec or Local-Exec
|
||||
// depending on the symbol being locally defined or not.
|
||||
//
|
||||
// R_RISCV_TLSDESC_{LOAD_LO12,ADD_LO12_I,CALL} reference a non-preemptible
|
||||
// label, so TLSDESC=>IE will be categorized as R_RELAX_TLS_GD_TO_LE. We fix
|
||||
// the categorization in RISCV::relocateAlloc.
|
||||
if (sym.isPreemptible) {
|
||||
sym.setFlags(NEEDS_TLSIE);
|
||||
sec->addReloc({ctx.target->adjustTlsExpr(type, R_RELAX_TLS_GD_TO_IE),
|
||||
|
||||
@ -64,8 +64,8 @@
|
||||
# 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 --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
|
||||
# UNPAIRED: error: {{.*}}.o:(.alloc+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_ULEB128
|
||||
# UNPAIRED: error: {{.*}}.o:(.debug_rnglists+0x8): R_RISCV_SET_ULEB128 not paired with R_RISCV_SUB_ULEB128
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax overflow.s -o overflow.o
|
||||
# RUN: not ld.lld -shared --threads=1 overflow.o 2>&1 | FileCheck %s --check-prefix=OVERFLOW
|
||||
|
||||
@ -8,12 +8,42 @@
|
||||
TARGET:
|
||||
nop
|
||||
|
||||
.global INVALID_VENDOR
|
||||
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
|
||||
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
|
||||
.reloc 1f, R_RISCV_CUSTOM255, TARGET
|
||||
1:
|
||||
INVALID_VENDOR:
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR+0
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR+0
|
||||
.reloc ., R_RISCV_CUSTOM255, TARGET
|
||||
nop
|
||||
|
||||
# CHECK: error: {{.*}}:(.text+0x4): malformed consecutive R_RISCV_VENDOR relocations
|
||||
# CHECK: error: {{.*}}:(.text+0x4): R_RISCV_VENDOR is not followed by a relocation of code 192 to 255
|
||||
# CHECK: error: {{.*}}:(.text+0x4): unknown vendor-specific relocation (255) in namespace 'INVALID_VENDOR' against symbol 'TARGET'
|
||||
|
||||
## R_RISCV_VENDOR followed by a standard relocation (not in 192-255 range).
|
||||
# CHECK: error: {{.*}}:(.text1+0x0): R_RISCV_VENDOR is not followed by a relocation of code 192 to 255
|
||||
.section .text1,"ax"
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR
|
||||
.reloc ., R_RISCV_32, TARGET
|
||||
nop
|
||||
|
||||
## R_RISCV_VENDOR at end of section (no following relocation).
|
||||
# CHECK: error: {{.*}}:(.text2+0x0): R_RISCV_VENDOR is not followed by a relocation of code 192 to 255
|
||||
.section .text2,"ax"
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR
|
||||
nop
|
||||
|
||||
## Code 192 and 255 are in the valid range and reach the default case.
|
||||
# CHECK: error: {{.*}}:(.text3+0x0): unknown vendor-specific relocation (192) in namespace 'INVALID_VENDOR' against symbol 'TARGET'
|
||||
# CHECK: error: {{.*}}:(.text3+0x0): unknown vendor-specific relocation (255) in namespace 'INVALID_VENDOR' against symbol 'TARGET'
|
||||
.section .text3,"ax"
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR
|
||||
.reloc ., R_RISCV_CUSTOM192, TARGET
|
||||
.reloc ., R_RISCV_VENDOR, INVALID_VENDOR
|
||||
.reloc ., R_RISCV_CUSTOM255, TARGET
|
||||
nop
|
||||
|
||||
## The vendor symbol must be defined. If not, don't bother with a better diagnostic.
|
||||
# CHECK: error: {{.*}}:(.text4+0x0): unknown relocation (255) against symbol TARGET
|
||||
# CHECK: error: undefined symbol: undef
|
||||
.section .text4,"ax"
|
||||
.reloc ., R_RISCV_VENDOR, undef
|
||||
.reloc ., R_RISCV_CUSTOM255, TARGET
|
||||
nop
|
||||
|
||||
32
lld/test/ELF/riscv-vendor-relocations2.test
Normal file
32
lld/test/ELF/riscv-vendor-relocations2.test
Normal file
@ -0,0 +1,32 @@
|
||||
# REQUIRES: riscv
|
||||
## R_RISCV_VENDOR followed by a relocation of code 256 (outside 192-255).
|
||||
# RUN: yaml2obj %s -o %t.o
|
||||
# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
# CHECK: error: {{.*}}:(.text+0x0): R_RISCV_VENDOR is not followed by a relocation of code 192 to 255
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_RISCV
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [SHF_ALLOC, SHF_EXECINSTR]
|
||||
Content: '13000000'
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Info: .text
|
||||
Relocations:
|
||||
- Type: R_RISCV_VENDOR
|
||||
Symbol: vendor
|
||||
- Type: 0x100 # 256, outside 192-255
|
||||
Symbol: foo
|
||||
Symbols:
|
||||
- Name: vendor
|
||||
Section: .text
|
||||
- Name: foo
|
||||
Section: .text
|
||||
Binding: STB_GLOBAL
|
||||
Loading…
x
Reference in New Issue
Block a user