19f2f44ceSEd Maste //===-- IRDynamicChecks.cpp -------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "llvm/IR/Constants.h"
1112b93ac6SEd Maste #include "llvm/IR/DataLayout.h"
12ac7ddfbfSEd Maste #include "llvm/IR/Function.h"
13ac7ddfbfSEd Maste #include "llvm/IR/Instructions.h"
14ac7ddfbfSEd Maste #include "llvm/IR/Module.h"
15ac7ddfbfSEd Maste #include "llvm/IR/Value.h"
16435933ddSDimitry Andric #include "llvm/Support/raw_ostream.h"
17ac7ddfbfSEd Maste 
189f2f44ceSEd Maste #include "lldb/Expression/IRDynamicChecks.h"
199f2f44ceSEd Maste 
209f2f44ceSEd Maste #include "lldb/Expression/UtilityFunction.h"
219f2f44ceSEd Maste #include "lldb/Target/ExecutionContext.h"
229f2f44ceSEd Maste #include "lldb/Target/ObjCLanguageRuntime.h"
239f2f44ceSEd Maste #include "lldb/Target/Process.h"
249f2f44ceSEd Maste #include "lldb/Target/StackFrame.h"
259f2f44ceSEd Maste #include "lldb/Target/Target.h"
26f678e45dSDimitry Andric #include "lldb/Utility/ConstString.h"
27f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
289f2f44ceSEd Maste 
29ac7ddfbfSEd Maste using namespace llvm;
30ac7ddfbfSEd Maste using namespace lldb_private;
31ac7ddfbfSEd Maste 
32ac7ddfbfSEd Maste static char ID;
33ac7ddfbfSEd Maste 
34a8bcc4d8SDimitry Andric #define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
35ac7ddfbfSEd Maste #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
36ac7ddfbfSEd Maste 
37ac7ddfbfSEd Maste static const char g_valid_pointer_check_text[] =
38ac7ddfbfSEd Maste     "extern \"C\" void\n"
39a8bcc4d8SDimitry Andric     "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
40ac7ddfbfSEd Maste     "{\n"
41ac7ddfbfSEd Maste     "    unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
42ac7ddfbfSEd Maste     "}";
43ac7ddfbfSEd Maste 
449f2f44ceSEd Maste DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
45ac7ddfbfSEd Maste 
469f2f44ceSEd Maste DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
47ac7ddfbfSEd Maste 
Install(DiagnosticManager & diagnostic_manager,ExecutionContext & exe_ctx)48435933ddSDimitry Andric bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
49435933ddSDimitry Andric                                       ExecutionContext &exe_ctx) {
505517e702SDimitry Andric   Status error;
51435933ddSDimitry Andric   m_valid_pointer_check.reset(
52435933ddSDimitry Andric       exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
53435933ddSDimitry Andric           g_valid_pointer_check_text, lldb::eLanguageTypeC,
54435933ddSDimitry Andric           VALID_POINTER_CHECK_NAME, error));
559f2f44ceSEd Maste   if (error.Fail())
569f2f44ceSEd Maste     return false;
579f2f44ceSEd Maste 
584bb0738eSEd Maste   if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
59ac7ddfbfSEd Maste     return false;
60ac7ddfbfSEd Maste 
61ac7ddfbfSEd Maste   Process *process = exe_ctx.GetProcessPtr();
62ac7ddfbfSEd Maste 
63435933ddSDimitry Andric   if (process) {
64435933ddSDimitry Andric     ObjCLanguageRuntime *objc_language_runtime =
65435933ddSDimitry Andric         process->GetObjCLanguageRuntime();
66ac7ddfbfSEd Maste 
67435933ddSDimitry Andric     if (objc_language_runtime) {
68435933ddSDimitry Andric       m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(
69435933ddSDimitry Andric           VALID_OBJC_OBJECT_CHECK_NAME));
70ac7ddfbfSEd Maste 
714bb0738eSEd Maste       if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
72ac7ddfbfSEd Maste         return false;
73ac7ddfbfSEd Maste     }
74ac7ddfbfSEd Maste   }
75ac7ddfbfSEd Maste 
76ac7ddfbfSEd Maste   return true;
77ac7ddfbfSEd Maste }
78ac7ddfbfSEd Maste 
DoCheckersExplainStop(lldb::addr_t addr,Stream & message)79435933ddSDimitry Andric bool DynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
80435933ddSDimitry Andric                                                     Stream &message) {
81435933ddSDimitry Andric   // FIXME: We have to get the checkers to know why they scotched the call in
82435933ddSDimitry Andric   // more detail,
83ac7ddfbfSEd Maste   // so we can print a better message here.
84435933ddSDimitry Andric   if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
85ac7ddfbfSEd Maste     message.Printf("Attempted to dereference an invalid pointer.");
86ac7ddfbfSEd Maste     return true;
87435933ddSDimitry Andric   } else if (m_objc_object_check &&
88435933ddSDimitry Andric              m_objc_object_check->ContainsAddress(addr)) {
89435933ddSDimitry Andric     message.Printf("Attempted to dereference an invalid ObjC Object or send it "
90435933ddSDimitry Andric                    "an unrecognized selector");
91ac7ddfbfSEd Maste     return true;
92ac7ddfbfSEd Maste   }
93ac7ddfbfSEd Maste   return false;
94ac7ddfbfSEd Maste }
95ac7ddfbfSEd Maste 
PrintValue(llvm::Value * V,bool truncate=false)96435933ddSDimitry Andric static std::string PrintValue(llvm::Value *V, bool truncate = false) {
97ac7ddfbfSEd Maste   std::string s;
98ac7ddfbfSEd Maste   raw_string_ostream rso(s);
99ac7ddfbfSEd Maste   V->print(rso);
100ac7ddfbfSEd Maste   rso.flush();
101ac7ddfbfSEd Maste   if (truncate)
102ac7ddfbfSEd Maste     s.resize(s.length() - 1);
103ac7ddfbfSEd Maste   return s;
104ac7ddfbfSEd Maste }
105ac7ddfbfSEd Maste 
106ac7ddfbfSEd Maste //----------------------------------------------------------------------
107ac7ddfbfSEd Maste /// @class Instrumenter IRDynamicChecks.cpp
108*4ba319b5SDimitry Andric /// Finds and instruments individual LLVM IR instructions
109ac7ddfbfSEd Maste ///
110*4ba319b5SDimitry Andric /// When instrumenting LLVM IR, it is frequently desirable to first search for
111*4ba319b5SDimitry Andric /// instructions, and then later modify them.  This way iterators remain
112*4ba319b5SDimitry Andric /// intact, and multiple passes can look at the same code base without
113ac7ddfbfSEd Maste /// treading on each other's toes.
114ac7ddfbfSEd Maste ///
115ac7ddfbfSEd Maste /// The Instrumenter class implements this functionality.  A client first
116*4ba319b5SDimitry Andric /// calls Inspect on a function, which populates a list of instructions to be
117*4ba319b5SDimitry Andric /// instrumented.  Then, later, when all passes' Inspect functions have been
118*4ba319b5SDimitry Andric /// called, the client calls Instrument, which adds the desired
119ac7ddfbfSEd Maste /// instrumentation.
120ac7ddfbfSEd Maste ///
121ac7ddfbfSEd Maste /// A subclass of Instrumenter must override InstrumentInstruction, which
122ac7ddfbfSEd Maste /// is responsible for adding whatever instrumentation is necessary.
123ac7ddfbfSEd Maste ///
124ac7ddfbfSEd Maste /// A subclass of Instrumenter may override:
125ac7ddfbfSEd Maste ///
126ac7ddfbfSEd Maste /// - InspectInstruction [default: does nothing]
127ac7ddfbfSEd Maste ///
128ac7ddfbfSEd Maste /// - InspectBasicBlock [default: iterates through the instructions in a
129ac7ddfbfSEd Maste ///   basic block calling InspectInstruction]
130ac7ddfbfSEd Maste ///
131ac7ddfbfSEd Maste /// - InspectFunction [default: iterates through the basic blocks in a
132ac7ddfbfSEd Maste ///   function calling InspectBasicBlock]
133ac7ddfbfSEd Maste //----------------------------------------------------------------------
134ac7ddfbfSEd Maste class Instrumenter {
135ac7ddfbfSEd Maste public:
136ac7ddfbfSEd Maste   //------------------------------------------------------------------
137ac7ddfbfSEd Maste   /// Constructor
138ac7ddfbfSEd Maste   ///
139ac7ddfbfSEd Maste   /// @param[in] module
140ac7ddfbfSEd Maste   ///     The module being instrumented.
141ac7ddfbfSEd Maste   //------------------------------------------------------------------
Instrumenter(llvm::Module & module,DynamicCheckerFunctions & checker_functions)142435933ddSDimitry Andric   Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
143435933ddSDimitry Andric       : m_module(module), m_checker_functions(checker_functions),
144435933ddSDimitry Andric         m_i8ptr_ty(nullptr), m_intptr_ty(nullptr) {}
145ac7ddfbfSEd Maste 
1469f2f44ceSEd Maste   virtual ~Instrumenter() = default;
147ac7ddfbfSEd Maste 
148ac7ddfbfSEd Maste   //------------------------------------------------------------------
149ac7ddfbfSEd Maste   /// Inspect a function to find instructions to instrument
150ac7ddfbfSEd Maste   ///
151ac7ddfbfSEd Maste   /// @param[in] function
152ac7ddfbfSEd Maste   ///     The function to inspect.
153ac7ddfbfSEd Maste   ///
154ac7ddfbfSEd Maste   /// @return
155ac7ddfbfSEd Maste   ///     True on success; false on error.
156ac7ddfbfSEd Maste   //------------------------------------------------------------------
Inspect(llvm::Function & function)157435933ddSDimitry Andric   bool Inspect(llvm::Function &function) { return InspectFunction(function); }
158ac7ddfbfSEd Maste 
159ac7ddfbfSEd Maste   //------------------------------------------------------------------
160ac7ddfbfSEd Maste   /// Instrument all the instructions found by Inspect()
161ac7ddfbfSEd Maste   ///
162ac7ddfbfSEd Maste   /// @return
163ac7ddfbfSEd Maste   ///     True on success; false on error.
164ac7ddfbfSEd Maste   //------------------------------------------------------------------
Instrument()165435933ddSDimitry Andric   bool Instrument() {
166435933ddSDimitry Andric     for (InstIterator ii = m_to_instrument.begin(),
167435933ddSDimitry Andric                       last_ii = m_to_instrument.end();
168435933ddSDimitry Andric          ii != last_ii; ++ii) {
169ac7ddfbfSEd Maste       if (!InstrumentInstruction(*ii))
170ac7ddfbfSEd Maste         return false;
171ac7ddfbfSEd Maste     }
172ac7ddfbfSEd Maste 
173ac7ddfbfSEd Maste     return true;
174ac7ddfbfSEd Maste   }
1759f2f44ceSEd Maste 
176ac7ddfbfSEd Maste protected:
177ac7ddfbfSEd Maste   //------------------------------------------------------------------
178ac7ddfbfSEd Maste   /// Add instrumentation to a single instruction
179ac7ddfbfSEd Maste   ///
180ac7ddfbfSEd Maste   /// @param[in] inst
181ac7ddfbfSEd Maste   ///     The instruction to be instrumented.
182ac7ddfbfSEd Maste   ///
183ac7ddfbfSEd Maste   /// @return
184ac7ddfbfSEd Maste   ///     True on success; false otherwise.
185ac7ddfbfSEd Maste   //------------------------------------------------------------------
186ac7ddfbfSEd Maste   virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
187ac7ddfbfSEd Maste 
188ac7ddfbfSEd Maste   //------------------------------------------------------------------
189ac7ddfbfSEd Maste   /// Register a single instruction to be instrumented
190ac7ddfbfSEd Maste   ///
191ac7ddfbfSEd Maste   /// @param[in] inst
192ac7ddfbfSEd Maste   ///     The instruction to be instrumented.
193ac7ddfbfSEd Maste   //------------------------------------------------------------------
RegisterInstruction(llvm::Instruction & i)194435933ddSDimitry Andric   void RegisterInstruction(llvm::Instruction &i) {
195ac7ddfbfSEd Maste     m_to_instrument.push_back(&i);
196ac7ddfbfSEd Maste   }
197ac7ddfbfSEd Maste 
198ac7ddfbfSEd Maste   //------------------------------------------------------------------
199*4ba319b5SDimitry Andric   /// Determine whether a single instruction is interesting to instrument,
200*4ba319b5SDimitry Andric   /// and, if so, call RegisterInstruction
201ac7ddfbfSEd Maste   ///
202ac7ddfbfSEd Maste   /// @param[in] i
203ac7ddfbfSEd Maste   ///     The instruction to be inspected.
204ac7ddfbfSEd Maste   ///
205ac7ddfbfSEd Maste   /// @return
206ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
207ac7ddfbfSEd Maste   //------------------------------------------------------------------
InspectInstruction(llvm::Instruction & i)208435933ddSDimitry Andric   virtual bool InspectInstruction(llvm::Instruction &i) { return true; }
209ac7ddfbfSEd Maste 
210ac7ddfbfSEd Maste   //------------------------------------------------------------------
211ac7ddfbfSEd Maste   /// Scan a basic block to see if any instructions are interesting
212ac7ddfbfSEd Maste   ///
213ac7ddfbfSEd Maste   /// @param[in] bb
214ac7ddfbfSEd Maste   ///     The basic block to be inspected.
215ac7ddfbfSEd Maste   ///
216ac7ddfbfSEd Maste   /// @return
217ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
218ac7ddfbfSEd Maste   //------------------------------------------------------------------
InspectBasicBlock(llvm::BasicBlock & bb)219435933ddSDimitry Andric   virtual bool InspectBasicBlock(llvm::BasicBlock &bb) {
220ac7ddfbfSEd Maste     for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
221435933ddSDimitry Andric          ii != last_ii; ++ii) {
222ac7ddfbfSEd Maste       if (!InspectInstruction(*ii))
223ac7ddfbfSEd Maste         return false;
224ac7ddfbfSEd Maste     }
225ac7ddfbfSEd Maste 
226ac7ddfbfSEd Maste     return true;
227ac7ddfbfSEd Maste   }
228ac7ddfbfSEd Maste 
229ac7ddfbfSEd Maste   //------------------------------------------------------------------
230ac7ddfbfSEd Maste   /// Scan a function to see if any instructions are interesting
231ac7ddfbfSEd Maste   ///
232ac7ddfbfSEd Maste   /// @param[in] f
233ac7ddfbfSEd Maste   ///     The function to be inspected.
234ac7ddfbfSEd Maste   ///
235ac7ddfbfSEd Maste   /// @return
236ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
237ac7ddfbfSEd Maste   //------------------------------------------------------------------
InspectFunction(llvm::Function & f)238435933ddSDimitry Andric   virtual bool InspectFunction(llvm::Function &f) {
239ac7ddfbfSEd Maste     for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
240435933ddSDimitry Andric          bbi != last_bbi; ++bbi) {
241ac7ddfbfSEd Maste       if (!InspectBasicBlock(*bbi))
242ac7ddfbfSEd Maste         return false;
243ac7ddfbfSEd Maste     }
244ac7ddfbfSEd Maste 
245ac7ddfbfSEd Maste     return true;
246ac7ddfbfSEd Maste   }
247ac7ddfbfSEd Maste 
248ac7ddfbfSEd Maste   //------------------------------------------------------------------
249*4ba319b5SDimitry Andric   /// Build a function pointer for a function with signature void
250*4ba319b5SDimitry Andric   /// (*)(uint8_t*) with a given address
251ac7ddfbfSEd Maste   ///
252ac7ddfbfSEd Maste   /// @param[in] start_address
253ac7ddfbfSEd Maste   ///     The address of the function.
254ac7ddfbfSEd Maste   ///
255ac7ddfbfSEd Maste   /// @return
256ac7ddfbfSEd Maste   ///     The function pointer, for use in a CallInst.
257ac7ddfbfSEd Maste   //------------------------------------------------------------------
BuildPointerValidatorFunc(lldb::addr_t start_address)258435933ddSDimitry Andric   llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) {
259ac7ddfbfSEd Maste     llvm::Type *param_array[1];
260ac7ddfbfSEd Maste 
261ac7ddfbfSEd Maste     param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
262ac7ddfbfSEd Maste 
263ac7ddfbfSEd Maste     ArrayRef<llvm::Type *> params(param_array, 1);
264ac7ddfbfSEd Maste 
265435933ddSDimitry Andric     FunctionType *fun_ty = FunctionType::get(
266435933ddSDimitry Andric         llvm::Type::getVoidTy(m_module.getContext()), params, true);
267ac7ddfbfSEd Maste     PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
268435933ddSDimitry Andric     Constant *fun_addr_int =
269435933ddSDimitry Andric         ConstantInt::get(GetIntptrTy(), start_address, false);
270ac7ddfbfSEd Maste     return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
271ac7ddfbfSEd Maste   }
272ac7ddfbfSEd Maste 
273ac7ddfbfSEd Maste   //------------------------------------------------------------------
274*4ba319b5SDimitry Andric   /// Build a function pointer for a function with signature void
275*4ba319b5SDimitry Andric   /// (*)(uint8_t*, uint8_t*) with a given address
276ac7ddfbfSEd Maste   ///
277ac7ddfbfSEd Maste   /// @param[in] start_address
278ac7ddfbfSEd Maste   ///     The address of the function.
279ac7ddfbfSEd Maste   ///
280ac7ddfbfSEd Maste   /// @return
281ac7ddfbfSEd Maste   ///     The function pointer, for use in a CallInst.
282ac7ddfbfSEd Maste   //------------------------------------------------------------------
BuildObjectCheckerFunc(lldb::addr_t start_address)283435933ddSDimitry Andric   llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) {
284ac7ddfbfSEd Maste     llvm::Type *param_array[2];
285ac7ddfbfSEd Maste 
286ac7ddfbfSEd Maste     param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
287ac7ddfbfSEd Maste     param_array[1] = const_cast<llvm::PointerType *>(GetI8PtrTy());
288ac7ddfbfSEd Maste 
289ac7ddfbfSEd Maste     ArrayRef<llvm::Type *> params(param_array, 2);
290ac7ddfbfSEd Maste 
291435933ddSDimitry Andric     FunctionType *fun_ty = FunctionType::get(
292435933ddSDimitry Andric         llvm::Type::getVoidTy(m_module.getContext()), params, true);
293ac7ddfbfSEd Maste     PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
294435933ddSDimitry Andric     Constant *fun_addr_int =
295435933ddSDimitry Andric         ConstantInt::get(GetIntptrTy(), start_address, false);
296ac7ddfbfSEd Maste     return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
297ac7ddfbfSEd Maste   }
298ac7ddfbfSEd Maste 
GetI8PtrTy()299435933ddSDimitry Andric   PointerType *GetI8PtrTy() {
300ac7ddfbfSEd Maste     if (!m_i8ptr_ty)
301ac7ddfbfSEd Maste       m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
302ac7ddfbfSEd Maste 
303ac7ddfbfSEd Maste     return m_i8ptr_ty;
304ac7ddfbfSEd Maste   }
305ac7ddfbfSEd Maste 
GetIntptrTy()306435933ddSDimitry Andric   IntegerType *GetIntptrTy() {
307435933ddSDimitry Andric     if (!m_intptr_ty) {
30812b93ac6SEd Maste       llvm::DataLayout data_layout(&m_module);
30912b93ac6SEd Maste 
310435933ddSDimitry Andric       m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
311435933ddSDimitry Andric                                           data_layout.getPointerSizeInBits());
31212b93ac6SEd Maste     }
31312b93ac6SEd Maste 
31412b93ac6SEd Maste     return m_intptr_ty;
31512b93ac6SEd Maste   }
31612b93ac6SEd Maste 
317ac7ddfbfSEd Maste   typedef std::vector<llvm::Instruction *> InstVector;
318ac7ddfbfSEd Maste   typedef InstVector::iterator InstIterator;
319ac7ddfbfSEd Maste 
320ac7ddfbfSEd Maste   InstVector m_to_instrument; ///< List of instructions the inspector found
321ac7ddfbfSEd Maste   llvm::Module &m_module;     ///< The module which is being instrumented
322435933ddSDimitry Andric   DynamicCheckerFunctions
323435933ddSDimitry Andric       &m_checker_functions; ///< The dynamic checker functions for the process
3249f2f44ceSEd Maste 
325ac7ddfbfSEd Maste private:
326ac7ddfbfSEd Maste   PointerType *m_i8ptr_ty;
32712b93ac6SEd Maste   IntegerType *m_intptr_ty;
328ac7ddfbfSEd Maste };
329ac7ddfbfSEd Maste 
330435933ddSDimitry Andric class ValidPointerChecker : public Instrumenter {
331ac7ddfbfSEd Maste public:
ValidPointerChecker(llvm::Module & module,DynamicCheckerFunctions & checker_functions)332ac7ddfbfSEd Maste   ValidPointerChecker(llvm::Module &module,
333435933ddSDimitry Andric                       DynamicCheckerFunctions &checker_functions)
334435933ddSDimitry Andric       : Instrumenter(module, checker_functions),
335435933ddSDimitry Andric         m_valid_pointer_check_func(nullptr) {}
336ac7ddfbfSEd Maste 
3379f2f44ceSEd Maste   ~ValidPointerChecker() override = default;
3389f2f44ceSEd Maste 
3399f2f44ceSEd Maste protected:
InstrumentInstruction(llvm::Instruction * inst)340435933ddSDimitry Andric   bool InstrumentInstruction(llvm::Instruction *inst) override {
341ac7ddfbfSEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
342ac7ddfbfSEd Maste 
343ac7ddfbfSEd Maste     if (log)
344ac7ddfbfSEd Maste       log->Printf("Instrumenting load/store instruction: %s\n",
345ac7ddfbfSEd Maste                   PrintValue(inst).c_str());
346ac7ddfbfSEd Maste 
347ac7ddfbfSEd Maste     if (!m_valid_pointer_check_func)
348435933ddSDimitry Andric       m_valid_pointer_check_func = BuildPointerValidatorFunc(
349435933ddSDimitry Andric           m_checker_functions.m_valid_pointer_check->StartAddress());
350ac7ddfbfSEd Maste 
3519f2f44ceSEd Maste     llvm::Value *dereferenced_ptr = nullptr;
352ac7ddfbfSEd Maste 
353ac7ddfbfSEd Maste     if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
354ac7ddfbfSEd Maste       dereferenced_ptr = li->getPointerOperand();
355ac7ddfbfSEd Maste     else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
356ac7ddfbfSEd Maste       dereferenced_ptr = si->getPointerOperand();
357ac7ddfbfSEd Maste     else
358ac7ddfbfSEd Maste       return false;
359ac7ddfbfSEd Maste 
360ac7ddfbfSEd Maste     // Insert an instruction to cast the loaded value to int8_t*
361ac7ddfbfSEd Maste 
362435933ddSDimitry Andric     BitCastInst *bit_cast =
363435933ddSDimitry Andric         new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst);
364ac7ddfbfSEd Maste 
365ac7ddfbfSEd Maste     // Insert an instruction to call the helper with the result
366ac7ddfbfSEd Maste 
367ac7ddfbfSEd Maste     llvm::Value *arg_array[1];
368ac7ddfbfSEd Maste 
369ac7ddfbfSEd Maste     arg_array[0] = bit_cast;
370ac7ddfbfSEd Maste 
371ac7ddfbfSEd Maste     llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
372ac7ddfbfSEd Maste 
373435933ddSDimitry Andric     CallInst::Create(m_valid_pointer_check_func, args, "", inst);
374ac7ddfbfSEd Maste 
375ac7ddfbfSEd Maste     return true;
376ac7ddfbfSEd Maste   }
377ac7ddfbfSEd Maste 
InspectInstruction(llvm::Instruction & i)378435933ddSDimitry Andric   bool InspectInstruction(llvm::Instruction &i) override {
379435933ddSDimitry Andric     if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i))
380ac7ddfbfSEd Maste       RegisterInstruction(i);
381ac7ddfbfSEd Maste 
382ac7ddfbfSEd Maste     return true;
383ac7ddfbfSEd Maste   }
384ac7ddfbfSEd Maste 
3859f2f44ceSEd Maste private:
386ac7ddfbfSEd Maste   llvm::Value *m_valid_pointer_check_func;
387ac7ddfbfSEd Maste };
388ac7ddfbfSEd Maste 
389435933ddSDimitry Andric class ObjcObjectChecker : public Instrumenter {
390ac7ddfbfSEd Maste public:
ObjcObjectChecker(llvm::Module & module,DynamicCheckerFunctions & checker_functions)391ac7ddfbfSEd Maste   ObjcObjectChecker(llvm::Module &module,
392435933ddSDimitry Andric                     DynamicCheckerFunctions &checker_functions)
393435933ddSDimitry Andric       : Instrumenter(module, checker_functions),
394435933ddSDimitry Andric         m_objc_object_check_func(nullptr) {}
395ac7ddfbfSEd Maste 
3969f2f44ceSEd Maste   ~ObjcObjectChecker() override = default;
397ac7ddfbfSEd Maste 
398435933ddSDimitry Andric   enum msgSend_type {
399ac7ddfbfSEd Maste     eMsgSend = 0,
400ac7ddfbfSEd Maste     eMsgSendSuper,
401ac7ddfbfSEd Maste     eMsgSendSuper_stret,
402ac7ddfbfSEd Maste     eMsgSend_fpret,
403ac7ddfbfSEd Maste     eMsgSend_stret
404ac7ddfbfSEd Maste   };
405ac7ddfbfSEd Maste 
406ac7ddfbfSEd Maste   std::map<llvm::Instruction *, msgSend_type> msgSend_types;
407ac7ddfbfSEd Maste 
4089f2f44ceSEd Maste protected:
InstrumentInstruction(llvm::Instruction * inst)409435933ddSDimitry Andric   bool InstrumentInstruction(llvm::Instruction *inst) override {
410ac7ddfbfSEd Maste     CallInst *call_inst = dyn_cast<CallInst>(inst);
411ac7ddfbfSEd Maste 
412ac7ddfbfSEd Maste     if (!call_inst)
413435933ddSDimitry Andric       return false; // call_inst really shouldn't be nullptr, because otherwise
414435933ddSDimitry Andric                     // InspectInstruction wouldn't have registered it
415ac7ddfbfSEd Maste 
416ac7ddfbfSEd Maste     if (!m_objc_object_check_func)
417435933ddSDimitry Andric       m_objc_object_check_func = BuildObjectCheckerFunc(
418435933ddSDimitry Andric           m_checker_functions.m_objc_object_check->StartAddress());
419ac7ddfbfSEd Maste 
420ac7ddfbfSEd Maste     // id objc_msgSend(id theReceiver, SEL theSelector, ...)
421ac7ddfbfSEd Maste 
422ac7ddfbfSEd Maste     llvm::Value *target_object;
423ac7ddfbfSEd Maste     llvm::Value *selector;
424ac7ddfbfSEd Maste 
425435933ddSDimitry Andric     switch (msgSend_types[inst]) {
426ac7ddfbfSEd Maste     case eMsgSend:
427ac7ddfbfSEd Maste     case eMsgSend_fpret:
428ac7ddfbfSEd Maste       target_object = call_inst->getArgOperand(0);
429ac7ddfbfSEd Maste       selector = call_inst->getArgOperand(1);
430ac7ddfbfSEd Maste       break;
431ac7ddfbfSEd Maste     case eMsgSend_stret:
432ac7ddfbfSEd Maste       target_object = call_inst->getArgOperand(1);
433ac7ddfbfSEd Maste       selector = call_inst->getArgOperand(2);
434ac7ddfbfSEd Maste       break;
435ac7ddfbfSEd Maste     case eMsgSendSuper:
436ac7ddfbfSEd Maste     case eMsgSendSuper_stret:
437ac7ddfbfSEd Maste       return true;
438ac7ddfbfSEd Maste     }
439ac7ddfbfSEd Maste 
440ac7ddfbfSEd Maste     // These objects should always be valid according to Sean Calannan
441ac7ddfbfSEd Maste     assert(target_object);
442ac7ddfbfSEd Maste     assert(selector);
443ac7ddfbfSEd Maste 
444ac7ddfbfSEd Maste     // Insert an instruction to cast the receiver id to int8_t*
445ac7ddfbfSEd Maste 
446435933ddSDimitry Andric     BitCastInst *bit_cast =
447435933ddSDimitry Andric         new BitCastInst(target_object, GetI8PtrTy(), "", inst);
448ac7ddfbfSEd Maste 
449ac7ddfbfSEd Maste     // Insert an instruction to call the helper with the result
450ac7ddfbfSEd Maste 
451ac7ddfbfSEd Maste     llvm::Value *arg_array[2];
452ac7ddfbfSEd Maste 
453ac7ddfbfSEd Maste     arg_array[0] = bit_cast;
454ac7ddfbfSEd Maste     arg_array[1] = selector;
455ac7ddfbfSEd Maste 
456ac7ddfbfSEd Maste     ArrayRef<llvm::Value *> args(arg_array, 2);
457ac7ddfbfSEd Maste 
458435933ddSDimitry Andric     CallInst::Create(m_objc_object_check_func, args, "", inst);
459ac7ddfbfSEd Maste 
460ac7ddfbfSEd Maste     return true;
461ac7ddfbfSEd Maste   }
462ac7ddfbfSEd Maste 
GetFunction(llvm::Value * value)463435933ddSDimitry Andric   static llvm::Function *GetFunction(llvm::Value *value) {
464435933ddSDimitry Andric     if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
4654bb0738eSEd Maste       return function;
4664bb0738eSEd Maste     }
4674bb0738eSEd Maste 
468435933ddSDimitry Andric     if (llvm::ConstantExpr *const_expr =
469435933ddSDimitry Andric             llvm::dyn_cast<llvm::ConstantExpr>(value)) {
470435933ddSDimitry Andric       switch (const_expr->getOpcode()) {
4714bb0738eSEd Maste       default:
4724bb0738eSEd Maste         return nullptr;
4734bb0738eSEd Maste       case llvm::Instruction::BitCast:
4744bb0738eSEd Maste         return GetFunction(const_expr->getOperand(0));
4754bb0738eSEd Maste       }
4764bb0738eSEd Maste     }
4774bb0738eSEd Maste 
4784bb0738eSEd Maste     return nullptr;
4794bb0738eSEd Maste   }
4804bb0738eSEd Maste 
GetCalledFunction(llvm::CallInst * inst)481435933ddSDimitry Andric   static llvm::Function *GetCalledFunction(llvm::CallInst *inst) {
4824bb0738eSEd Maste     return GetFunction(inst->getCalledValue());
4834bb0738eSEd Maste   }
4844bb0738eSEd Maste 
InspectInstruction(llvm::Instruction & i)485435933ddSDimitry Andric   bool InspectInstruction(llvm::Instruction &i) override {
486ac7ddfbfSEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
487ac7ddfbfSEd Maste 
488ac7ddfbfSEd Maste     CallInst *call_inst = dyn_cast<CallInst>(&i);
489ac7ddfbfSEd Maste 
490435933ddSDimitry Andric     if (call_inst) {
4914bb0738eSEd Maste       const llvm::Function *called_function = GetCalledFunction(call_inst);
492ac7ddfbfSEd Maste 
4934bb0738eSEd Maste       if (!called_function)
494ac7ddfbfSEd Maste         return true;
495ac7ddfbfSEd Maste 
4964bb0738eSEd Maste       std::string name_str = called_function->getName().str();
497ac7ddfbfSEd Maste       const char *name_cstr = name_str.c_str();
498ac7ddfbfSEd Maste 
499ac7ddfbfSEd Maste       if (log)
500435933ddSDimitry Andric         log->Printf("Found call to %s: %s\n", name_cstr,
501435933ddSDimitry Andric                     PrintValue(call_inst).c_str());
502ac7ddfbfSEd Maste 
503ac7ddfbfSEd Maste       if (name_str.find("objc_msgSend") == std::string::npos)
504ac7ddfbfSEd Maste         return true;
505ac7ddfbfSEd Maste 
506435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend")) {
507ac7ddfbfSEd Maste         RegisterInstruction(i);
508ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend;
509ac7ddfbfSEd Maste         return true;
510ac7ddfbfSEd Maste       }
511ac7ddfbfSEd Maste 
512435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend_stret")) {
513ac7ddfbfSEd Maste         RegisterInstruction(i);
514ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend_stret;
515ac7ddfbfSEd Maste         return true;
516ac7ddfbfSEd Maste       }
517ac7ddfbfSEd Maste 
518435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend_fpret")) {
519ac7ddfbfSEd Maste         RegisterInstruction(i);
520ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend_fpret;
521ac7ddfbfSEd Maste         return true;
522ac7ddfbfSEd Maste       }
523ac7ddfbfSEd Maste 
524435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSendSuper")) {
525ac7ddfbfSEd Maste         RegisterInstruction(i);
526ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSendSuper;
527ac7ddfbfSEd Maste         return true;
528ac7ddfbfSEd Maste       }
529ac7ddfbfSEd Maste 
530435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) {
531ac7ddfbfSEd Maste         RegisterInstruction(i);
532ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSendSuper_stret;
533ac7ddfbfSEd Maste         return true;
534ac7ddfbfSEd Maste       }
535ac7ddfbfSEd Maste 
536ac7ddfbfSEd Maste       if (log)
537435933ddSDimitry Andric         log->Printf(
538435933ddSDimitry Andric             "Function name '%s' contains 'objc_msgSend' but is not handled",
539435933ddSDimitry Andric             name_str.c_str());
540ac7ddfbfSEd Maste 
541ac7ddfbfSEd Maste       return true;
542ac7ddfbfSEd Maste     }
543ac7ddfbfSEd Maste 
544ac7ddfbfSEd Maste     return true;
545ac7ddfbfSEd Maste   }
546ac7ddfbfSEd Maste 
5479f2f44ceSEd Maste private:
548ac7ddfbfSEd Maste   llvm::Value *m_objc_object_check_func;
549ac7ddfbfSEd Maste };
550ac7ddfbfSEd Maste 
IRDynamicChecks(DynamicCheckerFunctions & checker_functions,const char * func_name)551ac7ddfbfSEd Maste IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
552435933ddSDimitry Andric                                  const char *func_name)
553435933ddSDimitry Andric     : ModulePass(ID), m_func_name(func_name),
554435933ddSDimitry Andric       m_checker_functions(checker_functions) {}
555ac7ddfbfSEd Maste 
5569f2f44ceSEd Maste IRDynamicChecks::~IRDynamicChecks() = default;
557ac7ddfbfSEd Maste 
runOnModule(llvm::Module & M)558435933ddSDimitry Andric bool IRDynamicChecks::runOnModule(llvm::Module &M) {
559ac7ddfbfSEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
560ac7ddfbfSEd Maste 
561435933ddSDimitry Andric   llvm::Function *function = M.getFunction(StringRef(m_func_name));
562ac7ddfbfSEd Maste 
563435933ddSDimitry Andric   if (!function) {
564ac7ddfbfSEd Maste     if (log)
565ac7ddfbfSEd Maste       log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
566ac7ddfbfSEd Maste 
567ac7ddfbfSEd Maste     return false;
568ac7ddfbfSEd Maste   }
569ac7ddfbfSEd Maste 
570435933ddSDimitry Andric   if (m_checker_functions.m_valid_pointer_check) {
571ac7ddfbfSEd Maste     ValidPointerChecker vpc(M, m_checker_functions);
572ac7ddfbfSEd Maste 
573ac7ddfbfSEd Maste     if (!vpc.Inspect(*function))
574ac7ddfbfSEd Maste       return false;
575ac7ddfbfSEd Maste 
576ac7ddfbfSEd Maste     if (!vpc.Instrument())
577ac7ddfbfSEd Maste       return false;
578ac7ddfbfSEd Maste   }
579ac7ddfbfSEd Maste 
580435933ddSDimitry Andric   if (m_checker_functions.m_objc_object_check) {
581ac7ddfbfSEd Maste     ObjcObjectChecker ooc(M, m_checker_functions);
582ac7ddfbfSEd Maste 
583ac7ddfbfSEd Maste     if (!ooc.Inspect(*function))
584ac7ddfbfSEd Maste       return false;
585ac7ddfbfSEd Maste 
586ac7ddfbfSEd Maste     if (!ooc.Instrument())
587ac7ddfbfSEd Maste       return false;
588ac7ddfbfSEd Maste   }
589ac7ddfbfSEd Maste 
590435933ddSDimitry Andric   if (log && log->GetVerbose()) {
591ac7ddfbfSEd Maste     std::string s;
592ac7ddfbfSEd Maste     raw_string_ostream oss(s);
593ac7ddfbfSEd Maste 
5949f2f44ceSEd Maste     M.print(oss, nullptr);
595ac7ddfbfSEd Maste 
596ac7ddfbfSEd Maste     oss.flush();
597ac7ddfbfSEd Maste 
598ac7ddfbfSEd Maste     log->Printf("Module after dynamic checks: \n%s", s.c_str());
599ac7ddfbfSEd Maste   }
600ac7ddfbfSEd Maste 
601ac7ddfbfSEd Maste   return true;
602ac7ddfbfSEd Maste }
603ac7ddfbfSEd Maste 
assignPassManager(PMStack & PMS,PassManagerType T)604435933ddSDimitry Andric void IRDynamicChecks::assignPassManager(PMStack &PMS, PassManagerType T) {}
605ac7ddfbfSEd Maste 
getPotentialPassManagerType() const606435933ddSDimitry Andric PassManagerType IRDynamicChecks::getPotentialPassManagerType() const {
607ac7ddfbfSEd Maste   return PMT_ModulePassManager;
608ac7ddfbfSEd Maste }
609