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/Expression/UtilityFunction.h" 259f2f44ceSEd Maste #include "lldb/Target/ExecutionContext.h" 269f2f44ceSEd Maste #include "lldb/Target/ObjCLanguageRuntime.h" 279f2f44ceSEd Maste #include "lldb/Target/Process.h" 289f2f44ceSEd Maste #include "lldb/Target/StackFrame.h" 299f2f44ceSEd Maste #include "lldb/Target/Target.h" 30f678e45dSDimitry Andric #include "lldb/Utility/ConstString.h" 31f678e45dSDimitry Andric #include "lldb/Utility/Log.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) { 545517e702SDimitry Andric Status 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