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"
36#define VALID_OBJC_OBJECT_CHECK_NAME "$__lldb_objc_object_check"
53 lang = frame->GetLanguage();
55 if (objc_language_runtime &&
57 Expected<std::unique_ptr<UtilityFunction>> checker_fn =
60 return checker_fn.takeError();
65 return Error::success();
74 message.
Printf(
"Attempted to dereference an invalid ObjC Object or send it "
75 "an unrecognized selector");
81static std::string
PrintValue(llvm::Value *V,
bool truncate =
false) {
83 raw_string_ostream rso(s);
86 s.resize(s.length() - 1);
123 std::shared_ptr<UtilityFunction> checker_function)
144 ii != last_ii; ++ii) {
188 for (llvm::BasicBlock::iterator ii = bb.begin(), last_ii = bb.end();
189 ii != last_ii; ++ii) {
205 for (llvm::Function::iterator bbi = f.begin(), last_bbi = f.end();
206 bbi != last_bbi; ++bbi) {
223 llvm::Type *param_array[2];
225 param_array[0] =
const_cast<llvm::PointerType *
>(
GetI8PtrTy());
226 param_array[1] =
const_cast<llvm::PointerType *
>(
GetI8PtrTy());
228 ArrayRef<llvm::Type *> params(param_array, 2);
230 FunctionType *fun_ty = FunctionType::get(
231 llvm::Type::getVoidTy(
m_module.getContext()), params,
true);
232 PointerType *fun_ptr_ty = PointerType::getUnqual(
m_module.getContext());
233 Constant *fun_addr_int =
234 ConstantInt::get(
GetIntptrTy(), start_address,
false);
235 return {fun_ty, ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty)};
249 m_module.getDataLayout().getPointerSizeInBits());
260 std::shared_ptr<UtilityFunction>
271 std::shared_ptr<UtilityFunction> checker_function)
289 CallInst *call_inst = dyn_cast<CallInst>(inst);
301 llvm::Value *target_object;
302 llvm::Value *selector;
309 if (call_inst->hasStructRetAttr()) {
310 target_object = call_inst->getArgOperand(1);
311 selector = call_inst->getArgOperand(2);
313 target_object = call_inst->getArgOperand(0);
314 selector = call_inst->getArgOperand(1);
318 target_object = call_inst->getArgOperand(1);
319 selector = call_inst->getArgOperand(2);
327 assert(target_object);
332 llvm::Value *arg_array[2];
334 arg_array[0] = target_object;
335 arg_array[1] = selector;
337 ArrayRef<llvm::Value *> args(arg_array, 2);
345 if (llvm::Function *function = llvm::dyn_cast<llvm::Function>(value)) {
349 if (llvm::ConstantExpr *const_expr =
350 llvm::dyn_cast<llvm::ConstantExpr>(value)) {
351 switch (const_expr->getOpcode()) {
354 case llvm::Instruction::BitCast:
369 CallInst *call_inst = dyn_cast<CallInst>(&i);
374 if (!called_function)
377 std::string name_str = called_function->getName().str();
378 const char *name_cstr = name_str.c_str();
380 LLDB_LOGF(log,
"Found call to %s: %s\n", name_cstr,
383 if (name_str.find(
"objc_msgSend") == std::string::npos)
386 if (!strcmp(name_cstr,
"objc_msgSend")) {
392 if (!strcmp(name_cstr,
"objc_msgSend_stret")) {
398 if (!strcmp(name_cstr,
"objc_msgSend_fpret")) {
404 if (!strcmp(name_cstr,
"objc_msgSendSuper")) {
410 if (!strcmp(name_cstr,
"objc_msgSendSuper_stret")) {
417 "Function name '%s' contains 'objc_msgSend' but is not handled",
440 llvm::Function *function = M.getFunction(StringRef(
m_func_name));
460 raw_string_ostream oss(s);
462 M.print(oss,
nullptr);
464 LLDB_LOGF(log,
"Module after dynamic checks: \n%s", s.c_str());
473 return PMT_ModulePassManager;
#define VALID_OBJC_OBJECT_CHECK_NAME
static std::string PrintValue(const Value *value, bool truncate=false)
#define LLDB_LOGF(log,...)
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.
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...
IntegerType * m_intptr_ty
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 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.
~ClangDynamicCheckerFunctions() override
Destructor.
DynamicCheckerFunctions(DynamicCheckerFunctionsKind kind)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame 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 bool LanguageIsObjC(lldb::LanguageType language)
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.
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.
A type-erased pair of llvm::dwarf::SourceLanguageName and version.
lldb::LanguageType AsLanguageType() const