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"
52 Expected<std::unique_ptr<UtilityFunction>> utility_fn =
57 return utility_fn.takeError();
64 if (objc_language_runtime) {
65 Expected<std::unique_ptr<UtilityFunction>> checker_fn =
68 return checker_fn.takeError();
73 return Error::success();
82 message.
Printf(
"Attempted to dereference an invalid pointer.");
86 message.
Printf(
"Attempted to dereference an invalid ObjC Object or send it "
87 "an unrecognized selector");
93static std::string
PrintValue(llvm::Value *V,
bool truncate =
false) {
95 raw_string_ostream rso(s);
99 s.resize(s.length() - 1);
136 std::shared_ptr<UtilityFunction> checker_function)
137 : m_module(module), m_checker_function(checker_function) {}
148 bool Inspect(llvm::Function &function) {
return InspectFunction(function); }
156 last_ii = m_to_instrument.end();
157 ii != last_ii; ++ii) {
158 if (!InstrumentInstruction(*ii))
180 m_to_instrument.push_back(&inst);
201 for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
202 ii != last_ii; ++ii) {
203 if (!InspectInstruction(*ii))
218 for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
219 bbi != last_bbi; ++bbi) {
220 if (!InspectBasicBlock(*bbi))
236 llvm::Type *param_array[1];
238 param_array[0] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
240 ArrayRef<llvm::Type *> params(param_array, 1);
242 FunctionType *fun_ty = FunctionType::get(
243 llvm::Type::getVoidTy(m_module.getContext()), params,
true);
244 PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
245 Constant *fun_addr_int =
246 ConstantInt::get(GetIntptrTy(), start_address,
false);
247 return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
259 llvm::Type *param_array[2];
261 param_array[0] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
262 param_array[1] =
const_cast<llvm::PointerType *
>(GetI8PtrTy());
264 ArrayRef<llvm::Type *> params(param_array, 2);
266 FunctionType *fun_ty = FunctionType::get(
267 llvm::Type::getVoidTy(m_module.getContext()), params,
true);
268 PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
269 Constant *fun_addr_int =
270 ConstantInt::get(GetIntptrTy(), start_address,
false);
271 return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
276 m_i8ptr_ty = llvm::PointerType::getUnqual(m_module.getContext());
283 m_intptr_ty = llvm::Type::getIntNTy(
284 m_module.getContext(),
285 m_module.getDataLayout().getPointerSizeInBits());
296 std::shared_ptr<UtilityFunction>
300 PointerType *m_i8ptr_ty =
nullptr;
301 IntegerType *m_intptr_ty =
nullptr;
307 std::shared_ptr<UtilityFunction> checker_function)
309 m_valid_pointer_check_func(nullptr) {}
317 LLDB_LOGF(log,
"Instrumenting load/store instruction: %s\n",
320 if (!m_valid_pointer_check_func)
321 m_valid_pointer_check_func =
322 BuildPointerValidatorFunc(m_checker_function->StartAddress());
324 llvm::Value *dereferenced_ptr =
nullptr;
326 if (llvm::LoadInst *li = dyn_cast<llvm::LoadInst>(inst))
327 dereferenced_ptr = li->getPointerOperand();
328 else if (llvm::StoreInst *si = dyn_cast<llvm::StoreInst>(inst))
329 dereferenced_ptr = si->getPointerOperand();
334 CallInst::Create(m_valid_pointer_check_func, dereferenced_ptr,
"", inst);
340 if (isa<llvm::LoadInst>(&i) || isa<llvm::StoreInst>(&i))
341 RegisterInstruction(i);
353 std::shared_ptr<UtilityFunction> checker_function)
355 m_objc_object_check_func(nullptr) {}
371 CallInst *call_inst = dyn_cast<CallInst>(inst);
377 if (!m_objc_object_check_func)
378 m_objc_object_check_func =
379 BuildObjectCheckerFunc(m_checker_function->StartAddress());
383 llvm::Value *target_object;
384 llvm::Value *selector;
386 switch (msgSend_types[inst]) {
391 if (call_inst->hasStructRetAttr()) {
392 target_object = call_inst->getArgOperand(1);
393 selector = call_inst->getArgOperand(2);
395 target_object = call_inst->getArgOperand(0);
396 selector = call_inst->getArgOperand(1);
400 target_object = call_inst->getArgOperand(1);
401 selector = call_inst->getArgOperand(2);
404 case eMsgSendSuper_stret:
409 assert(target_object);
414 llvm::Value *arg_array[2];
416 arg_array[0] = target_object;
417 arg_array[1] = selector;
419 ArrayRef<llvm::Value *> args(arg_array, 2);
421 CallInst::Create(m_objc_object_check_func, args,
"", inst);
427 if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
431 if (llvm::ConstantExpr *const_expr =
432 llvm::dyn_cast<llvm::ConstantExpr>(value)) {
433 switch (const_expr->getOpcode()) {
436 case llvm::Instruction::BitCast:
437 return GetFunction(const_expr->getOperand(0));
445 return GetFunction(inst->getCalledOperand());
451 CallInst *call_inst = dyn_cast<CallInst>(&i);
454 const llvm::Function *called_function = GetCalledFunction(call_inst);
456 if (!called_function)
459 std::string name_str = called_function->getName().str();
460 const char *name_cstr = name_str.c_str();
462 LLDB_LOGF(log,
"Found call to %s: %s\n", name_cstr,
465 if (name_str.find(
"objc_msgSend") == std::string::npos)
468 if (!strcmp(name_cstr,
"objc_msgSend")) {
469 RegisterInstruction(i);
470 msgSend_types[&i] = eMsgSend;
474 if (!strcmp(name_cstr,
"objc_msgSend_stret")) {
475 RegisterInstruction(i);
476 msgSend_types[&i] = eMsgSend_stret;
480 if (!strcmp(name_cstr,
"objc_msgSend_fpret")) {
481 RegisterInstruction(i);
482 msgSend_types[&i] = eMsgSend_fpret;
486 if (!strcmp(name_cstr,
"objc_msgSendSuper")) {
487 RegisterInstruction(i);
488 msgSend_types[&i] = eMsgSendSuper;
492 if (!strcmp(name_cstr,
"objc_msgSendSuper_stret")) {
493 RegisterInstruction(i);
494 msgSend_types[&i] = eMsgSendSuper_stret;
499 "Function name '%s' contains 'objc_msgSend' but is not handled",
514 : ModulePass(
ID), m_func_name(func_name),
515 m_checker_functions(checker_functions) {}
522 llvm::Function *function = M.getFunction(StringRef(
m_func_name));
552 raw_string_ostream oss(s);
554 M.print(oss,
nullptr);
558 LLDB_LOGF(log,
"Module after dynamic checks: \n%s", s.c_str());
567 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
llvm::Error 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.