10
10
#include " RuntimeDyldCheckerImpl.h"
11
11
#include " llvm/ADT/STLExtras.h"
12
12
#include " llvm/ADT/StringExtras.h"
13
+ #include " llvm/MC/MCAsmInfo.h"
13
14
#include " llvm/MC/MCContext.h"
14
15
#include " llvm/MC/MCDisassembler/MCDisassembler.h"
15
16
#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"
16
23
#include " llvm/Support/Endian.h"
17
24
#include " llvm/Support/MSVCErrorWorkarounds.h"
18
25
#include " llvm/Support/MemoryBuffer.h"
25
32
26
33
using namespace llvm ;
27
34
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
+
28
48
namespace llvm {
29
49
30
50
// Helper class that implements the language evaluated by RuntimeDyldChecker.
@@ -276,6 +296,20 @@ class RuntimeDyldCheckerExprEval {
276
296
" " );
277
297
278
298
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
+
279
313
if (OpIdx >= Inst.getNumOperands ()) {
280
314
std::string ErrMsg;
281
315
raw_string_ostream ErrMsgStream (ErrMsg);
@@ -284,8 +318,8 @@ class RuntimeDyldCheckerExprEval {
284
318
<< " '. Instruction has only "
285
319
<< format (" %i" , Inst.getNumOperands ())
286
320
<< " 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 );
289
323
}
290
324
291
325
const MCOperand &Op = Inst.getOperand (OpIdx);
@@ -294,9 +328,8 @@ class RuntimeDyldCheckerExprEval {
294
328
raw_string_ostream ErrMsgStream (ErrMsg);
295
329
ErrMsgStream << " Operand '" << format (" %i" , OpIdx) << " ' of instruction '"
296
330
<< Symbol << " ' is not an immediate.\n Instruction is:\n " ;
297
- Inst.dump_pretty (ErrMsgStream, Checker.InstPrinter );
298
331
299
- return std::make_pair ( EvalResult (ErrMsgStream. str ()), " " );
332
+ return printInst (Symbol, Inst, ErrMsgStream );
300
333
}
301
334
302
335
return std::make_pair (EvalResult (Op.getImm ()), RemainingExpr);
@@ -687,31 +720,101 @@ class RuntimeDyldCheckerExprEval {
687
720
688
721
bool decodeInst (StringRef Symbol, MCInst &Inst, uint64_t &Size ,
689
722
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
+
691
732
StringRef SymbolMem = Checker.getSymbolContent (Symbol);
692
733
ArrayRef<uint8_t > SymbolBytes (SymbolMem.bytes_begin () + Offset,
693
734
SymbolMem.size () - Offset);
694
735
695
736
MCDisassembler::DecodeStatus S =
696
- Dis ->getInstruction (Inst, Size , SymbolBytes, 0 , nulls ());
737
+ TI-> Disassembler ->getInstruction (Inst, Size , SymbolBytes, 0 , nulls ());
697
738
698
739
return (S == MCDisassembler::Success);
699
740
}
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
+ }
700
804
};
701
805
} // namespace llvm
702
806
703
807
RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl (
704
808
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
705
809
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)
709
812
: IsSymbolValid(std::move(IsSymbolValid)),
710
813
GetSymbolInfo(std::move(GetSymbolInfo)),
711
814
GetSectionInfo(std::move(GetSectionInfo)),
712
815
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) {}
715
818
716
819
bool RuntimeDyldCheckerImpl::check (StringRef CheckExpr) const {
717
820
CheckExpr = CheckExpr.trim ();
@@ -822,6 +925,36 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
822
925
return {SymInfo->getContent ().data (), SymInfo->getContent ().size ()};
823
926
}
824
927
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
+
825
958
std::pair<uint64_t , std::string> RuntimeDyldCheckerImpl::getSectionAddr (
826
959
StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
827
960
@@ -884,13 +1017,12 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
884
1017
RuntimeDyldChecker::RuntimeDyldChecker (
885
1018
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
886
1019
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)
890
1022
: Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
891
1023
std::move (IsSymbolValid), std::move(GetSymbolInfo),
892
1024
std::move(GetSectionInfo), std::move(GetStubInfo),
893
- std::move(GetGOTInfo), Endianness, Disassembler, InstPrinter ,
1025
+ std::move(GetGOTInfo), Endianness, std::move(TT), std::move(TF) ,
894
1026
ErrStream)) {}
895
1027
896
1028
RuntimeDyldChecker::~RuntimeDyldChecker () = default ;
0 commit comments