Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,24 +803,28 @@ static const Relocation *getLinxPCRelHi20(Ctx &ctx,
hiSec = eh->getParent();
}
if (!hiSec) {
Err(ctx) << loSec->getLocation(loReloc.offset)
<< ": R_LINX_LO12 relocation "
"points to unsupported anchor section '"
<< d->section->name << "' for symbol '" << sym->getName()
<< "'";
return nullptr;
/*
* Final kernel/static links can point the LO12 relocation at a symbol
* that already lives in an output/synthetic section (for example
* .init.data, __param, or linker-defined text/data boundaries). Those
* symbols still commonly have a matching HI20 relocation by symbol in
* the same input section, so do not reject them here just because they
* are no longer modeled as an InputSection.
*/
hiSec = nullptr;
}
if (hiSec) {
anchor = sym->getName().empty() ? "offset 0x" + utohexstr(d->value)
: toStr(ctx, *sym) + "+0x" +
utohexstr(d->value);
if (addend != 0)
Warn(ctx) << loSec->getLocation(loReloc.offset)
<< ": non-zero addend in "
"R_LINX_LO12 relocation to "
<< anchor << " is ignored";
if (const Relocation *hiRel = findLinxPCRelHiByOffset(hiSec, d->value))
return hiRel;
}

anchor = sym->getName().empty() ? "offset 0x" + utohexstr(d->value)
: toStr(ctx, *sym) + "+0x" +
utohexstr(d->value);
if (addend != 0)
Warn(ctx) << loSec->getLocation(loReloc.offset)
<< ": non-zero addend in "
"R_LINX_LO12 relocation to "
<< anchor << " is ignored";
if (const Relocation *hiRel = findLinxPCRelHiByOffset(hiSec, d->value))
return hiRel;
}
}

Expand Down Expand Up @@ -1015,7 +1019,10 @@ uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
}
case RE_LINX_PC_INDIRECT: {
if (const Relocation *hiRel = getLinxPCRelHi20(ctx, this, r))
return getRelocTargetVA(ctx, *hiRel, getVA(hiRel->offset));
// For Linx ADDTPC+ADDI/ADDIW materialization, the HI20 relocation only
// establishes the page-relative anchor. The paired LO12 relocation must
// receive the final symbol VA's low 12 bits, not the HI20 page delta.
return r.sym->getVA(ctx, a);
return 0;
Comment on lines 1021 to 1026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If getLinxPCRelHi20 returns nullptr (which now happens when hiSec is null, as allowed by the changes in getLinxPCRelHi20), the code falls through and returns 0. This silently resolves the relocation to 0 instead of the actual symbol's virtual address (r.sym->getVA(ctx, a)), leading to a silent miscompilation/link error.

Since the LO12 relocation's value only needs the low 12 bits of the target symbol's VA, we should return r.sym->getVA(ctx, a) directly, while still calling getLinxPCRelHi20 for validation and warnings.

    (void)getLinxPCRelHi20(ctx, this, r);
    // For Linx ADDTPC+ADDI/ADDIW materialization, the HI20 relocation only
    // establishes the page-relative anchor. The paired LO12 relocation must
    // receive the final symbol VA's low 12 bits, not the HI20 page delta.
    return r.sym->getVA(ctx, a);

}
case RE_LOONGARCH_PC_INDIRECT: {
Expand Down
9 changes: 7 additions & 2 deletions llvm/lib/Target/LinxISA/AsmParser/LinxISAAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2403,8 +2403,13 @@ bool LinxISAAsmParser::buildMCInstForForm(unsigned FormIndex, const ParsedInst &
if (!require(HasArrow || AllowsExplicitHiddenMemDst,
"expected '->' destination for RegDst"))
return false;
if (!require(!PI.ArrowDests.empty(), "expected destination after '->'"))
return false;
if (PI.ArrowDests.empty()) {
if (!require(AllowsExplicitHiddenMemDst,
"expected destination after '->'"))
return false;
emitFieldImm(0);
continue;
}
if (!require(PI.ArrowDests[0].Code < (1u << Field.bit_width),
"destination register does not fit field width"))
return false;
Expand Down
7 changes: 5 additions & 2 deletions llvm/lib/Target/LinxISA/LinxISAAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ void LinxISAAsmPrinter::emitInstruction(const MachineInstr *MI) {
}

bool Emitted = false;
if (MI->getOpcode() == LinxISA::BSTART_STD_CALL &&
if ((MI->getOpcode() == LinxISA::BSTART_STD_CALL ||
MI->getOpcode() == LinxISA::BSTART_FP_CALL) &&
OutStreamer->hasRawTextSupport()) {
MachineBasicBlock *MBB = const_cast<MachineBasicBlock *>(MI->getParent());
if (MBB) {
Expand All @@ -95,7 +96,9 @@ void LinxISAAsmPrinter::emitInstruction(const MachineInstr *MI) {

SmallString<128> Line;
raw_svector_ostream OS(Line);
OS << "BSTART\tCALL, ";
OS << (MI->getOpcode() == LinxISA::BSTART_FP_CALL
? "BSTART.FP\tCALL, "
: "BSTART\tCALL, ");

if (BStartInst.getNumOperands() >= 1) {
const MCOperand &TargetOp = BStartInst.getOperand(0);
Expand Down
Loading