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 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
+
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,100 @@ 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 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
+
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> 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
+ }
700
803
};
701
804
} // namespace llvm
702
805
703
806
RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl (
704
807
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
705
808
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)
709
811
: IsSymbolValid(std::move(IsSymbolValid)),
710
812
GetSymbolInfo(std::move(GetSymbolInfo)),
711
813
GetSectionInfo(std::move(GetSectionInfo)),
712
814
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) {}
715
817
716
818
bool RuntimeDyldCheckerImpl::check (StringRef CheckExpr) const {
717
819
CheckExpr = CheckExpr.trim ();
@@ -822,6 +924,36 @@ StringRef RuntimeDyldCheckerImpl::getSymbolContent(StringRef Symbol) const {
822
924
return {SymInfo->getContent ().data (), SymInfo->getContent ().size ()};
823
925
}
824
926
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
+
825
957
std::pair<uint64_t , std::string> RuntimeDyldCheckerImpl::getSectionAddr (
826
958
StringRef FileName, StringRef SectionName, bool IsInsideLoad) const {
827
959
@@ -884,14 +1016,13 @@ std::pair<uint64_t, std::string> RuntimeDyldCheckerImpl::getStubOrGOTAddrFor(
884
1016
RuntimeDyldChecker::RuntimeDyldChecker (
885
1017
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,
886
1018
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)
890
1021
: Impl(::std::make_unique<RuntimeDyldCheckerImpl>(
891
1022
std::move (IsSymbolValid), std::move(GetSymbolInfo),
892
1023
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)) {}
895
1026
896
1027
RuntimeDyldChecker::~RuntimeDyldChecker () = default ;
897
1028
0 commit comments