Skip to content

Commit

Permalink
[SOL] fix 64 bit data relocations
Browse files Browse the repository at this point in the history
Relocate FK_Data_8 fixups as R_BPF_64_ABS64. R_BPF_64_64 is used for ldimm64
which only makes sense in .text.

Currently 64 bit values in non-text sections get chopped to 32 bits and shifted
32 bits to the left (that is, the first 8 bytes of a ldimm64 relocation). This
commit fixes it so that 64 bit values get written fully at the intended offset.

For backwards compatibility, the new behaviour is used only if the reloc-abs64
feature is on (required by -mcpu=sbfv2), since rbpf before
solana-labs/rbpf#301 assumes the legacy buggy layout.
  • Loading branch information
alessandrod authored and LucasSte committed Feb 16, 2024
1 parent 928b518 commit cf66620
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 15 deletions.
13 changes: 12 additions & 1 deletion lld/ELF/Arch/BPF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,18 @@ RelExpr BPF::getRelExpr(RelType type, const Symbol &s,
}

RelType BPF::getDynRel(RelType type) const {
return type;
switch (type) {
case R_BPF_64_ABS64:
// R_BPF_64_ABS64 is symbolic like R_BPF_64_64, which is set as our
// symbolicRel in the constructor. Return R_BPF_64_64 here so that if
// the symbol isn't preemptible, we emit a _RELATIVE relocation instead
// and skip emitting the symbol.
//
// See https://github.com/solana-labs/llvm-project/blob/6b6aef5dbacef31a3c7b3a54f7f1ba54cafc7077/lld/ELF/Relocations.cpp#L1179
return R_BPF_64_64;
default:
return type;
}
}

int64_t BPF::getImplicitAddend(const uint8_t *buf, RelType type) const {
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/BPF/BPF.td
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ def FeatureDynamicFrames : SubtargetFeature<"dynamic-frames", "HasDynamicFrames"
def FeatureSdiv : SubtargetFeature<"sdiv", "HasSdiv", "true",
"Enable native BPF_SDIV support">;

def FeatureRelocAbs64 : SubtargetFeature<"reloc-abs64", "UseRelocAbs64", "true",
"Fix 64bit data relocations">;

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

Expand All @@ -40,7 +43,7 @@ def : Proc<"v1", []>;
def : Proc<"v2", []>;
def : Proc<"v3", []>;
def : Proc<"probe", []>;
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames, FeatureSdiv]>;
def : Proc<"sbfv2", [FeatureSolana, FeatureDynamicFrames, FeatureSdiv, FeatureRelocAbs64]>;

def BPFInstPrinter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/BPF/BPFSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
// whether we should use fixed or dynamic frames
bool HasDynamicFrames;

// Fixme
bool UseRelocAbs64;

// whether the cpu supports native BPF_SDIV
bool HasSdiv;

Expand Down
10 changes: 6 additions & 4 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ namespace {
class BPFAsmBackend : public MCAsmBackend {
public:
BPFAsmBackend(support::endianness Endian, const MCSubtargetInfo &STI)
: MCAsmBackend(Endian),
isSolana(STI.hasFeature(BPF::FeatureSolana) ||
STI.getTargetTriple().getArch() == Triple::sbf) {}
: MCAsmBackend(Endian),
isSolana(STI.hasFeature(BPF::FeatureSolana) ||
STI.getTargetTriple().getArch() == Triple::sbf),
relocAbs64(STI.hasFeature(BPF::FeatureRelocAbs64)) {}
~BPFAsmBackend() override = default;

void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
Expand All @@ -50,6 +51,7 @@ class BPFAsmBackend : public MCAsmBackend {
const MCSubtargetInfo *STI) const override;
private:
bool isSolana;
bool relocAbs64;
};

} // end anonymous namespace
Expand Down Expand Up @@ -105,7 +107,7 @@ void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,

std::unique_ptr<MCObjectTargetWriter>
BPFAsmBackend::createObjectTargetWriter() const {
return createBPFELFObjectWriter(0, isSolana);
return createBPFELFObjectWriter(0, isSolana, relocAbs64);
}

MCAsmBackend *llvm::createBPFAsmBackend(const Target &T,
Expand Down
14 changes: 8 additions & 6 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace {

class BPFELFObjectWriter : public MCELFObjectTargetWriter {
public:
BPFELFObjectWriter(uint8_t OSABI, bool isSolana);
BPFELFObjectWriter(uint8_t OSABI, bool isSolana, bool relocAbs64);
~BPFELFObjectWriter() override = default;

protected:
Expand All @@ -32,6 +32,7 @@ class BPFELFObjectWriter : public MCELFObjectTargetWriter {
unsigned Type) const override;
private:
bool isSolana;
bool relocAbs64;
};

} // end anonymous namespace
Expand All @@ -45,10 +46,11 @@ bool BPFELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
return isSolana;
}

BPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI, bool isSolana)
BPFELFObjectWriter::BPFELFObjectWriter(uint8_t OSABI, bool isSolana,
bool relocAbs64)
: MCELFObjectTargetWriter(/*Is64Bit*/ true, OSABI, ELF::EM_BPF,
/*HasRelocationAddend*/ false),
isSolana(isSolana) {}
isSolana(isSolana), relocAbs64(relocAbs64) {}

unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
const MCFixup &Fixup,
Expand All @@ -64,7 +66,7 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
// CALL instruction.
return ELF::R_BPF_64_32;
case FK_Data_8:
return isSolana ? ELF::R_BPF_64_64 : ELF::R_BPF_64_ABS64;
return (isSolana && !relocAbs64) ? ELF::R_BPF_64_64 : ELF::R_BPF_64_ABS64;
case FK_Data_4:
if (const MCSymbolRefExpr *A = Target.getSymA()) {
const MCSymbol &Sym = A->getSymbol();
Expand Down Expand Up @@ -102,6 +104,6 @@ unsigned BPFELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}

std::unique_ptr<MCObjectTargetWriter>
llvm::createBPFELFObjectWriter(uint8_t OSABI, bool isSolana) {
return std::make_unique<BPFELFObjectWriter>(OSABI, isSolana);
llvm::createBPFELFObjectWriter(uint8_t OSABI, bool isSolana, bool useRelocAbs64) {
return std::make_unique<BPFELFObjectWriter>(OSABI, isSolana, useRelocAbs64);
}
6 changes: 3 additions & 3 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ MCAsmBackend *createBPFbeAsmBackend(const Target &T, const MCSubtargetInfo &STI,
const MCRegisterInfo &MRI,
const MCTargetOptions &Options);

std::unique_ptr<MCObjectTargetWriter> createBPFELFObjectWriter(uint8_t OSABI,
bool isSolana);
}
std::unique_ptr<MCObjectTargetWriter>
createBPFELFObjectWriter(uint8_t OSABI, bool isSolana, bool useRelocAbs64);
} // namespace llvm

// Defines symbolic names for BPF registers. This defines a mapping from
// register name to register number.
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/BPF/reloc-abs64-sbf.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; RUN: llc -march=sbf -filetype=obj < %s | llvm-objdump -r - | tee -i /tmp/foo | FileCheck --check-prefix=CHECK-RELOC-SBF %s
; RUN: llc -march=sbf -mcpu=sbfv2 -filetype=obj < %s | llvm-objdump -r - | tee -i /tmp/foo | FileCheck --check-prefix=CHECK-RELOC-SBFv2 %s

@.str = private unnamed_addr constant [25 x i8] c"reloc_64_relative_data.c\00", align 1
@FILE = dso_local constant i64 ptrtoint ([25 x i8]* @.str to i64), align 8

; Function Attrs: noinline nounwind optnone
define dso_local i64 @entrypoint(i8* %input) #0 {
entry:
%input.addr = alloca i8*, align 8
store i8* %input, i8** %input.addr, align 8
%0 = load volatile i64, i64* @FILE, align 8
ret i64 %0
}

; CHECK-RELOC-SBF: RELOCATION RECORDS FOR [.data.rel.ro]:
; CHECK-RELOC-SBF: 0000000000000000 R_BPF_64_64 .L.str

; CHECK-RELOC-SBFv2: RELOCATION RECORDS FOR [.data.rel.ro]:
; CHECK-RELOC-SBFv2: 0000000000000000 R_BPF_64_ABS64 .L.str

0 comments on commit cf66620

Please sign in to comment.