Skip to content

Commit 9c017a9

Browse files
eymaylhames
authored andcommitted
[jitlink][rtdyld][checker] Re-apply 4b17c81 with fixes.
This re-applies 4b17c81, "[jitlink/rtdydl][checker] Add TargetFlag dependent disassembler switching support", which was reverted in 4871a9c due to bot failures. The patch has been updated to add missing plumbing for Subtarget Features and a CPU string, which should fix the failing tests. https://reviews.llvm.org/D158280
1 parent eea232d commit 9c017a9

File tree

15 files changed

+250
-61
lines changed

15 files changed

+250
-61
lines changed

llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,10 +623,8 @@ class Symbol {
623623
this->S = static_cast<uint8_t>(S);
624624
}
625625

626-
/// Check whether the given target flags are set for this Symbol.
627-
bool hasTargetFlags(TargetFlagsType Flags) const {
628-
return static_cast<TargetFlagsType>(TargetFlags) & Flags;
629-
}
626+
/// Get the target flags of this Symbol.
627+
TargetFlagsType getTargetFlags() const { return TargetFlags; }
630628

631629
/// Set the target flags for this Symbol.
632630
void setTargetFlags(TargetFlagsType Flags) {

llvm/include/llvm/ExecutionEngine/JITLink/aarch32.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace llvm {
2323
namespace jitlink {
2424
namespace aarch32 {
2525

26+
/// Check whether the given target flags are set for this Symbol.
27+
bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags);
28+
2629
/// JITLink-internal AArch32 fixup kinds
2730
enum EdgeKind_aarch32 : Edge::Kind {
2831

llvm/include/llvm/ExecutionEngine/RuntimeDyldChecker.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include "llvm/ADT/DenseMap.h"
1313
#include "llvm/ExecutionEngine/JITSymbol.h"
1414
#include "llvm/Support/Endian.h"
15+
#include "llvm/TargetParser/SubtargetFeature.h"
16+
#include "llvm/TargetParser/Triple.h"
1517
#include <optional>
1618

1719
#include <cstdint>
@@ -29,6 +31,9 @@ class RuntimeDyld;
2931
class RuntimeDyldCheckerImpl;
3032
class raw_ostream;
3133

34+
/// Holds target-specific properties for a symbol.
35+
using TargetFlagsType = uint8_t;
36+
3237
/// RuntimeDyld invariant checker for verifying that RuntimeDyld has
3338
/// correctly applied relocations.
3439
///
@@ -78,10 +83,11 @@ class RuntimeDyldChecker {
7883
public:
7984
MemoryRegionInfo() = default;
8085

81-
/// Constructor for symbols/sections with content.
82-
MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress)
86+
/// Constructor for symbols/sections with content and TargetFlag.
87+
MemoryRegionInfo(ArrayRef<char> Content, JITTargetAddress TargetAddress,
88+
TargetFlagsType TargetFlags)
8389
: ContentPtr(Content.data()), Size(Content.size()),
84-
TargetAddress(TargetAddress) {}
90+
TargetAddress(TargetAddress), TargetFlags(TargetFlags) {}
8591

8692
/// Constructor for zero-fill symbols/sections.
8793
MemoryRegionInfo(uint64_t Size, JITTargetAddress TargetAddress)
@@ -127,10 +133,20 @@ class RuntimeDyldChecker {
127133
/// Return the target address for this region.
128134
JITTargetAddress getTargetAddress() const { return TargetAddress; }
129135

136+
/// Get the target flags for this Symbol.
137+
TargetFlagsType getTargetFlags() const { return TargetFlags; }
138+
139+
/// Set the target flags for this Symbol.
140+
void setTargetFlags(TargetFlagsType Flags) {
141+
assert(Flags <= 1 && "Add more bits to store more than one flag");
142+
TargetFlags = Flags;
143+
}
144+
130145
private:
131146
const char *ContentPtr = nullptr;
132147
uint64_t Size = 0;
133148
JITTargetAddress TargetAddress = 0;
149+
TargetFlagsType TargetFlags = 0;
134150
};
135151

136152
using IsSymbolValidFunction = std::function<bool(StringRef Symbol)>;
@@ -148,9 +164,8 @@ class RuntimeDyldChecker {
148164
GetSectionInfoFunction GetSectionInfo,
149165
GetStubInfoFunction GetStubInfo,
150166
GetGOTInfoFunction GetGOTInfo,
151-
support::endianness Endianness,
152-
MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
153-
raw_ostream &ErrStream);
167+
support::endianness Endianness, Triple TT, StringRef CPU,
168+
SubtargetFeatures TF, raw_ostream &ErrStream);
154169
~RuntimeDyldChecker();
155170

156171
/// Check a single expression against the attached RuntimeDyld

llvm/lib/ExecutionEngine/JITLink/aarch32.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ namespace llvm {
2525
namespace jitlink {
2626
namespace aarch32 {
2727

28+
/// Check whether the given target flags are set for this Symbol.
29+
bool hasTargetFlags(Symbol &Sym, TargetFlagsType Flags) {
30+
return static_cast<TargetFlagsType>(Sym.getTargetFlags()) & Flags;
31+
}
32+
2833
/// Encode 22-bit immediate value for branch instructions without J1J2 range
2934
/// extension (formats B T4, BL T1 and BLX T2).
3035
///
@@ -287,7 +292,7 @@ Error applyFixupData(LinkGraph &G, Block &B, const Edge &E) {
287292
int64_t Addend = E.getAddend();
288293
Symbol &TargetSymbol = E.getTarget();
289294
uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
290-
assert(!TargetSymbol.hasTargetFlags(ThumbSymbol));
295+
assert(!hasTargetFlags(TargetSymbol, ThumbSymbol));
291296

292297
// Regular data relocations have size 4, alignment 1 and write the full 32-bit
293298
// result to the place; no need for overflow checking. There are three
@@ -341,14 +346,14 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
341346
int64_t Addend = E.getAddend();
342347
Symbol &TargetSymbol = E.getTarget();
343348
uint64_t TargetAddress = TargetSymbol.getAddress().getValue();
344-
if (TargetSymbol.hasTargetFlags(ThumbSymbol))
349+
if (hasTargetFlags(TargetSymbol, ThumbSymbol))
345350
TargetAddress |= 0x01;
346351

347352
switch (Kind) {
348353
case Thumb_Jump24: {
349354
if (!checkOpcode<Thumb_Jump24>(R))
350355
return makeUnexpectedOpcodeError(G, R, Kind);
351-
if (!(TargetSymbol.hasTargetFlags(ThumbSymbol)))
356+
if (!hasTargetFlags(TargetSymbol, ThumbSymbol))
352357
return make_error<JITLinkError>("Branch relocation needs interworking "
353358
"stub when bridging to ARM: " +
354359
StringRef(G.getEdgeKindName(Kind)));
@@ -375,7 +380,7 @@ Error applyFixupThumb(LinkGraph &G, Block &B, const Edge &E,
375380

376381
// The call instruction itself is Thumb. The call destination can either be
377382
// Thumb or Arm. We use BL to stay in Thumb and BLX to change to Arm.
378-
bool TargetIsArm = !TargetSymbol.hasTargetFlags(ThumbSymbol);
383+
bool TargetIsArm = !hasTargetFlags(TargetSymbol, ThumbSymbol);
379384
bool InstrIsBlx = (R.Lo & FixupInfo<Thumb_Call>::LoBitNoBlx) == 0;
380385
if (TargetIsArm != InstrIsBlx) {
381386
if (LLVM_LIKELY(TargetIsArm)) {

llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
4646
case Triple::armeb:
4747
case Triple::thumb:
4848
case Triple::thumbeb:
49-
if (Sym.hasTargetFlags(aarch32::ThumbSymbol)) {
49+
if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
5050
// Set LSB to indicate thumb target
5151
assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
5252
assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp

Lines changed: 147 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,16 @@
1010
#include "RuntimeDyldCheckerImpl.h"
1111
#include "llvm/ADT/STLExtras.h"
1212
#include "llvm/ADT/StringExtras.h"
13+
#include "llvm/MC/MCAsmInfo.h"
1314
#include "llvm/MC/MCContext.h"
1415
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
1516
#include "llvm/MC/MCInst.h"
17+
#include "llvm/MC/MCInstPrinter.h"
18+
#include "llvm/MC/MCInstrInfo.h"
19+
#include "llvm/MC/MCRegisterInfo.h"
20+
#include "llvm/MC/MCSubtargetInfo.h"
21+
#include "llvm/MC/MCTargetOptions.h"
22+
#include "llvm/MC/TargetRegistry.h"
1623
#include "llvm/Support/Endian.h"
1724
#include "llvm/Support/MSVCErrorWorkarounds.h"
1825
#include "llvm/Support/MemoryBuffer.h"
@@ -25,6 +32,19 @@
2532

2633
using namespace llvm;
2734

35+
namespace {
36+
struct TargetInfo {
37+
const Target *TheTarget;
38+
std::unique_ptr<MCSubtargetInfo> STI;
39+
std::unique_ptr<MCRegisterInfo> MRI;
40+
std::unique_ptr<MCAsmInfo> MAI;
41+
std::unique_ptr<MCContext> Ctx;
42+
std::unique_ptr<MCDisassembler> Disassembler;
43+
std::unique_ptr<MCInstrInfo> MII;
44+
std::unique_ptr<MCInstPrinter> InstPrinter;
45+
};
46+
} // anonymous namespace
47+
2848
namespace llvm {
2949

3050
// Helper class that implements the language evaluated by RuntimeDyldChecker.
@@ -276,6 +296,20 @@ class RuntimeDyldCheckerExprEval {
276296
"");
277297

278298
unsigned OpIdx = OpIdxExpr.getValue();
299+
300+
auto printInst = [this](StringRef Symbol, MCInst Inst,
301+
raw_string_ostream &ErrMsgStream) {
302+
auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
303+
auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
304+
if (auto E = TI.takeError()) {
305+
errs() << "Error obtaining instruction printer: "
306+
<< toString(std::move(E)) << "\n";
307+
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
308+
}
309+
Inst.dump_pretty(ErrMsgStream, TI->InstPrinter.get());
310+
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
311+
};
312+
279313
if (OpIdx >= Inst.getNumOperands()) {
280314
std::string ErrMsg;
281315
raw_string_ostream ErrMsgStream(ErrMsg);
@@ -284,8 +318,8 @@ class RuntimeDyldCheckerExprEval {
284318
<< "'. Instruction has only "
285319
<< format("%i", Inst.getNumOperands())
286320
<< " operands.\nInstruction is:\n ";
287-
Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
288-
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
321+
322+
return printInst(Symbol, Inst, ErrMsgStream);
289323
}
290324

291325
const MCOperand &Op = Inst.getOperand(OpIdx);
@@ -294,9 +328,8 @@ class RuntimeDyldCheckerExprEval {
294328
raw_string_ostream ErrMsgStream(ErrMsg);
295329
ErrMsgStream << "Operand '" << format("%i", OpIdx) << "' of instruction '"
296330
<< Symbol << "' is not an immediate.\nInstruction is:\n ";
297-
Inst.dump_pretty(ErrMsgStream, Checker.InstPrinter);
298331

299-
return std::make_pair(EvalResult(ErrMsgStream.str()), "");
332+
return printInst(Symbol, Inst, ErrMsgStream);
300333
}
301334

302335
return std::make_pair(EvalResult(Op.getImm()), RemainingExpr);
@@ -687,31 +720,100 @@ class RuntimeDyldCheckerExprEval {
687720

688721
bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size,
689722
int64_t Offset) const {
690-
MCDisassembler *Dis = Checker.Disassembler;
723+
auto TT = Checker.getTripleForSymbol(Checker.getTargetFlag(Symbol));
724+
auto TI = getTargetInfo(TT, Checker.getCPU(), Checker.getFeatures());
725+
726+
if (auto E = TI.takeError()) {
727+
errs() << "Error obtaining disassembler: " << toString(std::move(E))
728+
<< "\n";
729+
return false;
730+
}
731+
691732
StringRef SymbolMem = Checker.getSymbolContent(Symbol);
692733
ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin() + Offset,
693734
SymbolMem.size() - Offset);
694735

695736
MCDisassembler::DecodeStatus S =
696-
Dis->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
737+
TI->Disassembler->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
697738

698739
return (S == MCDisassembler::Success);
699740
}
741+
742+
Expected<TargetInfo> getTargetInfo(const Triple &TT, const StringRef &CPU,
743+
const SubtargetFeatures &TF) const {
744+
745+
auto TripleName = TT.str();
746+
std::string ErrorStr;
747+
const Target *TheTarget =
748+
TargetRegistry::lookupTarget(TripleName, ErrorStr);
749+
if (!TheTarget)
750+
return make_error<StringError>("Error accessing target '" + TripleName +
751+
"': " + ErrorStr,
752+
inconvertibleErrorCode());
753+
754+
std::unique_ptr<MCSubtargetInfo> STI(
755+
TheTarget->createMCSubtargetInfo(TripleName, CPU, TF.getString()));
756+
if (!STI)
757+
return make_error<StringError>("Unable to create subtarget for " +
758+
TripleName,
759+
inconvertibleErrorCode());
760+
761+
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
762+
if (!MRI)
763+
return make_error<StringError>("Unable to create target register info "
764+
"for " +
765+
TripleName,
766+
inconvertibleErrorCode());
767+
768+
MCTargetOptions MCOptions;
769+
std::unique_ptr<MCAsmInfo> MAI(
770+
TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
771+
if (!MAI)
772+
return make_error<StringError>("Unable to create target asm info " +
773+
TripleName,
774+
inconvertibleErrorCode());
775+
776+
auto Ctx = std::make_unique<MCContext>(Triple(TripleName), MAI.get(),
777+
MRI.get(), STI.get());
778+
779+
std::unique_ptr<MCDisassembler> Disassembler(
780+
TheTarget->createMCDisassembler(*STI, *Ctx));
781+
if (!Disassembler)
782+
return make_error<StringError>("Unable to create disassembler for " +
783+
TripleName,
784+
inconvertibleErrorCode());
785+
786+
std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
787+
if (!MII)
788+
return make_error<StringError>("Unable to create instruction info for" +
789+
TripleName,
790+
inconvertibleErrorCode());
791+
792+
std::unique_ptr<MCInstPrinter> InstPrinter(TheTarget->createMCInstPrinter(
793+
Triple(TripleName), 0, *MAI, *MII, *MRI));
794+
if (!InstPrinter)
795+
return make_error<StringError>(
796+
"Unable to create instruction printer for" + TripleName,
797+
inconvertibleErrorCode());
798+
799+
return TargetInfo({TheTarget, std::move(STI), std::move(MRI),
800+
std::move(MAI), std::move(Ctx), std::move(Disassembler),
801+
std::move(MII), std::move(InstPrinter)});
802+
}
700803
};
701804
} // namespace llvm
702805

703806
RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(
704807
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
705808
GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
706-
GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
707-
MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
708-
raw_ostream &ErrStream)
809+
GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
810+
StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
709811
: IsSymbolValid(std::move(IsSymbolValid)),
710812
GetSymbolInfo(std::move(GetSymbolInfo)),
711813
GetSectionInfo(std::move(GetSectionInfo)),
712814
GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
713-
Endianness(Endianness), Disassembler(Disassembler),
714-
InstPrinter(InstPrinter), ErrStream(ErrStream) {}
815+
Endianness(Endianness), TT(std::move(TT)), CPU(std::move(CPU)),
816+
TF(std::move(TF)), ErrStream(ErrStream) {}
715817

716818
bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const {
717819
CheckExpr = CheckExpr.trim();
@@ -822,6 +924,36 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
822924
return {SymInfo->getContent().data(), SymInfo->getContent().size()};
823925
}
824926

927+
TargetFlagsType RuntimeDyldCheckerImpl::getTargetFlag(StringRef Symbol) const {
928+
auto SymInfo = GetSymbolInfo(Symbol);
929+
if (!SymInfo) {
930+
logAllUnhandledErrors(SymInfo.takeError(), errs(), "RTDyldChecker: ");
931+
return TargetFlagsType{};
932+
}
933+
return SymInfo->getTargetFlags();
934+
}
935+
936+
Triple
937+
RuntimeDyldCheckerImpl::getTripleForSymbol(TargetFlagsType Flag) const {
938+
Triple TheTriple = TT;
939+
940+
switch (TT.getArch()) {
941+
case Triple::ArchType::arm:
942+
if (~Flag & 0x1)
943+
return TT;
944+
TheTriple.setArchName((Twine("thumb") + TT.getArchName().substr(3)).str());
945+
return TheTriple;
946+
case Triple::ArchType::thumb:
947+
if (Flag & 0x1)
948+
return TT;
949+
TheTriple.setArchName((Twine("arm") + TT.getArchName().substr(5)).str());
950+
return TheTriple;
951+
952+
default:
953+
return TT;
954+
}
955+
}
956+
825957
std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getSectionAddr(
826958
StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
827959

@@ -884,14 +1016,13 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
8841016
RuntimeDyldChecker::RuntimeDyldChecker(
8851017
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
8861018
GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
887-
GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
888-
MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
889-
raw_ostream &ErrStream)
1019+
GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
1020+
StringRef CPU, SubtargetFeatures TF, raw_ostream &ErrStream)
8901021
: Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
8911022
std::move(IsSymbolValid), std::move(GetSymbolInfo),
8921023
std::move(GetSectionInfo), std::move(GetStubInfo),
893-
std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter,
894-
ErrStream)) {}
1024+
std::move(GetGOTInfo), Endianness, std::move(TT), std::move(CPU),
1025+
std::move(TF), ErrStream)) {}
8951026

8961027
RuntimeDyldChecker::~RuntimeDyldChecker() = default;
8971028

0 commit comments

Comments
 (0)