Skip to content

MCAsmBackend::applyFixup: Change Data to indicate the relocated location #151724

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

Closed
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
13 changes: 6 additions & 7 deletions llvm/include/llvm/MC/MCAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,13 @@ class LLVM_ABI MCAsmBackend {
void maybeAddReloc(const MCFragment &, const MCFixup &, const MCValue &,
uint64_t &Value, bool IsResolved);

/// Determine if a relocation is required. In addition,
/// Apply the \p Value for given \p Fixup into the provided data fragment, at
/// the offset specified by the fixup and following the fixup kind as
/// appropriate. Errors (such as an out of range fixup value) should be
/// reported via \p Ctx.
// Determine if a relocation is required. In addition, apply `Value` to the
// `Data` fragment at the specified fixup offset if applicable. `Data` points
// to the first byte of the fixup offset, which may be at the content's end if
// the fixup is zero-sized.
virtual void applyFixup(const MCFragment &, const MCFixup &,
const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsResolved) = 0;
const MCValue &Target, uint8_t *Data, uint64_t Value,
bool IsResolved) = 0;

/// @}

Expand Down
3 changes: 1 addition & 2 deletions llvm/include/llvm/MC/MCAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ class MCAssembler {
/// \param RecordReloc Record relocation if needed.
/// relocation.
bool evaluateFixup(const MCFragment &F, MCFixup &Fixup, MCValue &Target,
uint64_t &Value, bool RecordReloc,
MutableArrayRef<char> Contents) const;
uint64_t &Value, bool RecordReloc, uint8_t *Data) const;

/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
/// (increased in size, in order to hold its value correctly).
Expand Down
35 changes: 19 additions & 16 deletions llvm/lib/MC/MCAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const {

bool MCAssembler::evaluateFixup(const MCFragment &F, MCFixup &Fixup,
MCValue &Target, uint64_t &Value,
bool RecordReloc,
MutableArrayRef<char> Contents) const {
bool RecordReloc, uint8_t *Data) const {
if (RecordReloc)
++stats::Fixups;

Expand Down Expand Up @@ -187,7 +186,7 @@ bool MCAssembler::evaluateFixup(const MCFragment &F, MCFixup &Fixup,

if (IsResolved && mc::isRelocRelocation(Fixup.getKind()))
IsResolved = false;
getBackend().applyFixup(F, Fixup, Target, Contents, Value, IsResolved);
getBackend().applyFixup(F, Fixup, Target, Data, Value, IsResolved);
return true;
}

Expand Down Expand Up @@ -705,21 +704,25 @@ void MCAssembler::layout() {
for (MCFixup &Fixup : F.getFixups()) {
uint64_t FixedValue;
MCValue Target;
assert(mc::isRelocRelocation(Fixup.getKind()) ||
Fixup.getOffset() <= F.getFixedSize());
auto *Data =
reinterpret_cast<uint8_t *>(Contents.data() + Fixup.getOffset());
evaluateFixup(F, Fixup, Target, FixedValue,
/*RecordReloc=*/true, Contents);
/*RecordReloc=*/true, Data);
}
if (F.getVarFixups().size()) {
// In the variable part, fixup offsets are relative to the fixed part's
// start. Extend the variable contents to the left to account for the
// fixed part size.
Contents = MutableArrayRef(F.getParent()->ContentStorage)
.slice(F.VarContentStart - Contents.size(), F.getSize());
for (MCFixup &Fixup : F.getVarFixups()) {
uint64_t FixedValue;
MCValue Target;
evaluateFixup(F, Fixup, Target, FixedValue,
/*RecordReloc=*/true, Contents);
}
// In the variable part, fixup offsets are relative to the fixed part's
// start.
for (MCFixup &Fixup : F.getVarFixups()) {
uint64_t FixedValue;
MCValue Target;
assert(mc::isRelocRelocation(Fixup.getKind()) ||
(Fixup.getOffset() >= F.getFixedSize() &&
Fixup.getOffset() <= F.getSize()));
auto *Data = reinterpret_cast<uint8_t *>(
F.getVarContents().data() + (Fixup.getOffset() - F.getFixedSize()));
evaluateFixup(F, Fixup, Target, FixedValue,
/*RecordReloc=*/true, Data);
}
}
}
Expand Down
23 changes: 11 additions & 12 deletions llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ class AArch64AsmBackend : public MCAsmBackend {
}

void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) override;
uint8_t *Data, uint64_t Value, bool IsResolved) override;

bool fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value) const override;
Expand Down Expand Up @@ -421,9 +420,8 @@ static bool shouldForceRelocation(const MCFixup &Fixup) {
}

void AArch64AsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
if (shouldForceRelocation(Fixup))
IsResolved = false;
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
Expand Down Expand Up @@ -460,8 +458,8 @@ void AArch64AsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
// Shift the value into position.
Value <<= Info.TargetOffset;

unsigned Offset = Fixup.getOffset();
assert(Offset + NumBytes <= F.getSize() && "Invalid fixup offset!");
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");

// Used to point to big endian bytes.
unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind());
Expand All @@ -471,15 +469,16 @@ void AArch64AsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
if (FulleSizeInBytes == 0) {
// Handle as little-endian
for (unsigned i = 0; i != NumBytes; ++i) {
Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
Data[i] |= uint8_t((Value >> (i * 8)) & 0xff);
}
} else {
// Handle as big-endian
assert((Offset + FulleSizeInBytes) <= Data.size() && "Invalid fixup size!");
assert(Fixup.getOffset() + FulleSizeInBytes <= F.getSize() &&
"Invalid fixup size!");
assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!");
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx = FulleSizeInBytes - 1 - i;
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}

Expand All @@ -492,9 +491,9 @@ void AArch64AsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
// If the immediate is negative, generate MOVN else MOVZ.
// (Bit 30 = 0) ==> MOVN, (Bit 30 = 1) ==> MOVZ.
if (SignedValue < 0)
Data[Offset + 3] &= ~(1 << 6);
Data[3] &= ~(1 << 6);
else
Data[Offset + 3] |= (1 << 6);
Data[3] |= (1 << 6);
}
}

Expand Down
14 changes: 6 additions & 8 deletions llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ class AMDGPUAsmBackend : public MCAsmBackend {
AMDGPUAsmBackend(const Target &T) : MCAsmBackend(llvm::endianness::little) {}

void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) override;
uint8_t *Data, uint64_t Value, bool IsResolved) override;
bool fixupNeedsRelaxation(const MCFixup &Fixup,
uint64_t Value) const override;

Expand Down Expand Up @@ -129,9 +128,8 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
}

void AMDGPUAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
if (Target.getSpecifier())
IsResolved = false;
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
Expand All @@ -148,13 +146,13 @@ void AMDGPUAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
Value <<= Info.TargetOffset;

unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
uint32_t Offset = Fixup.getOffset();
assert(Offset + NumBytes <= F.getSize() && "Invalid fixup offset!");
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");

// For each byte of the fragment that the fixup touches, mask in the bits from
// the fixup value.
for (unsigned i = 0; i != NumBytes; ++i)
Data[Offset + i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
Data[i] |= static_cast<uint8_t>((Value >> (i * 8)) & 0xff);
}

std::optional<MCFixupKind>
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,9 +1108,8 @@ std::optional<bool> ARMAsmBackend::evaluateFixup(const MCFragment &F,
}

void ARMAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
if (IsResolved && shouldForceRelocation(Fixup, Target))
IsResolved = false;
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
Expand All @@ -1124,14 +1123,15 @@ void ARMAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
return; // Doesn't change encoding.
const unsigned NumBytes = getFixupKindNumBytes(Kind);

unsigned Offset = Fixup.getOffset();
assert(Offset + NumBytes <= F.getSize() && "Invalid fixup offset!");
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");

// Used to point to big endian bytes.
unsigned FullSizeBytes;
if (Endian == llvm::endianness::big) {
FullSizeBytes = getFixupKindContainerSizeBytes(Kind);
assert((Offset + FullSizeBytes) <= Data.size() && "Invalid fixup size!");
assert(Fixup.getOffset() + FullSizeBytes <= F.getSize() &&
"Invalid fixup size!");
assert(NumBytes <= FullSizeBytes && "Invalid fixup size!");
}

Expand All @@ -1141,7 +1141,7 @@ void ARMAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
for (unsigned i = 0; i != NumBytes; ++i) {
unsigned Idx =
Endian == llvm::endianness::little ? i : (FullSizeBytes - 1 - i);
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
}
}

Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ class ARMAsmBackend : public MCAsmBackend {
std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
uint64_t &) override;
void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) override;
uint8_t *Data, uint64_t Value, bool IsResolved) override;

unsigned getRelaxedOpcode(unsigned Op, const MCSubtargetInfo &STI) const;

Expand Down
11 changes: 5 additions & 6 deletions llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,8 @@ AVRAsmBackend::createObjectTargetWriter() const {
}

void AVRAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
// AVR sets the fixup value to bypass the assembly time overflow with a
// relocation.
if (IsResolved) {
Expand All @@ -397,14 +396,14 @@ void AVRAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
// Shift the value into position.
Value <<= Info.TargetOffset;

unsigned Offset = Fixup.getOffset();
assert(Offset + NumBytes <= F.getSize() && "Invalid fixup offset!");
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");

// For each byte of the fragment that the fixup touches, mask in the
// bits from the fixup value.
for (unsigned i = 0; i < NumBytes; ++i) {
uint8_t mask = (((Value >> (i * 8)) & 0xff));
Data[Offset + i] |= mask;
Data[i] |= mask;
}
}

Expand Down
3 changes: 1 addition & 2 deletions llvm/lib/Target/AVR/MCTargetDesc/AVRAsmBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class AVRAsmBackend : public MCAsmBackend {
createObjectTargetWriter() const override;

void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) override;
uint8_t *Data, uint64_t Value, bool IsResolved) override;

std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
Expand Down
29 changes: 12 additions & 17 deletions llvm/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ class BPFAsmBackend : public MCAsmBackend {
~BPFAsmBackend() override = default;

void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) override;
uint8_t *Data, uint64_t Value, bool IsResolved) override;

std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const override;
Expand Down Expand Up @@ -66,35 +65,32 @@ bool BPFAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
}

void BPFAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
if (Fixup.getKind() == FK_SecRel_8) {
// The Value is 0 for global variables, and the in-section offset
// for static variables. Write to the immediate field of the inst.
assert(Value <= UINT32_MAX);
support::endian::write<uint32_t>(&Data[Fixup.getOffset() + 4],
static_cast<uint32_t>(Value),
support::endian::write<uint32_t>(Data + 4, static_cast<uint32_t>(Value),
Endian);
} else if (Fixup.getKind() == FK_Data_4 && !Fixup.isPCRel()) {
support::endian::write<uint32_t>(&Data[Fixup.getOffset()], Value, Endian);
support::endian::write<uint32_t>(Data, Value, Endian);
} else if (Fixup.getKind() == FK_Data_8) {
support::endian::write<uint64_t>(&Data[Fixup.getOffset()], Value, Endian);
support::endian::write<uint64_t>(Data, Value, Endian);
} else if (Fixup.getKind() == FK_Data_4 && Fixup.isPCRel()) {
Value = (uint32_t)((Value - 8) / 8);
if (Endian == llvm::endianness::little) {
Data[Fixup.getOffset() + 1] = 0x10;
support::endian::write32le(&Data[Fixup.getOffset() + 4], Value);
Data[1] = 0x10;
support::endian::write32le(Data + 4, Value);
} else {
Data[Fixup.getOffset() + 1] = 0x1;
support::endian::write32be(&Data[Fixup.getOffset() + 4], Value);
Data[1] = 0x1;
support::endian::write32be(Data + 4, Value);
}
} else if (Fixup.getKind() == BPF::FK_BPF_PCRel_4) {
// The input Value represents the number of bytes.
Value = (uint32_t)((Value - 8) / 8);
support::endian::write<uint32_t>(&Data[Fixup.getOffset() + 4], Value,
Endian);
support::endian::write<uint32_t>(Data + 4, Value, Endian);
} else {
assert(Fixup.getKind() == FK_Data_2 && Fixup.isPCRel());

Expand All @@ -103,8 +99,7 @@ void BPFAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
report_fatal_error("Branch target out of insn range");

Value = (uint16_t)((Value - 8) / 8);
support::endian::write<uint16_t>(&Data[Fixup.getOffset() + 2], Value,
Endian);
support::endian::write<uint16_t>(Data + 2, Value, Endian);
}
}

Expand Down
19 changes: 9 additions & 10 deletions llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,8 @@ std::optional<bool> CSKYAsmBackend::evaluateFixup(const MCFragment &F,
}

void CSKYAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved) {
const MCValue &Target, uint8_t *Data,
uint64_t Value, bool IsResolved) {
if (IsResolved && shouldForceRelocation(Fixup, Target))
IsResolved = false;
maybeAddReloc(F, Fixup, Target, Value, IsResolved);
Expand All @@ -217,25 +216,25 @@ void CSKYAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
// Shift the value into position.
Value <<= Info.TargetOffset;

unsigned Offset = Fixup.getOffset();
unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;

assert(Offset + NumBytes <= F.getSize() && "Invalid fixup offset!");
assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
"Invalid fixup offset!");

// For each byte of the fragment that the fixup touches, mask in the
// bits from the fixup value.
bool IsLittleEndian = (Endian == llvm::endianness::little);
bool IsInstFixup = (Kind >= FirstTargetFixupKind);

if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {
Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
Data[Offset + 2] |= uint8_t(Value & 0xff);
Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
Data[0] |= uint8_t((Value >> 16) & 0xff);
Data[1] |= uint8_t((Value >> 24) & 0xff);
Data[2] |= uint8_t(Value & 0xff);
Data[3] |= uint8_t((Value >> 8) & 0xff);
} else {
for (unsigned I = 0; I != NumBytes; I++) {
unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
Data[Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
}
}
}
Expand Down
Loading
Loading