Skip to content

Commit a54f144

Browse files
yjndinyy
authored andcommitted
[BOLT][RISCV]fix up GOT Relocation Handling
1 parent a102342 commit a54f144

File tree

4 files changed

+133
-17
lines changed

4 files changed

+133
-17
lines changed

bolt/include/bolt/Core/MCPlusBuilder.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,20 @@ class MCPlusBuilder {
839839
return StringRef();
840840
}
841841

842+
/// Returns the base register used by the instruction.
843+
virtual unsigned getBaseReg(const MCInst &Inst) const{
844+
llvm_unreachable("not implemented");
845+
return 0;
846+
}
847+
848+
/// Matches a pair of instructions that implement a GOT load:
849+
/// an AUIPC (loading the high part of the address)
850+
/// followed by a GOT-loading instruction (loading the low part of the address).
851+
virtual bool matchGotAuipcPair(const MCInst &Inst) const{
852+
llvm_unreachable("not implemented");
853+
return false;
854+
}
855+
842856
/// Interface and basic functionality of a MCInstMatcher. The idea is to make
843857
/// it easy to match one or more MCInsts against a tree-like pattern and
844858
/// extract the fragment operands. Example:

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 88 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ Error BinaryFunction::disassemble() {
14571457
if (BC.isAArch64())
14581458
handleAArch64IndirectCall(Instruction, Offset);
14591459
}
1460-
} else if (BC.isRISCV()) {
1460+
}else if (BC.isRISCV()) {
14611461
// Check if there's a relocation associated with this instruction.
14621462
for (auto Itr = Relocations.lower_bound(Offset),
14631463
ItrE = Relocations.lower_bound(Offset + Size);
@@ -1466,15 +1466,7 @@ Error BinaryFunction::disassemble() {
14661466
MCSymbol *Symbol = Relocation.Symbol;
14671467

14681468
if (Relocation::isInstructionReference(Relocation.Type)) {
1469-
uint64_t RefOffset = Relocation.Value - getAddress();
1470-
LabelsMapType::iterator LI = InstructionLabels.find(RefOffset);
1471-
1472-
if (LI == InstructionLabels.end()) {
1473-
Symbol = BC.Ctx->createNamedTempSymbol();
1474-
InstructionLabels.emplace(RefOffset, Symbol);
1475-
} else {
1476-
Symbol = LI->second;
1477-
}
1469+
continue;
14781470
}
14791471

14801472
uint64_t Addend = Relocation.Addend;
@@ -1484,16 +1476,15 @@ Error BinaryFunction::disassemble() {
14841476
if (Relocation::isGOT(Relocation.Type)) {
14851477
assert(Relocation::isPCRelative(Relocation.Type) &&
14861478
"GOT relocation must be PC-relative on RISC-V");
1487-
Symbol = BC.registerNameAtAddress("__BOLT_got_zero", 0, 0, 0);
1488-
Addend = Relocation.Value + Relocation.Offset + getAddress();
1479+
continue;
14891480
}
14901481
int64_t Value = Relocation.Value;
14911482
const bool Result = BC.MIB->replaceImmWithSymbolRef(
14921483
Instruction, Symbol, Addend, Ctx.get(), Value, Relocation.Type);
14931484
(void)Result;
14941485
assert(Result && "cannot replace immediate with relocation");
14951486
}
1496-
}
1487+
}
14971488

14981489
add_instruction:
14991490
if (getDWARFLineTable()) {
@@ -1514,14 +1505,97 @@ Error BinaryFunction::disassemble() {
15141505

15151506
addInstruction(Offset, std::move(Instruction));
15161507
}
1508+
if(BC.isRISCV()){
1509+
for (auto CurInstrIt = Instructions.begin(); CurInstrIt != Instructions.end(); ++CurInstrIt) {
1510+
uint64_t CurOffset = CurInstrIt->first;
1511+
if (const size_t DataInCodeSize = getSizeOfDataInCodeAt(CurOffset)) continue;
1512+
1513+
if(MIB->isBranch(CurInstrIt->second) || MIB->isCall(CurInstrIt->second)) continue;
1514+
if (MIB->isPseudo(CurInstrIt->second)) continue;
1515+
if (isZeroPaddingAt(CurInstrIt->first)) break;
1516+
1517+
auto NextInstrIt = std::next(CurInstrIt);
1518+
uint64_t NextOffset = (NextInstrIt != Instructions.end()) ? NextInstrIt->first : getSize();
1519+
for (auto Itr = Relocations.lower_bound(CurOffset),
1520+
ItrE = Relocations.lower_bound(NextOffset);
1521+
Itr != ItrE; ++Itr) {
1522+
Relocation &Relocation = Itr->second;
1523+
MCSymbol *Symbol = Relocation.Symbol;
1524+
1525+
if (Relocation::isInstructionReference(Relocation.Type)) {
1526+
uint64_t RefOffset = Relocation.Value - getAddress();
1527+
LabelsMapType::iterator LI = InstructionLabels.find(RefOffset);
1528+
1529+
if (LI == InstructionLabels.end()) {
1530+
Symbol = BC.Ctx->createNamedTempSymbol();
1531+
InstructionLabels.emplace(RefOffset, Symbol);
1532+
} else {
1533+
Symbol = LI->second;
1534+
}
1535+
}
1536+
1537+
uint64_t Addend = Relocation.Addend;
1538+
1539+
// For GOT relocations, create a reference against GOT entry ignoring
1540+
// the relocation symbol.
1541+
if (Relocation::isGOT(Relocation.Type)) {
1542+
assert(Relocation::isPCRelative(Relocation.Type) &&
1543+
"GOT relocation must be PC-relative on RISC-V");
1544+
// For RISC-V, we need to find the next instruction
1545+
// that matches the current instruction's base register.
1546+
auto NextInstrIt = std::next(CurInstrIt);
1547+
unsigned CurReg = BC.MIB->getBaseReg(CurInstrIt->second);
1548+
while (NextInstrIt != Instructions.end()) {
1549+
MCInst &NextInst = NextInstrIt->second;
1550+
unsigned NextReg = BC.MIB->getBaseReg(NextInst);
1551+
// some case there exit extra auipc instruction
1552+
// like auipc+auipc+ld instruction,so we need skip it
1553+
if(CurReg == NextReg && !BC.MIB->matchGotAuipcPair(NextInst)) {
1554+
break;
1555+
}
1556+
if(CurReg == NextReg && BC.MIB->matchGotAuipcPair(NextInst)){
1557+
1558+
int64_t CurImm = 0;
1559+
for (const MCOperand &Op : CurInstrIt->second) {
1560+
if (Op.isImm()) {
1561+
CurImm = Op.getImm();
1562+
break;
1563+
}
1564+
}
1565+
int64_t NextImm = 0;
1566+
for (const MCOperand &Op : NextInstrIt->second) {
1567+
if (Op.isImm()) {
1568+
NextImm = Op.getImm();
1569+
break;
1570+
}
1571+
}
1572+
Relocation.Value = (CurImm << 12) + NextImm;
1573+
break;
1574+
}
1575+
NextInstrIt = std::next(NextInstrIt);
1576+
}
1577+
Symbol = BC.registerNameAtAddress("__BOLT_got_zero", 0, 0, 0);
1578+
Addend = Relocation.Value + Relocation.Offset + getAddress();
1579+
1580+
}else if (!Relocation::isInstructionReference(Relocation.Type)) {
1581+
continue;
1582+
}
1583+
int64_t Value = Relocation.Value;
1584+
const bool Result = BC.MIB->replaceImmWithSymbolRef(
1585+
CurInstrIt->second, Symbol, Addend, Ctx.get(), Value, Relocation.Type);
1586+
(void)Result;
1587+
assert(Result && "cannot replace immediate with relocation");
1588+
1589+
}
1590+
}
1591+
}
15171592

15181593
for (auto [Offset, Label] : InstructionLabels) {
15191594
InstrMapType::iterator II = Instructions.find(Offset);
15201595
assert(II != Instructions.end() && "reference to non-existing instruction");
15211596

15221597
BC.MIB->setInstLabel(II->second, Label);
15231598
}
1524-
15251599
// Reset symbolizer for the disassembler.
15261600
BC.SymbolicDisAsm->setSymbolizer(nullptr);
15271601

bolt/lib/Target/RISCV/RISCVMCPlusBuilder.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,24 @@ class RISCVMCPlusBuilder : public MCPlusBuilder {
339339
}
340340
}
341341

342+
unsigned getBaseReg(const MCInst &Inst) const override{
343+
switch (Inst.getOpcode()) {
344+
default:
345+
return 0;
346+
case RISCV::AUIPC:
347+
return Inst.getOperand(0).getReg();
348+
case RISCV::ADDI:
349+
case RISCV::LD:
350+
return Inst.getOperand(1).getReg();
351+
}
352+
}
353+
354+
bool matchGotAuipcPair(const MCInst &Inst) const override{
355+
return Inst.getOpcode() == RISCV::ADDI ||
356+
Inst.getOpcode() == RISCV::LD ;
357+
}
358+
359+
342360
const MCSymbol *getTargetSymbol(const MCExpr *Expr) const override {
343361
auto *RISCVExpr = dyn_cast<MCSpecifierExpr>(Expr);
344362
if (RISCVExpr && RISCVExpr->getSubExpr())

bolt/test/RISCV/reloc-got.s

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,26 @@
88
d:
99
.dword 0
1010

11+
.globl e
12+
.p2align 3
13+
e:
14+
.dword 0
15+
1116
.text
1217
.globl _start
1318
.p2align 1
1419
// CHECK: Binary Function "_start" after building cfg {
1520
_start:
1621
nop // Here to not make the _start and .Ltmp0 symbols coincide
17-
// CHECK: auipc t0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) # Label: .Ltmp0
18-
// CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp0)(t0)
22+
// CHECK: auipc t0, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) # Label: .Ltmp0
23+
// CHECK: auipc t1, %pcrel_hi(__BOLT_got_zero+{{[0-9]+}}) # Label: .Ltmp1
24+
// CHECK-NEXT: ld t0, %pcrel_lo(.Ltmp0)(t0)
25+
// CHECK-NEXT: ld t1, %pcrel_lo(.Ltmp1)(t1)
1926
1:
2027
auipc t0, %got_pcrel_hi(d)
28+
2:
29+
auipc t1, %got_pcrel_hi(e)
2130
ld t0, %pcrel_lo(1b)(t0)
31+
ld t1, %pcrel_lo(2b)(t1)
2232
ret
23-
.size _start, .-_start
33+
.size _start, .-_start

0 commit comments

Comments
 (0)