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 
109f2f44ceSEd Maste // C Includes
119f2f44ceSEd Maste // C++ Includes
129f2f44ceSEd Maste // Other libraries and framework includes
13ac7ddfbfSEd Maste #include "llvm/IR/Constants.h"
1412b93ac6SEd Maste #include "llvm/IR/DataLayout.h"
15ac7ddfbfSEd Maste #include "llvm/IR/Function.h"
16ac7ddfbfSEd Maste #include "llvm/IR/Instructions.h"
17ac7ddfbfSEd Maste #include "llvm/IR/Module.h"
18ac7ddfbfSEd Maste #include "llvm/IR/Value.h"
19435933ddSDimitry Andric #include "llvm/Support/raw_ostream.h"
20ac7ddfbfSEd Maste 
219f2f44ceSEd Maste // Project includes
229f2f44ceSEd Maste #include "lldb/Expression/IRDynamicChecks.h"
239f2f44ceSEd Maste 
249f2f44ceSEd Maste #include "lldb/Core/ConstString.h"
259f2f44ceSEd Maste #include "lldb/Core/Log.h"
269f2f44ceSEd Maste #include "lldb/Expression/UtilityFunction.h"
279f2f44ceSEd Maste #include "lldb/Target/ExecutionContext.h"
289f2f44ceSEd Maste #include "lldb/Target/ObjCLanguageRuntime.h"
299f2f44ceSEd Maste #include "lldb/Target/Process.h"
309f2f44ceSEd Maste #include "lldb/Target/StackFrame.h"
319f2f44ceSEd Maste #include "lldb/Target/Target.h"
329f2f44ceSEd Maste 
33ac7ddfbfSEd Maste using namespace llvm;
34ac7ddfbfSEd Maste using namespace lldb_private;
35ac7ddfbfSEd Maste 
36ac7ddfbfSEd Maste static char ID;
37ac7ddfbfSEd Maste 
38a8bcc4d8SDimitry Andric #define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
39ac7ddfbfSEd Maste #define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste static const char g_valid_pointer_check_text[] =
42ac7ddfbfSEd Maste     "extern \"C\" void\n"
43a8bcc4d8SDimitry Andric     "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
44ac7ddfbfSEd Maste     "{\n"
45ac7ddfbfSEd Maste     "    unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
46ac7ddfbfSEd Maste     "}";
47ac7ddfbfSEd Maste 
489f2f44ceSEd Maste DynamicCheckerFunctions::DynamicCheckerFunctions() = default;
49ac7ddfbfSEd Maste 
509f2f44ceSEd Maste DynamicCheckerFunctions::~DynamicCheckerFunctions() = default;
51ac7ddfbfSEd Maste 
52435933ddSDimitry Andric bool DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager,
53435933ddSDimitry Andric                                       ExecutionContext &exe_ctx) {
549f2f44ceSEd Maste   Error error;
55435933ddSDimitry Andric   m_valid_pointer_check.reset(
56435933ddSDimitry Andric       exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(
57435933ddSDimitry Andric           g_valid_pointer_check_text, lldb::eLanguageTypeC,
58435933ddSDimitry Andric           VALID_POINTER_CHECK_NAME, error));
599f2f44ceSEd Maste   if (error.Fail())
609f2f44ceSEd Maste     return false;
619f2f44ceSEd Maste 
624bb0738eSEd Maste   if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx))
63ac7ddfbfSEd Maste     return false;
64ac7ddfbfSEd Maste 
65ac7ddfbfSEd Maste   Process *process = exe_ctx.GetProcessPtr();
66ac7ddfbfSEd Maste 
67435933ddSDimitry Andric   if (process) {
68435933ddSDimitry Andric     ObjCLanguageRuntime *objc_language_runtime =
69435933ddSDimitry Andric         process->GetObjCLanguageRuntime();
70ac7ddfbfSEd Maste 
71435933ddSDimitry Andric     if (objc_language_runtime) {
72435933ddSDimitry Andric       m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(
73435933ddSDimitry Andric           VALID_OBJC_OBJECT_CHECK_NAME));
74ac7ddfbfSEd Maste 
754bb0738eSEd Maste       if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx))
76ac7ddfbfSEd Maste         return false;
77ac7ddfbfSEd Maste     }
78ac7ddfbfSEd Maste   }
79ac7ddfbfSEd Maste 
80ac7ddfbfSEd Maste   return true;
81ac7ddfbfSEd Maste }
82ac7ddfbfSEd Maste 
83435933ddSDimitry Andric bool DynamicCheckerFunctions::DoCheckersExplainStop(lldb::addr_t addr,
84435933ddSDimitry Andric                                                     Stream &message) {
85435933ddSDimitry Andric   // FIXME: We have to get the checkers to know why they scotched the call in
86435933ddSDimitry Andric   // more detail,
87ac7ddfbfSEd Maste   // so we can print a better message here.
88435933ddSDimitry Andric   if (m_valid_pointer_check && m_valid_pointer_check->ContainsAddress(addr)) {
89ac7ddfbfSEd Maste     message.Printf("Attempted to dereference an invalid pointer.");
90ac7ddfbfSEd Maste     return true;
91435933ddSDimitry Andric   } else if (m_objc_object_check &&
92435933ddSDimitry Andric              m_objc_object_check->ContainsAddress(addr)) {
93435933ddSDimitry Andric     message.Printf("Attempted to dereference an invalid ObjC Object or send it "
94435933ddSDimitry Andric                    "an unrecognized selector");
95ac7ddfbfSEd Maste     return true;
96ac7ddfbfSEd Maste   }
97ac7ddfbfSEd Maste   return false;
98ac7ddfbfSEd Maste }
99ac7ddfbfSEd Maste 
100435933ddSDimitry Andric static std::string PrintValue(llvm::Value *V, bool truncate = false) {
101ac7ddfbfSEd Maste   std::string s;
102ac7ddfbfSEd Maste   raw_string_ostream rso(s);
103ac7ddfbfSEd Maste   V->print(rso);
104ac7ddfbfSEd Maste   rso.flush();
105ac7ddfbfSEd Maste   if (truncate)
106ac7ddfbfSEd Maste     s.resize(s.length() - 1);
107ac7ddfbfSEd Maste   return s;
108ac7ddfbfSEd Maste }
109ac7ddfbfSEd Maste 
110ac7ddfbfSEd Maste //----------------------------------------------------------------------
111ac7ddfbfSEd Maste /// @class Instrumenter IRDynamicChecks.cpp
112ac7ddfbfSEd Maste /// @brief Finds and instruments individual LLVM IR instructions
113ac7ddfbfSEd Maste ///
114ac7ddfbfSEd Maste /// When instrumenting LLVM IR, it is frequently desirable to first search
115ac7ddfbfSEd Maste /// for instructions, and then later modify them.  This way iterators
116ac7ddfbfSEd Maste /// remain intact, and multiple passes can look at the same code base without
117ac7ddfbfSEd Maste /// treading on each other's toes.
118ac7ddfbfSEd Maste ///
119ac7ddfbfSEd Maste /// The Instrumenter class implements this functionality.  A client first
120ac7ddfbfSEd Maste /// calls Inspect on a function, which populates a list of instructions to
121ac7ddfbfSEd Maste /// be instrumented.  Then, later, when all passes' Inspect functions have
122ac7ddfbfSEd Maste /// been called, the client calls Instrument, which adds the desired
123ac7ddfbfSEd Maste /// instrumentation.
124ac7ddfbfSEd Maste ///
125ac7ddfbfSEd Maste /// A subclass of Instrumenter must override InstrumentInstruction, which
126ac7ddfbfSEd Maste /// is responsible for adding whatever instrumentation is necessary.
127ac7ddfbfSEd Maste ///
128ac7ddfbfSEd Maste /// A subclass of Instrumenter may override:
129ac7ddfbfSEd Maste ///
130ac7ddfbfSEd Maste /// - InspectInstruction [default: does nothing]
131ac7ddfbfSEd Maste ///
132ac7ddfbfSEd Maste /// - InspectBasicBlock [default: iterates through the instructions in a
133ac7ddfbfSEd Maste ///   basic block calling InspectInstruction]
134ac7ddfbfSEd Maste ///
135ac7ddfbfSEd Maste /// - InspectFunction [default: iterates through the basic blocks in a
136ac7ddfbfSEd Maste ///   function calling InspectBasicBlock]
137ac7ddfbfSEd Maste //----------------------------------------------------------------------
138ac7ddfbfSEd Maste class Instrumenter {
139ac7ddfbfSEd Maste public:
140ac7ddfbfSEd Maste   //------------------------------------------------------------------
141ac7ddfbfSEd Maste   /// Constructor
142ac7ddfbfSEd Maste   ///
143ac7ddfbfSEd Maste   /// @param[in] module
144ac7ddfbfSEd Maste   ///     The module being instrumented.
145ac7ddfbfSEd Maste   //------------------------------------------------------------------
146435933ddSDimitry Andric   Instrumenter(llvm::Module &module, DynamicCheckerFunctions &checker_functions)
147435933ddSDimitry Andric       : m_module(module), m_checker_functions(checker_functions),
148435933ddSDimitry Andric         m_i8ptr_ty(nullptr), m_intptr_ty(nullptr) {}
149ac7ddfbfSEd Maste 
1509f2f44ceSEd Maste   virtual ~Instrumenter() = default;
151ac7ddfbfSEd Maste 
152ac7ddfbfSEd Maste   //------------------------------------------------------------------
153ac7ddfbfSEd Maste   /// Inspect a function to find instructions to instrument
154ac7ddfbfSEd Maste   ///
155ac7ddfbfSEd Maste   /// @param[in] function
156ac7ddfbfSEd Maste   ///     The function to inspect.
157ac7ddfbfSEd Maste   ///
158ac7ddfbfSEd Maste   /// @return
159ac7ddfbfSEd Maste   ///     True on success; false on error.
160ac7ddfbfSEd Maste   //------------------------------------------------------------------
161435933ddSDimitry Andric   bool Inspect(llvm::Function &function) { return InspectFunction(function); }
162ac7ddfbfSEd Maste 
163ac7ddfbfSEd Maste   //------------------------------------------------------------------
164ac7ddfbfSEd Maste   /// Instrument all the instructions found by Inspect()
165ac7ddfbfSEd Maste   ///
166ac7ddfbfSEd Maste   /// @return
167ac7ddfbfSEd Maste   ///     True on success; false on error.
168ac7ddfbfSEd Maste   //------------------------------------------------------------------
169435933ddSDimitry Andric   bool Instrument() {
170435933ddSDimitry Andric     for (InstIterator ii = m_to_instrument.begin(),
171435933ddSDimitry Andric                       last_ii = m_to_instrument.end();
172435933ddSDimitry Andric          ii != last_ii; ++ii) {
173ac7ddfbfSEd Maste       if (!InstrumentInstruction(*ii))
174ac7ddfbfSEd Maste         return false;
175ac7ddfbfSEd Maste     }
176ac7ddfbfSEd Maste 
177ac7ddfbfSEd Maste     return true;
178ac7ddfbfSEd Maste   }
1799f2f44ceSEd Maste 
180ac7ddfbfSEd Maste protected:
181ac7ddfbfSEd Maste   //------------------------------------------------------------------
182ac7ddfbfSEd Maste   /// Add instrumentation to a single instruction
183ac7ddfbfSEd Maste   ///
184ac7ddfbfSEd Maste   /// @param[in] inst
185ac7ddfbfSEd Maste   ///     The instruction to be instrumented.
186ac7ddfbfSEd Maste   ///
187ac7ddfbfSEd Maste   /// @return
188ac7ddfbfSEd Maste   ///     True on success; false otherwise.
189ac7ddfbfSEd Maste   //------------------------------------------------------------------
190ac7ddfbfSEd Maste   virtual bool InstrumentInstruction(llvm::Instruction *inst) = 0;
191ac7ddfbfSEd Maste 
192ac7ddfbfSEd Maste   //------------------------------------------------------------------
193ac7ddfbfSEd Maste   /// Register a single instruction to be instrumented
194ac7ddfbfSEd Maste   ///
195ac7ddfbfSEd Maste   /// @param[in] inst
196ac7ddfbfSEd Maste   ///     The instruction to be instrumented.
197ac7ddfbfSEd Maste   //------------------------------------------------------------------
198435933ddSDimitry Andric   void RegisterInstruction(llvm::Instruction &i) {
199ac7ddfbfSEd Maste     m_to_instrument.push_back(&i);
200ac7ddfbfSEd Maste   }
201ac7ddfbfSEd Maste 
202ac7ddfbfSEd Maste   //------------------------------------------------------------------
203ac7ddfbfSEd Maste   /// Determine whether a single instruction is interesting to
204ac7ddfbfSEd Maste   /// instrument, and, if so, call RegisterInstruction
205ac7ddfbfSEd Maste   ///
206ac7ddfbfSEd Maste   /// @param[in] i
207ac7ddfbfSEd Maste   ///     The instruction to be inspected.
208ac7ddfbfSEd Maste   ///
209ac7ddfbfSEd Maste   /// @return
210ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
211ac7ddfbfSEd Maste   //------------------------------------------------------------------
212435933ddSDimitry Andric   virtual bool InspectInstruction(llvm::Instruction &i) { return true; }
213ac7ddfbfSEd Maste 
214ac7ddfbfSEd Maste   //------------------------------------------------------------------
215ac7ddfbfSEd Maste   /// Scan a basic block to see if any instructions are interesting
216ac7ddfbfSEd Maste   ///
217ac7ddfbfSEd Maste   /// @param[in] bb
218ac7ddfbfSEd Maste   ///     The basic block to be inspected.
219ac7ddfbfSEd Maste   ///
220ac7ddfbfSEd Maste   /// @return
221ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
222ac7ddfbfSEd Maste   //------------------------------------------------------------------
223435933ddSDimitry Andric   virtual bool InspectBasicBlock(llvm::BasicBlock &bb) {
224ac7ddfbfSEd Maste     for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
225435933ddSDimitry Andric          ii != last_ii; ++ii) {
226ac7ddfbfSEd Maste       if (!InspectInstruction(*ii))
227ac7ddfbfSEd Maste         return false;
228ac7ddfbfSEd Maste     }
229ac7ddfbfSEd Maste 
230ac7ddfbfSEd Maste     return true;
231ac7ddfbfSEd Maste   }
232ac7ddfbfSEd Maste 
233ac7ddfbfSEd Maste   //------------------------------------------------------------------
234ac7ddfbfSEd Maste   /// Scan a function to see if any instructions are interesting
235ac7ddfbfSEd Maste   ///
236ac7ddfbfSEd Maste   /// @param[in] f
237ac7ddfbfSEd Maste   ///     The function to be inspected.
238ac7ddfbfSEd Maste   ///
239ac7ddfbfSEd Maste   /// @return
240ac7ddfbfSEd Maste   ///     False if there was an error scanning; true otherwise.
241ac7ddfbfSEd Maste   //------------------------------------------------------------------
242435933ddSDimitry Andric   virtual bool InspectFunction(llvm::Function &f) {
243ac7ddfbfSEd Maste     for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
244435933ddSDimitry Andric          bbi != last_bbi; ++bbi) {
245ac7ddfbfSEd Maste       if (!InspectBasicBlock(*bbi))
246ac7ddfbfSEd Maste         return false;
247ac7ddfbfSEd Maste     }
248ac7ddfbfSEd Maste 
249ac7ddfbfSEd Maste     return true;
250ac7ddfbfSEd Maste   }
251ac7ddfbfSEd Maste 
252ac7ddfbfSEd Maste   //------------------------------------------------------------------
253ac7ddfbfSEd Maste   /// Build a function pointer for a function with signature
254ac7ddfbfSEd Maste   /// void (*)(uint8_t*) with a given address
255ac7ddfbfSEd Maste   ///
256ac7ddfbfSEd Maste   /// @param[in] start_address
257ac7ddfbfSEd Maste   ///     The address of the function.
258ac7ddfbfSEd Maste   ///
259ac7ddfbfSEd Maste   /// @return
260ac7ddfbfSEd Maste   ///     The function pointer, for use in a CallInst.
261ac7ddfbfSEd Maste   //------------------------------------------------------------------
262435933ddSDimitry Andric   llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) {
263ac7ddfbfSEd Maste     llvm::Type *param_array[1];
264ac7ddfbfSEd Maste 
265ac7ddfbfSEd Maste     param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
266ac7ddfbfSEd Maste 
267ac7ddfbfSEd Maste     ArrayRef<llvm::Type *> params(param_array, 1);
268ac7ddfbfSEd Maste 
269435933ddSDimitry Andric     FunctionType *fun_ty = FunctionType::get(
270435933ddSDimitry Andric         llvm::Type::getVoidTy(m_module.getContext()), params, true);
271ac7ddfbfSEd Maste     PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
272435933ddSDimitry Andric     Constant *fun_addr_int =
273435933ddSDimitry Andric         ConstantInt::get(GetIntptrTy(), start_address, false);
274ac7ddfbfSEd Maste     return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
275ac7ddfbfSEd Maste   }
276ac7ddfbfSEd Maste 
277ac7ddfbfSEd Maste   //------------------------------------------------------------------
278ac7ddfbfSEd Maste   /// Build a function pointer for a function with signature
279ac7ddfbfSEd Maste   /// void (*)(uint8_t*, uint8_t*) with a given address
280ac7ddfbfSEd Maste   ///
281ac7ddfbfSEd Maste   /// @param[in] start_address
282ac7ddfbfSEd Maste   ///     The address of the function.
283ac7ddfbfSEd Maste   ///
284ac7ddfbfSEd Maste   /// @return
285ac7ddfbfSEd Maste   ///     The function pointer, for use in a CallInst.
286ac7ddfbfSEd Maste   //------------------------------------------------------------------
287435933ddSDimitry Andric   llvm::Value *BuildObjectCheckerFunc(lldb::addr_t start_address) {
288ac7ddfbfSEd Maste     llvm::Type *param_array[2];
289ac7ddfbfSEd Maste 
290ac7ddfbfSEd Maste     param_array[0] = const_cast<llvm::PointerType *>(GetI8PtrTy());
291ac7ddfbfSEd Maste     param_array[1] = const_cast<llvm::PointerType *>(GetI8PtrTy());
292ac7ddfbfSEd Maste 
293ac7ddfbfSEd Maste     ArrayRef<llvm::Type *> params(param_array, 2);
294ac7ddfbfSEd Maste 
295435933ddSDimitry Andric     FunctionType *fun_ty = FunctionType::get(
296435933ddSDimitry Andric         llvm::Type::getVoidTy(m_module.getContext()), params, true);
297ac7ddfbfSEd Maste     PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
298435933ddSDimitry Andric     Constant *fun_addr_int =
299435933ddSDimitry Andric         ConstantInt::get(GetIntptrTy(), start_address, false);
300ac7ddfbfSEd Maste     return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
301ac7ddfbfSEd Maste   }
302ac7ddfbfSEd Maste 
303435933ddSDimitry Andric   PointerType *GetI8PtrTy() {
304ac7ddfbfSEd Maste     if (!m_i8ptr_ty)
305ac7ddfbfSEd Maste       m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
306ac7ddfbfSEd Maste 
307ac7ddfbfSEd Maste     return m_i8ptr_ty;
308ac7ddfbfSEd Maste   }
309ac7ddfbfSEd Maste 
310435933ddSDimitry Andric   IntegerType *GetIntptrTy() {
311435933ddSDimitry Andric     if (!m_intptr_ty) {
31212b93ac6SEd Maste       llvm::DataLayout data_layout(&m_module);
31312b93ac6SEd Maste 
314435933ddSDimitry Andric       m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
315435933ddSDimitry Andric                                           data_layout.getPointerSizeInBits());
31612b93ac6SEd Maste     }
31712b93ac6SEd Maste 
31812b93ac6SEd Maste     return m_intptr_ty;
31912b93ac6SEd Maste   }
32012b93ac6SEd Maste 
321ac7ddfbfSEd Maste   typedef std::vector<llvm::Instruction *> InstVector;
322ac7ddfbfSEd Maste   typedef InstVector::iterator InstIterator;
323ac7ddfbfSEd Maste 
324ac7ddfbfSEd Maste   InstVector m_to_instrument; ///< List of instructions the inspector found
325ac7ddfbfSEd Maste   llvm::Module &m_module;     ///< The module which is being instrumented
326435933ddSDimitry Andric   DynamicCheckerFunctions
327435933ddSDimitry Andric       &m_checker_functions; ///< The dynamic checker functions for the process
3289f2f44ceSEd Maste 
329ac7ddfbfSEd Maste private:
330ac7ddfbfSEd Maste   PointerType *m_i8ptr_ty;
33112b93ac6SEd Maste   IntegerType *m_intptr_ty;
332ac7ddfbfSEd Maste };
333ac7ddfbfSEd Maste 
334435933ddSDimitry Andric class ValidPointerChecker : public Instrumenter {
335ac7ddfbfSEd Maste public:
336ac7ddfbfSEd Maste   ValidPointerChecker(llvm::Module &module,
337435933ddSDimitry Andric                       DynamicCheckerFunctions &checker_functions)
338435933ddSDimitry Andric       : Instrumenter(module, checker_functions),
339435933ddSDimitry Andric         m_valid_pointer_check_func(nullptr) {}
340ac7ddfbfSEd Maste 
3419f2f44ceSEd Maste   ~ValidPointerChecker() override = default;
3429f2f44ceSEd Maste 
3439f2f44ceSEd Maste protected:
344435933ddSDimitry Andric   bool InstrumentInstruction(llvm::Instruction *inst) override {
345ac7ddfbfSEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
346ac7ddfbfSEd Maste 
347ac7ddfbfSEd Maste     if (log)
348ac7ddfbfSEd Maste       log->Printf("Instrumenting load/store instruction: %s\n",
349ac7ddfbfSEd Maste                   PrintValue(inst).c_str());
350ac7ddfbfSEd Maste 
351ac7ddfbfSEd Maste     if (!m_valid_pointer_check_func)
352435933ddSDimitry Andric       m_valid_pointer_check_func = BuildPointerValidatorFunc(
353435933ddSDimitry Andric           m_checker_functions.m_valid_pointer_check->StartAddress());
354ac7ddfbfSEd Maste 
3559f2f44ceSEd Maste     llvm::Value *dereferenced_ptr = nullptr;
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste     if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
358ac7ddfbfSEd Maste       dereferenced_ptr = li->getPointerOperand();
359ac7ddfbfSEd Maste     else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
360ac7ddfbfSEd Maste       dereferenced_ptr = si->getPointerOperand();
361ac7ddfbfSEd Maste     else
362ac7ddfbfSEd Maste       return false;
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste     // Insert an instruction to cast the loaded value to int8_t*
365ac7ddfbfSEd Maste 
366435933ddSDimitry Andric     BitCastInst *bit_cast =
367435933ddSDimitry Andric         new BitCastInst(dereferenced_ptr, GetI8PtrTy(), "", inst);
368ac7ddfbfSEd Maste 
369ac7ddfbfSEd Maste     // Insert an instruction to call the helper with the result
370ac7ddfbfSEd Maste 
371ac7ddfbfSEd Maste     llvm::Value *arg_array[1];
372ac7ddfbfSEd Maste 
373ac7ddfbfSEd Maste     arg_array[0] = bit_cast;
374ac7ddfbfSEd Maste 
375ac7ddfbfSEd Maste     llvm::ArrayRef<llvm::Value *> args(arg_array, 1);
376ac7ddfbfSEd Maste 
377435933ddSDimitry Andric     CallInst::Create(m_valid_pointer_check_func, args, "", inst);
378ac7ddfbfSEd Maste 
379ac7ddfbfSEd Maste     return true;
380ac7ddfbfSEd Maste   }
381ac7ddfbfSEd Maste 
382435933ddSDimitry Andric   bool InspectInstruction(llvm::Instruction &i) override {
383435933ddSDimitry Andric     if (dyn_cast<llvm::LoadInst>(&i) || dyn_cast<llvm::StoreInst>(&i))
384ac7ddfbfSEd Maste       RegisterInstruction(i);
385ac7ddfbfSEd Maste 
386ac7ddfbfSEd Maste     return true;
387ac7ddfbfSEd Maste   }
388ac7ddfbfSEd Maste 
3899f2f44ceSEd Maste private:
390ac7ddfbfSEd Maste   llvm::Value *m_valid_pointer_check_func;
391ac7ddfbfSEd Maste };
392ac7ddfbfSEd Maste 
393435933ddSDimitry Andric class ObjcObjectChecker : public Instrumenter {
394ac7ddfbfSEd Maste public:
395ac7ddfbfSEd Maste   ObjcObjectChecker(llvm::Module &module,
396435933ddSDimitry Andric                     DynamicCheckerFunctions &checker_functions)
397435933ddSDimitry Andric       : Instrumenter(module, checker_functions),
398435933ddSDimitry Andric         m_objc_object_check_func(nullptr) {}
399ac7ddfbfSEd Maste 
4009f2f44ceSEd Maste   ~ObjcObjectChecker() override = default;
401ac7ddfbfSEd Maste 
402435933ddSDimitry Andric   enum msgSend_type {
403ac7ddfbfSEd Maste     eMsgSend = 0,
404ac7ddfbfSEd Maste     eMsgSendSuper,
405ac7ddfbfSEd Maste     eMsgSendSuper_stret,
406ac7ddfbfSEd Maste     eMsgSend_fpret,
407ac7ddfbfSEd Maste     eMsgSend_stret
408ac7ddfbfSEd Maste   };
409ac7ddfbfSEd Maste 
410ac7ddfbfSEd Maste   std::map<llvm::Instruction *, msgSend_type> msgSend_types;
411ac7ddfbfSEd Maste 
4129f2f44ceSEd Maste protected:
413435933ddSDimitry Andric   bool InstrumentInstruction(llvm::Instruction *inst) override {
414ac7ddfbfSEd Maste     CallInst *call_inst = dyn_cast<CallInst>(inst);
415ac7ddfbfSEd Maste 
416ac7ddfbfSEd Maste     if (!call_inst)
417435933ddSDimitry Andric       return false; // call_inst really shouldn't be nullptr, because otherwise
418435933ddSDimitry Andric                     // InspectInstruction wouldn't have registered it
419ac7ddfbfSEd Maste 
420ac7ddfbfSEd Maste     if (!m_objc_object_check_func)
421435933ddSDimitry Andric       m_objc_object_check_func = BuildObjectCheckerFunc(
422435933ddSDimitry Andric           m_checker_functions.m_objc_object_check->StartAddress());
423ac7ddfbfSEd Maste 
424ac7ddfbfSEd Maste     // id objc_msgSend(id theReceiver, SEL theSelector, ...)
425ac7ddfbfSEd Maste 
426ac7ddfbfSEd Maste     llvm::Value *target_object;
427ac7ddfbfSEd Maste     llvm::Value *selector;
428ac7ddfbfSEd Maste 
429435933ddSDimitry Andric     switch (msgSend_types[inst]) {
430ac7ddfbfSEd Maste     case eMsgSend:
431ac7ddfbfSEd Maste     case eMsgSend_fpret:
432ac7ddfbfSEd Maste       target_object = call_inst->getArgOperand(0);
433ac7ddfbfSEd Maste       selector = call_inst->getArgOperand(1);
434ac7ddfbfSEd Maste       break;
435ac7ddfbfSEd Maste     case eMsgSend_stret:
436ac7ddfbfSEd Maste       target_object = call_inst->getArgOperand(1);
437ac7ddfbfSEd Maste       selector = call_inst->getArgOperand(2);
438ac7ddfbfSEd Maste       break;
439ac7ddfbfSEd Maste     case eMsgSendSuper:
440ac7ddfbfSEd Maste     case eMsgSendSuper_stret:
441ac7ddfbfSEd Maste       return true;
442ac7ddfbfSEd Maste     }
443ac7ddfbfSEd Maste 
444ac7ddfbfSEd Maste     // These objects should always be valid according to Sean Calannan
445ac7ddfbfSEd Maste     assert(target_object);
446ac7ddfbfSEd Maste     assert(selector);
447ac7ddfbfSEd Maste 
448ac7ddfbfSEd Maste     // Insert an instruction to cast the receiver id to int8_t*
449ac7ddfbfSEd Maste 
450435933ddSDimitry Andric     BitCastInst *bit_cast =
451435933ddSDimitry Andric         new BitCastInst(target_object, GetI8PtrTy(), "", inst);
452ac7ddfbfSEd Maste 
453ac7ddfbfSEd Maste     // Insert an instruction to call the helper with the result
454ac7ddfbfSEd Maste 
455ac7ddfbfSEd Maste     llvm::Value *arg_array[2];
456ac7ddfbfSEd Maste 
457ac7ddfbfSEd Maste     arg_array[0] = bit_cast;
458ac7ddfbfSEd Maste     arg_array[1] = selector;
459ac7ddfbfSEd Maste 
460ac7ddfbfSEd Maste     ArrayRef<llvm::Value *> args(arg_array, 2);
461ac7ddfbfSEd Maste 
462435933ddSDimitry Andric     CallInst::Create(m_objc_object_check_func, args, "", inst);
463ac7ddfbfSEd Maste 
464ac7ddfbfSEd Maste     return true;
465ac7ddfbfSEd Maste   }
466ac7ddfbfSEd Maste 
467435933ddSDimitry Andric   static llvm::Function *GetFunction(llvm::Value *value) {
468435933ddSDimitry Andric     if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
4694bb0738eSEd Maste       return function;
4704bb0738eSEd Maste     }
4714bb0738eSEd Maste 
472435933ddSDimitry Andric     if (llvm::ConstantExpr *const_expr =
473435933ddSDimitry Andric             llvm::dyn_cast<llvm::ConstantExpr>(value)) {
474435933ddSDimitry Andric       switch (const_expr->getOpcode()) {
4754bb0738eSEd Maste       default:
4764bb0738eSEd Maste         return nullptr;
4774bb0738eSEd Maste       case llvm::Instruction::BitCast:
4784bb0738eSEd Maste         return GetFunction(const_expr->getOperand(0));
4794bb0738eSEd Maste       }
4804bb0738eSEd Maste     }
4814bb0738eSEd Maste 
4824bb0738eSEd Maste     return nullptr;
4834bb0738eSEd Maste   }
4844bb0738eSEd Maste 
485435933ddSDimitry Andric   static llvm::Function *GetCalledFunction(llvm::CallInst *inst) {
4864bb0738eSEd Maste     return GetFunction(inst->getCalledValue());
4874bb0738eSEd Maste   }
4884bb0738eSEd Maste 
489435933ddSDimitry Andric   bool InspectInstruction(llvm::Instruction &i) override {
490ac7ddfbfSEd Maste     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
491ac7ddfbfSEd Maste 
492ac7ddfbfSEd Maste     CallInst *call_inst = dyn_cast<CallInst>(&i);
493ac7ddfbfSEd Maste 
494435933ddSDimitry Andric     if (call_inst) {
4954bb0738eSEd Maste       const llvm::Function *called_function = GetCalledFunction(call_inst);
496ac7ddfbfSEd Maste 
4974bb0738eSEd Maste       if (!called_function)
498ac7ddfbfSEd Maste         return true;
499ac7ddfbfSEd Maste 
5004bb0738eSEd Maste       std::string name_str = called_function->getName().str();
501ac7ddfbfSEd Maste       const char *name_cstr = name_str.c_str();
502ac7ddfbfSEd Maste 
503ac7ddfbfSEd Maste       if (log)
504435933ddSDimitry Andric         log->Printf("Found call to %s: %s\n", name_cstr,
505435933ddSDimitry Andric                     PrintValue(call_inst).c_str());
506ac7ddfbfSEd Maste 
507ac7ddfbfSEd Maste       if (name_str.find("objc_msgSend") == std::string::npos)
508ac7ddfbfSEd Maste         return true;
509ac7ddfbfSEd Maste 
510435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend")) {
511ac7ddfbfSEd Maste         RegisterInstruction(i);
512ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend;
513ac7ddfbfSEd Maste         return true;
514ac7ddfbfSEd Maste       }
515ac7ddfbfSEd Maste 
516435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend_stret")) {
517ac7ddfbfSEd Maste         RegisterInstruction(i);
518ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend_stret;
519ac7ddfbfSEd Maste         return true;
520ac7ddfbfSEd Maste       }
521ac7ddfbfSEd Maste 
522435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSend_fpret")) {
523ac7ddfbfSEd Maste         RegisterInstruction(i);
524ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSend_fpret;
525ac7ddfbfSEd Maste         return true;
526ac7ddfbfSEd Maste       }
527ac7ddfbfSEd Maste 
528435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSendSuper")) {
529ac7ddfbfSEd Maste         RegisterInstruction(i);
530ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSendSuper;
531ac7ddfbfSEd Maste         return true;
532ac7ddfbfSEd Maste       }
533ac7ddfbfSEd Maste 
534435933ddSDimitry Andric       if (!strcmp(name_cstr, "objc_msgSendSuper_stret")) {
535ac7ddfbfSEd Maste         RegisterInstruction(i);
536ac7ddfbfSEd Maste         msgSend_types[&i] = eMsgSendSuper_stret;
537ac7ddfbfSEd Maste         return true;
538ac7ddfbfSEd Maste       }
539ac7ddfbfSEd Maste 
540ac7ddfbfSEd Maste       if (log)
541435933ddSDimitry Andric         log->Printf(
542435933ddSDimitry Andric             "Function name '%s' contains 'objc_msgSend' but is not handled",
543435933ddSDimitry Andric             name_str.c_str());
544ac7ddfbfSEd Maste 
545ac7ddfbfSEd Maste       return true;
546ac7ddfbfSEd Maste     }
547ac7ddfbfSEd Maste 
548ac7ddfbfSEd Maste     return true;
549ac7ddfbfSEd Maste   }
550ac7ddfbfSEd Maste 
5519f2f44ceSEd Maste private:
552ac7ddfbfSEd Maste   llvm::Value *m_objc_object_check_func;
553ac7ddfbfSEd Maste };
554ac7ddfbfSEd Maste 
555ac7ddfbfSEd Maste IRDynamicChecks::IRDynamicChecks(DynamicCheckerFunctions &checker_functions,
556435933ddSDimitry Andric                                  const char *func_name)
557435933ddSDimitry Andric     : ModulePass(ID), m_func_name(func_name),
558435933ddSDimitry Andric       m_checker_functions(checker_functions) {}
559ac7ddfbfSEd Maste 
5609f2f44ceSEd Maste IRDynamicChecks::~IRDynamicChecks() = default;
561ac7ddfbfSEd Maste 
562435933ddSDimitry Andric bool IRDynamicChecks::runOnModule(llvm::Module &M) {
563ac7ddfbfSEd Maste   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
564ac7ddfbfSEd Maste 
565435933ddSDimitry Andric   llvm::Function *function = M.getFunction(StringRef(m_func_name));
566ac7ddfbfSEd Maste 
567435933ddSDimitry Andric   if (!function) {
568ac7ddfbfSEd Maste     if (log)
569ac7ddfbfSEd Maste       log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
570ac7ddfbfSEd Maste 
571ac7ddfbfSEd Maste     return false;
572ac7ddfbfSEd Maste   }
573ac7ddfbfSEd Maste 
574435933ddSDimitry Andric   if (m_checker_functions.m_valid_pointer_check) {
575ac7ddfbfSEd Maste     ValidPointerChecker vpc(M, m_checker_functions);
576ac7ddfbfSEd Maste 
577ac7ddfbfSEd Maste     if (!vpc.Inspect(*function))
578ac7ddfbfSEd Maste       return false;
579ac7ddfbfSEd Maste 
580ac7ddfbfSEd Maste     if (!vpc.Instrument())
581ac7ddfbfSEd Maste       return false;
582ac7ddfbfSEd Maste   }
583ac7ddfbfSEd Maste 
584435933ddSDimitry Andric   if (m_checker_functions.m_objc_object_check) {
585ac7ddfbfSEd Maste     ObjcObjectChecker ooc(M, m_checker_functions);
586ac7ddfbfSEd Maste 
587ac7ddfbfSEd Maste     if (!ooc.Inspect(*function))
588ac7ddfbfSEd Maste       return false;
589ac7ddfbfSEd Maste 
590ac7ddfbfSEd Maste     if (!ooc.Instrument())
591ac7ddfbfSEd Maste       return false;
592ac7ddfbfSEd Maste   }
593ac7ddfbfSEd Maste 
594435933ddSDimitry Andric   if (log && log->GetVerbose()) {
595ac7ddfbfSEd Maste     std::string s;
596ac7ddfbfSEd Maste     raw_string_ostream oss(s);
597ac7ddfbfSEd Maste 
5989f2f44ceSEd Maste     M.print(oss, nullptr);
599ac7ddfbfSEd Maste 
600ac7ddfbfSEd Maste     oss.flush();
601ac7ddfbfSEd Maste 
602ac7ddfbfSEd Maste     log->Printf("Module after dynamic checks: \n%s", s.c_str());
603ac7ddfbfSEd Maste   }
604ac7ddfbfSEd Maste 
605ac7ddfbfSEd Maste   return true;
606ac7ddfbfSEd Maste }
607ac7ddfbfSEd Maste 
608435933ddSDimitry Andric void IRDynamicChecks::assignPassManager(PMStack &PMS, PassManagerType T) {}
609ac7ddfbfSEd Maste 
610435933ddSDimitry Andric PassManagerType IRDynamicChecks::getPotentialPassManagerType() const {
611ac7ddfbfSEd Maste   return PMT_ModulePassManager;
612ac7ddfbfSEd Maste }
613