9#include "llvm/IR/Constants.h"
10#include "llvm/IR/DataLayout.h"
11#include "llvm/IR/Function.h"
12#include "llvm/IR/Instructions.h"
13#include "llvm/IR/Module.h"
14#include "llvm/IR/Value.h"
15#include "llvm/Support/raw_ostream.h"
35#define VALID_POINTER_CHECK_NAME "_$__lldb_valid_pointer_check"
36#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
40 "_$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
42 " unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
55 if (!utility_fn_or_error) {
56 llvm::consumeError(utility_fn_or_error.takeError());
65 if (objc_language_runtime) {
68 if (!utility_fn_or_error) {
69 llvm::consumeError(utility_fn_or_error.takeError());
85 message.
Printf(
"Attempted to dereference an invalid pointer.");
89 message.
Printf(
"Attempted to dereference an invalid ObjC Object or send it "
90 "an unrecognized selector");
96static std::string
PrintValue(llvm::Value *V,
bool truncate =
false) {
98 raw_string_ostream rso(s);
102 s.resize(s.length() - 1);
139 std::shared_ptr<UtilityFunction> checker_function)
140 : m_module(module), m_checker_function(checker_function) {}
151 bool Inspect(llvm::Function &function) {
return InspectFunction(function); }
159 last_ii = m_to_instrument.end();
160 ii != last_ii; ++ii) {
161 if (!InstrumentInstruction(*ii))
183 m_to_instrument.push_back(&inst);
204 for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
205 ii != last_ii; ++ii) {
206 if (!InspectInstruction(*ii))
221 for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
222 bbi != last_bbi; ++bbi) {
223 if (!InspectBasicBlock(*bbi))
239 llvm::Type *param_array[1];
241 param_array[0] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
243 ArrayRef<llvm::Type *> params(param_array, 1);
245 FunctionType *fun_ty = FunctionType::get(
246 llvm::Type::getVoidTy(m_module.getContext()), params,
true);
247 PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
248 Constant *fun_addr_int =
249 ConstantInt::get(GetIntptrTy(), start_address,
false);
250 return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
262 llvm::Type *param_array[2];
264 param_array[0] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
265 param_array[1] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
267 ArrayRef<llvm::Type *> params(param_array, 2);
269 FunctionType *fun_ty = FunctionType::get(
270 llvm::Type::getVoidTy(m_module.getContext()), params,
true);
271 PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
272 Constant *fun_addr_int =
273 ConstantInt::get(GetIntptrTy(), start_address,
false);
274 return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
279 m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
286 llvm::DataLayout data_layout(&m_module);
288 m_intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
289 data_layout.getPointerSizeInBits());
300 std::shared_ptr<UtilityFunction>
304 PointerType *m_i8ptr_ty =
nullptr;
305 IntegerType *m_intptr_ty =
nullptr;
311 std::shared_ptr<UtilityFunction> checker_function)
313 m_valid_pointer_check_func(nullptr) {}
321 LLDB_LOGF(log,
"Instrumenting load/store instruction: %s\n",
324 if (!m_valid_pointer_check_func)
325 m_valid_pointer_check_func =
326 BuildPointerValidatorFunc(m_checker_function->StartAddress());
328 llvm::Value *dereferenced_ptr =
nullptr;
330 if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
331 dereferenced_ptr = li->getPointerOperand();
332 else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
333 dereferenced_ptr = si->getPointerOperand();
338 CallInst::Create(m_valid_pointer_check_func, dereferenced_ptr,
"", inst);
344 if (isa<llvm::LoadInst>(&i) || isa<llvm::StoreInst>(&i))
345 RegisterInstruction(i);
357 std::shared_ptr<UtilityFunction> checker_function)
359 m_objc_object_check_func(nullptr) {}
375 CallInst *call_inst = dyn_cast<CallInst>(inst);
381 if (!m_objc_object_check_func)
382 m_objc_object_check_func =
383 BuildObjectCheckerFunc(m_checker_function->StartAddress());
387 llvm::Value *target_object;
388 llvm::Value *selector;
390 switch (msgSend_types[inst]) {
395 if (call_inst->hasStructRetAttr()) {
396 target_object = call_inst->getArgOperand(1);
397 selector = call_inst->getArgOperand(2);
399 target_object = call_inst->getArgOperand(0);
400 selector = call_inst->getArgOperand(1);
404 target_object = call_inst->getArgOperand(1);
405 selector = call_inst->getArgOperand(2);
408 case eMsgSendSuper_stret:
413 assert(target_object);
418 llvm::Value *arg_array[2];
420 arg_array[0] = target_object;
421 arg_array[1] = selector;
423 ArrayRef<llvm::Value *> args(arg_array, 2);
425 CallInst::Create(m_objc_object_check_func, args,
"", inst);
431 if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
435 if (llvm::ConstantExpr *const_expr =
436 llvm::dyn_cast<llvm::ConstantExpr>(value)) {
437 switch (const_expr->getOpcode()) {
440 case llvm::Instruction::BitCast:
441 return GetFunction(const_expr->getOperand(0));
449 return GetFunction(inst->getCalledOperand());
455 CallInst *call_inst = dyn_cast<CallInst>(&i);
458 const llvm::Function *called_function = GetCalledFunction(call_inst);
460 if (!called_function)
463 std::string name_str = called_function->getName().str();
464 const char *name_cstr = name_str.c_str();
466 LLDB_LOGF(log,
"Found call to %s: %s\n", name_cstr,
469 if (name_str.find(
"objc_msgSend") == std::string::npos)
472 if (!strcmp(name_cstr,
"objc_msgSend")) {
473 RegisterInstruction(i);
474 msgSend_types[&i] = eMsgSend;
478 if (!strcmp(name_cstr,
"objc_msgSend_stret")) {
479 RegisterInstruction(i);
480 msgSend_types[&i] = eMsgSend_stret;
484 if (!strcmp(name_cstr,
"objc_msgSend_fpret")) {
485 RegisterInstruction(i);
486 msgSend_types[&i] = eMsgSend_fpret;
490 if (!strcmp(name_cstr,
"objc_msgSendSuper")) {
491 RegisterInstruction(i);
492 msgSend_types[&i] = eMsgSendSuper;
496 if (!strcmp(name_cstr,
"objc_msgSendSuper_stret")) {
497 RegisterInstruction(i);
498 msgSend_types[&i] = eMsgSendSuper_stret;
503 "Function name '%s' contains 'objc_msgSend' but is not handled",
518 : ModulePass(
ID), m_func_name(func_name),
519 m_checker_functions(checker_functions) {}
526 llvm::Function *function = M.getFunction(StringRef(
m_func_name));
556 raw_string_ostream oss(s);
558 M.print(oss,
nullptr);
562 LLDB_LOGF(log,
"Module after dynamic checks: \n%s", s.c_str());
571 return PMT_ModulePassManager;
#define VALID_OBJC_OBJECT_CHECK_NAME
static const char g_valid_pointer_check_text[]
#define VALID_POINTER_CHECK_NAME
static std::string PrintValue(const Value *value, bool truncate=false)
#define LLDB_LOGF(log,...)
Finds and instruments individual LLVM IR instructions.
llvm::Module & m_module
The module which is being instrumented.
virtual bool InspectInstruction(llvm::Instruction &i)
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
IntegerType * GetIntptrTy()
virtual bool InstrumentInstruction(llvm::Instruction *inst)=0
Add instrumentation to a single instruction.
std::shared_ptr< UtilityFunction > m_checker_function
The dynamic checker function for the process.
Instrumenter(llvm::Module &module, std::shared_ptr< UtilityFunction > checker_function)
Constructor.
InstVector m_to_instrument
List of instructions the inspector found.
llvm::FunctionCallee BuildPointerValidatorFunc(lldb::addr_t start_address)
Build a function pointer for a function with signature void (*)(uint8_t*) with a given address.
PointerType * GetI8PtrTy()
bool Inspect(llvm::Function &function)
Inspect a function to find instructions to instrument.
virtual ~Instrumenter()=default
std::vector< llvm::Instruction * > InstVector
bool Instrument()
Instrument all the instructions found by Inspect()
virtual bool InspectBasicBlock(llvm::BasicBlock &bb)
Scan a basic block to see if any instructions are interesting.
virtual bool InspectFunction(llvm::Function &f)
Scan a function to see if any instructions are interesting.
void RegisterInstruction(llvm::Instruction &inst)
Register a single instruction to be instrumented.
llvm::FunctionCallee BuildObjectCheckerFunc(lldb::addr_t start_address)
Build a function pointer for a function with signature void (*)(uint8_t*, uint8_t*) with a given addr...
InstVector::iterator InstIterator
std::map< llvm::Instruction *, msgSend_type > msgSend_types
bool InspectInstruction(llvm::Instruction &i) override
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
static llvm::Function * GetCalledFunction(llvm::CallInst *inst)
~ObjcObjectChecker() override=default
llvm::FunctionCallee m_objc_object_check_func
bool InstrumentInstruction(llvm::Instruction *inst) override
Add instrumentation to a single instruction.
static llvm::Function * GetFunction(llvm::Value *value)
ObjcObjectChecker(llvm::Module &module, std::shared_ptr< UtilityFunction > checker_function)
bool InstrumentInstruction(llvm::Instruction *inst) override
Add instrumentation to a single instruction.
ValidPointerChecker(llvm::Module &module, std::shared_ptr< UtilityFunction > checker_function)
llvm::FunctionCallee m_valid_pointer_check_func
bool InspectInstruction(llvm::Instruction &i) override
Determine whether a single instruction is interesting to instrument, and, if so, call RegisterInstruc...
~ValidPointerChecker() override=default
bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message) override
std::shared_ptr< UtilityFunction > m_objc_object_check
bool Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override
Install the utility functions into a process.
ClangDynamicCheckerFunctions()
Constructor.
std::shared_ptr< UtilityFunction > m_valid_pointer_check
~ClangDynamicCheckerFunctions() override
Destructor.
Encapsulates dynamic check functions used by expressions.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
Target & GetTargetRef() const
Returns a reference to the target object.
Process * GetProcessPtr() const
Returns a pointer to the process object.
~IRDynamicChecks() override
Destructor.
ClangDynamicCheckerFunctions & m_checker_functions
The checker functions for the process.
bool runOnModule(llvm::Module &M) override
Run this IR transformer on a single module.
std::string m_func_name
The name of the function to add checks to.
IRDynamicChecks(ClangDynamicCheckerFunctions &checker_functions, const char *func_name="$__lldb_expr")
Constructor.
llvm::PassManagerType getPotentialPassManagerType() const override
Returns PMT_ModulePassManager.
void assignPassManager(llvm::PMStack &PMS, llvm::PassManagerType T=llvm::PMT_ModulePassManager) override
Interface stub.
static ObjCLanguageRuntime * Get(Process &process)
virtual llvm::Expected< std::unique_ptr< UtilityFunction > > CreateObjectChecker(std::string name, ExecutionContext &exe_ctx)=0
A plug-in interface definition class for debugging a process.
A stream class that can stream formatted output to a file.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
llvm::Expected< std::unique_ptr< UtilityFunction > > CreateUtilityFunction(std::string expression, std::string name, lldb::LanguageType language, ExecutionContext &exe_ctx)
Creates and installs a UtilityFunction for the given language.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
@ eLanguageTypeC
Non-standardized C, such as K&R.