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"
2532
2633using 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+
2848namespace 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 TI = getTargetInfo (
303+ Checker.getTripleFromTargetFlag (Checker.getTargetFlag (Symbol)));
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.\n Instruction 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.\n Instruction 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,101 @@ 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 TI = getTargetInfo (
724+ Checker.getTripleFromTargetFlag (Checker.getTargetFlag (Symbol)));
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>
743+ getTargetInfo (const Triple &TT,
744+ const SubtargetFeatures &TF = SubtargetFeatures()) const {
745+
746+ auto TripleName = TT.str ();
747+ std::string ErrorStr;
748+ const Target *TheTarget =
749+ TargetRegistry::lookupTarget (TripleName, ErrorStr);
750+ if (!TheTarget)
751+ return make_error<StringError>(" Error accessing target '" + TripleName +
752+ " ': " + ErrorStr,
753+ inconvertibleErrorCode ());
754+
755+ std::unique_ptr<MCSubtargetInfo> STI (
756+ TheTarget->createMCSubtargetInfo (TripleName, " " , TF.getString ()));
757+ if (!STI)
758+ return make_error<StringError>(" Unable to create subtarget for " +
759+ TripleName,
760+ inconvertibleErrorCode ());
761+
762+ std::unique_ptr<MCRegisterInfo> MRI (TheTarget->createMCRegInfo (TripleName));
763+ if (!MRI)
764+ return make_error<StringError>(" Unable to create target register info "
765+ " for " +
766+ TripleName,
767+ inconvertibleErrorCode ());
768+
769+ MCTargetOptions MCOptions;
770+ std::unique_ptr<MCAsmInfo> MAI (
771+ TheTarget->createMCAsmInfo (*MRI, TripleName, MCOptions));
772+ if (!MAI)
773+ return make_error<StringError>(" Unable to create target asm info " +
774+ TripleName,
775+ inconvertibleErrorCode ());
776+
777+ auto Ctx = std::make_unique<MCContext>(Triple (TripleName), MAI.get (),
778+ MRI.get (), STI.get ());
779+
780+ std::unique_ptr<MCDisassembler> Disassembler (
781+ TheTarget->createMCDisassembler (*STI, *Ctx));
782+ if (!Disassembler)
783+ return make_error<StringError>(" Unable to create disassembler for " +
784+ TripleName,
785+ inconvertibleErrorCode ());
786+
787+ std::unique_ptr<MCInstrInfo> MII (TheTarget->createMCInstrInfo ());
788+ if (!MII)
789+ return make_error<StringError>(" Unable to create instruction info for" +
790+ TripleName,
791+ inconvertibleErrorCode ());
792+
793+ std::unique_ptr<MCInstPrinter> InstPrinter (TheTarget->createMCInstPrinter (
794+ Triple (TripleName), 0 , *MAI, *MII, *MRI));
795+ if (!InstPrinter)
796+ return make_error<StringError>(
797+ " Unable to create instruction printer for" + TripleName,
798+ inconvertibleErrorCode ());
799+
800+ return TargetInfo ({TheTarget, std::move (STI), std::move (MRI),
801+ std::move (MAI), std::move (Ctx), std::move (Disassembler),
802+ std::move (MII), std::move (InstPrinter)});
803+ }
700804};
701805} // namespace llvm
702806
703807RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl (
704808 IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
705809 GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
706- GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
707- MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
708- raw_ostream &ErrStream)
810+ GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
811+ SubtargetFeatures TF, raw_ostream &ErrStream)
709812 : IsSymbolValid(std::move(IsSymbolValid)),
710813 GetSymbolInfo(std::move(GetSymbolInfo)),
711814 GetSectionInfo(std::move(GetSectionInfo)),
712815 GetStubInfo(std::move(GetStubInfo)), GetGOTInfo(std::move(GetGOTInfo)),
713- Endianness(Endianness), Disassembler(Disassembler ),
714- InstPrinter(InstPrinter), ErrStream(ErrStream) {}
816+ Endianness(Endianness), TT(std::move(TT)), TF(std::move(TF) ),
817+ ErrStream(ErrStream) {}
715818
716819bool RuntimeDyldCheckerImpl::check (StringRef CheckExpr) const {
717820 CheckExpr = CheckExpr.trim ();
@@ -822,6 +925,36 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
822925 return {SymInfo->getContent ().data (), SymInfo->getContent ().size ()};
823926}
824927
928+ TargetFlagsType RuntimeDyldCheckerImpl::getTargetFlag (StringRef Symbol) const {
929+ auto SymInfo = GetSymbolInfo (Symbol);
930+ if (!SymInfo) {
931+ logAllUnhandledErrors (SymInfo.takeError (), errs (), " RTDyldChecker: " );
932+ return TargetFlagsType{};
933+ }
934+ return SymInfo->getTargetFlags ();
935+ }
936+
937+ Triple
938+ RuntimeDyldCheckerImpl::getTripleFromTargetFlag (TargetFlagsType Flag) const {
939+ Triple TheTriple = TT;
940+
941+ switch (TT.getArch ()) {
942+ case Triple::ArchType::arm:
943+ if (~Flag & 0x1 )
944+ return TT;
945+ TheTriple.setArchName ((Twine (" thumb" ) + TT.getArchName ().substr (3 )).str ());
946+ return TheTriple;
947+ case Triple::ArchType::thumb:
948+ if (Flag & 0x1 )
949+ return TT;
950+ TheTriple.setArchName ((Twine (" arm" ) + TT.getArchName ().substr (5 )).str ());
951+ return TheTriple;
952+
953+ default :
954+ return TT;
955+ }
956+ }
957+
825958std::pair<uint64_t , std::string> RuntimeDyldCheckerImpl::getSectionAddr (
826959 StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
827960
@@ -884,13 +1017,12 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
8841017RuntimeDyldChecker::RuntimeDyldChecker (
8851018 IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
8861019 GetSectionInfoFunction GetSectionInfo, GetStubInfoFunction GetStubInfo,
887- GetGOTInfoFunction GetGOTInfo, support::endianness Endianness,
888- MCDisassembler *Disassembler, MCInstPrinter *InstPrinter,
889- raw_ostream &ErrStream)
1020+ GetGOTInfoFunction GetGOTInfo, support::endianness Endianness, Triple TT,
1021+ SubtargetFeatures TF, raw_ostream &ErrStream)
8901022 : Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
8911023 std::move (IsSymbolValid), std::move(GetSymbolInfo),
8921024 std::move(GetSectionInfo), std::move(GetStubInfo),
893- std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter ,
1025+ std::move(GetGOTInfo), Endianness, std::move(TT), std::move(TF) ,
8941026 ErrStream)) {}
8951027
8961028RuntimeDyldChecker::~RuntimeDyldChecker () = default ;
0 commit comments