/// 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.
- virtual void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ virtual void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel,
MCContext &Ctx) const = 0;
/// finishLayout - Finalize a layout, including fragment lowering.
void finishLayout(MCAsmLayout &Layout);
- std::pair<uint64_t, bool> handleFixup(const MCAsmLayout &Layout,
- MCFragment &F, const MCFixup &Fixup);
+ std::tuple<MCValue, uint64_t, bool>
+ handleFixup(const MCAsmLayout &Layout, MCFragment &F, const MCFixup &Fixup);
public:
/// Construct a new assembler instance.
Layout.getSectionAddressSize(Sec));
}
-std::pair<uint64_t, bool> MCAssembler::handleFixup(const MCAsmLayout &Layout,
- MCFragment &F,
- const MCFixup &Fixup) {
+std::tuple<MCValue, uint64_t, bool>
+MCAssembler::handleFixup(const MCAsmLayout &Layout, MCFragment &F,
+ const MCFixup &Fixup) {
// Evaluate the fixup.
MCValue Target;
uint64_t FixedValue;
getWriter().recordRelocation(*this, Layout, &F, Fixup, Target, IsPCRel,
FixedValue);
}
- return std::make_pair(FixedValue, IsPCRel);
+ return std::make_tuple(Target, FixedValue, IsPCRel);
}
void MCAssembler::layout(MCAsmLayout &Layout) {
for (const MCFixup &Fixup : Fixups) {
uint64_t FixedValue;
bool IsPCRel;
- std::tie(FixedValue, IsPCRel) = handleFixup(Layout, Frag, Fixup);
- getBackend().applyFixup(Fixup, Contents, FixedValue, IsPCRel,
- getContext());
+ MCValue Target;
+ std::tie(Target, FixedValue, IsPCRel) =
+ handleFixup(Layout, Frag, Fixup);
+ getBackend().applyFixup(*this, Fixup, Target, Contents, FixedValue,
+ IsPCRel, getContext());
}
}
}
return Infos[Kind - FirstTargetFixupKind];
}
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
bool mayNeedRelaxation(const MCInst &Inst) const override;
}
}
-void AArch64AsmBackend::applyFixup(const MCFixup &Fixup,
+void AArch64AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsPCRel, MCContext &Ctx) const {
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
const MCValue &Target, uint64_t &Value,
bool &IsResolved) override;
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *DF,
Value = adjustFixupValue(Fixup, Value, &Asm.getContext());
}
-void AMDGPUAsmBackend::applyFixup(const MCFixup &Fixup,
+void AMDGPUAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsPCRel, MCContext &Ctx) const {
if (!Value)
return Value;
}
-unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
+ const MCFixup &Fixup,
+ const MCValue &Target, uint64_t Value,
bool IsPCRel, MCContext &Ctx,
bool IsLittleEndian,
bool IsResolved) const {
unsigned Kind = Fixup.getKind();
+
+ // MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT
+ // and .word relocations they put the Thumb bit into the addend if possible.
+ // Other relocation types don't want this bit though (branches couldn't encode
+ // it if it *was* present, and no other relocations exist) and it can
+ // interfere with checking valid expressions.
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ if (A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&A->getSymbol()) &&
+ (Kind == FK_Data_4 || Kind == ARM::fixup_arm_movw_lo16 ||
+ Kind == ARM::fixup_arm_movt_hi16 || Kind == ARM::fixup_t2_movw_lo16 ||
+ Kind == ARM::fixup_t2_movt_hi16))
+ Value |= 1;
+ }
+
switch (Kind) {
default:
Ctx.reportError(Fixup.getLoc(), "bad relocation fixup type");
return swapHalfWords(out, IsLittleEndian);
}
case ARM::fixup_arm_thumb_bl: {
+ // FIXME: We get both thumb1 and thumb2 in here, so we can only check for
+ // the less strict thumb2 value.
+ if (!isInt<26>(Value - 4)) {
+ Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
+ return 0;
+ }
+
// The value doesn't encode the low bit (always zero) and is offset by
// four. The 32-bit immediate value is encoded as
// imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
const MCSymbolRefExpr *A = Target.getSymA();
const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
const unsigned FixupKind = Fixup.getKind() ;
- // MachO (the only user of "Value") tries to make .o files that look vaguely
- // pre-linked, so for MOVW/MOVT and .word relocations they put the Thumb bit
- // into the addend if possible. Other relocation types don't want this bit
- // though (branches couldn't encode it if it *was* present, and no other
- // relocations exist) and it can interfere with checking valid expressions.
- if (FixupKind == FK_Data_4 ||
- FixupKind == ARM::fixup_arm_movw_lo16 ||
- FixupKind == ARM::fixup_arm_movt_hi16 ||
- FixupKind == ARM::fixup_t2_movw_lo16 ||
- FixupKind == ARM::fixup_t2_movt_hi16) {
- if (Sym) {
- if (Asm.isThumbFunc(Sym))
- Value |= 1;
- }
- }
if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) {
assert(Sym && "How did we resolve this?");
// If the symbol is out of range, produce a relocation and hope the
// linker can handle it. GNU AS produces an error in this case.
- if (Sym->isExternal() || Value >= 0x400004)
+ if (Sym->isExternal())
IsResolved = false;
}
// Create relocations for unconditional branches to function symbols with
}
}
-void ARMAsmBackend::applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
- uint64_t Value, bool IsPCRel,
- MCContext &Ctx) const {
+void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data, uint64_t Value,
+ bool IsPCRel, MCContext &Ctx) const {
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
- Value = adjustFixupValue(Fixup, Value, IsPCRel, Ctx, IsLittleEndian, true);
+ Value = adjustFixupValue(Asm, Fixup, Target, Value, IsPCRel, Ctx,
+ IsLittleEndian, true);
if (!Value)
return; // Doesn't change encoding.
const MCValue &Target, uint64_t &Value,
bool &IsResolved) override;
- unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, bool IsPCRel,
+ unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, uint64_t Value, bool IsPCRel,
MCContext &Ctx, bool IsLittleEndian,
bool IsResolved) const;
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
unsigned getRelaxedOpcode(unsigned Op) const;
: MCAsmBackend(), IsLittleEndian(IsLittleEndian) {}
~BPFAsmBackend() override = default;
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
return true;
}
-void BPFAsmBackend::applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
- uint64_t Value, bool IsPCRel,
- MCContext &Ctx) const {
+void BPFAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data, uint64_t Value,
+ bool IsPCRel, MCContext &Ctx) const {
if (Fixup.getKind() == FK_SecRel_4 || Fixup.getKind() == FK_SecRel_8) {
assert(Value == 0);
} else if (Fixup.getKind() == FK_Data_4 || Fixup.getKind() == FK_Data_8) {
/// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
/// data fragment, at the offset specified by the fixup and following the
/// fixup kind as appropriate.
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t FixupValue, bool IsPCRel,
MCContext &Ctx) const override {
LanaiAsmBackend(const Target &T, Triple::OSType OST)
: MCAsmBackend(), OSType(OST) {}
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
return true;
}
-void LanaiAsmBackend::applyFixup(const MCFixup &Fixup,
+void LanaiAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool /*IsPCRel*/, MCContext & /*Ctx*/) const {
MCFixupKind Kind = Fixup.getKind();
/// ApplyFixup - 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.
-void MipsAsmBackend::applyFixup(const MCFixup &Fixup,
+void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsPCRel, MCContext &Ctx) const {
MCFixupKind Kind = Fixup.getKind();
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
return (IsLittleEndian? InfosLE : InfosBE)[Kind - FirstTargetFixupKind];
}
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override {
Value = adjustFixupValue(Fixup.getKind(), Value);
if (!Value) return; // Doesn't change encoding.
: MCAsmBackend(), OSABI(OSABI), Is64Bit(Is64Bit) {}
~RISCVAsmBackend() override {}
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
return true;
}
-void RISCVAsmBackend::applyFixup(const MCFixup &Fixup,
+void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsPCRel, MCContext &Ctx) const {
return;
ELFSparcAsmBackend(const Target &T, Triple::OSType OSType) :
SparcAsmBackend(T), OSType(OSType) { }
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel,
MCContext &Ctx) const override {
return SystemZ::NumTargetFixupKinds;
}
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
bool mayNeedRelaxation(const MCInst &Inst) const override {
return false;
return Infos[Kind - FirstTargetFixupKind];
}
-void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup,
+void SystemZMCAsmBackend::applyFixup(const MCAssembler &Asm,
+ const MCFixup &Fixup,
+ const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsPCRel, MCContext &Ctx) const {
MCFixupKind Kind = Fixup.getKind();
return Infos[Kind - FirstTargetFixupKind];
}
- void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
+ void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target, MutableArrayRef<char> Data,
uint64_t Value, bool IsPCRel, MCContext &Ctx) const override {
unsigned Size = 1 << getFixupKindLog2Size(Fixup.getKind());
-@ RUN: llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o - \
-@ RUN: | llvm-readobj -r | FileCheck %s
+@ RUN: not llvm-mc %s -triple thumbv5-linux-gnueabi -filetype=obj -o /dev/null 2>&1 | FileCheck %s
+ .code 16
bl end
- .space 0x3fffff
+ .space 0x1ffffff
end:
bl end2
- .space 0x3fffff
+ .space 0x1ffffff
.global end2
end2:
bl end3
- .space 0x400000
+ .space 0x2000000
.global end3
end3:
+// CHECK-NOT: error
+// CHECK: [[@LINE+1]]:{{[0-9]}}: error: Relocation out of range
bl end4
- .space 0x400000
+// CHECK-NOT: error
+ .space 0x2000000
end4:
-@ CHECK: 0x400003 R_ARM_THM_CALL end2 0x0
-@ CHECK: 0x800006 R_ARM_THM_CALL end3 0x0
-@ CHECK: 0xC0000A R_ARM_THM_CALL end4 0x0
+start1:
+ .space 0x1fffffc
+ bl start1
+
+ .global start2
+start2:
+ .space 0x1fffffc
+ bl start2
+
+ .global start3
+start3:
+ .space 0x1fffffd
+ bl start3
+
+start4:
+ .space 0x1fffffd
+// CHECK: [[@LINE+1]]:{{[0-9]}}: error: Relocation out of range
+ bl start4