diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 3 | ||||
-rw-r--r-- | lldb/source/Expression/ASTResultSynthesizer.cpp | 21 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionParser.cpp | 22 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionVariable.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 15 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUtilityFunction.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Expression/IRDynamicChecks.cpp | 220 | ||||
-rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 46 |
9 files changed, 306 insertions, 47 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 67745ee7097..61ada69e48f 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -219,7 +219,7 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream return false; } - ClangExpressionVariable *expr_result; + ClangExpressionVariable *expr_result = NULL; if (!user_expression.Execute (error_stream, m_exe_ctx, expr_result)) { @@ -249,7 +249,6 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream } else { - error_stream.Printf ("Expression produced no result\n"); if (result) result->SetStatus (eReturnStatusSuccessFinishNoResult); } diff --git a/lldb/source/Expression/ASTResultSynthesizer.cpp b/lldb/source/Expression/ASTResultSynthesizer.cpp index b3790f2cae5..8838fddf8ff 100644 --- a/lldb/source/Expression/ASTResultSynthesizer.cpp +++ b/lldb/source/Expression/ASTResultSynthesizer.cpp @@ -113,6 +113,18 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl) if (!function_decl) return false; + if (log) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf("Function AST before transforming:\n%s", s.c_str()); + } + Stmt *function_body = function_decl->getBody(); CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body); @@ -125,6 +137,15 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl) Stmt **last_stmt_ptr = compound_stmt->body_end() - 1; Stmt *last_stmt = *last_stmt_ptr; + while (dyn_cast<NullStmt>(last_stmt)) + { + if (last_stmt_ptr != compound_stmt->body_begin()) + { + last_stmt_ptr--; + last_stmt = *last_stmt_ptr; + } + } + Expr *last_expr = dyn_cast<Expr>(last_stmt); if (!last_expr) diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index ef0be1e8849..37d13a98a52 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -401,6 +401,16 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize, return LLDB_INVALID_ADDRESS; } + if (!m_struct_size) + { + if (log) + log->PutCString("Not bothering to allocate a struct because no arguments are needed"); + + m_allocated_area = NULL; + + return true; + } + const SymbolContext &sym_ctx(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything)); if (!dematerialize) diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index 1bc8866975b..f8b71edbe9c 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -403,7 +403,10 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, "")); - IRForTarget ir_for_target(decl_map, target_machine->getTargetData(), m_expr.FunctionName()); + IRForTarget ir_for_target(decl_map, + target_machine->getTargetData(), + m_expr.NeedsVariableResolution(), + m_expr.FunctionName()); if (!ir_for_target.runOnModule(*module)) { @@ -412,14 +415,17 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, return err; } - IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName()); - - if (!ir_dynamic_checks.runOnModule(*module)) + if (m_expr.NeedsValidation()) { - err.SetErrorToGenericError(); - err.SetErrorString("Couldn't add dynamic checks to the expression"); - return err; - } + IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName()); + + if (!ir_dynamic_checks.runOnModule(*module)) + { + err.SetErrorToGenericError(); + err.SetErrorString("Couldn't add dynamic checks to the expression"); + return err; + } + } } m_jit_mm = new RecordingMemoryManager(); diff --git a/lldb/source/Expression/ClangExpressionVariable.cpp b/lldb/source/Expression/ClangExpressionVariable.cpp index d576578b5ef..3931cfb2e74 100644 --- a/lldb/source/Expression/ClangExpressionVariable.cpp +++ b/lldb/source/Expression/ClangExpressionVariable.cpp @@ -18,6 +18,8 @@ #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Value.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" using namespace lldb_private; using namespace clang; @@ -79,6 +81,12 @@ ClangExpressionVariable::Print (Stream &output_stream, DataExtractor data; Error expr_error = val.GetValueAsData (&exe_ctx, ast_context, data, 0); + + // Set byte order and pointer size to TARGET byte order and pointer size! + + data.SetByteOrder(exe_ctx.process->GetByteOrder()); + data.SetAddressByteSize(exe_ctx.process->GetAddressByteSize()); + if (!expr_error.Success ()) { err.SetErrorToGenericError (); diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index d8841d3b3e8..4e49c4875a2 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -196,13 +196,16 @@ ClangUserExpression::Execute (Stream &error_stream, Error dump_error; - if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error)) + if (struct_address) { - log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error")); - } - else - { - log->Printf("Structure contents:\n%s", args.GetData()); + if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error)) + { + log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error")); + } + else + { + log->Printf("Structure contents:\n%s", args.GetData()); + } } } diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp index 17ba7dba331..310cac9d571 100644 --- a/lldb/source/Expression/ClangUtilityFunction.cpp +++ b/lldb/source/Expression/ClangUtilityFunction.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Stream.h" +#include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionParser.h" #include "lldb/Expression/ClangUtilityFunction.h" #include "lldb/Host/Host.h" @@ -93,6 +94,8 @@ ClangUtilityFunction::Install (Stream &error_stream, ////////////////////////// // Parse the expression // + + m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx)); ClangExpressionParser parser(target_triple.GetCString(), *this); @@ -101,6 +104,9 @@ ClangUtilityFunction::Install (Stream &error_stream, if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + + m_expr_decl_map.reset(); + return false; } @@ -110,6 +116,8 @@ ClangUtilityFunction::Install (Stream &error_stream, Error jit_error = parser.MakeJIT (m_jit_begin, m_jit_end, exe_ctx); + m_expr_decl_map.reset(); + if (jit_error.Success()) { return true; diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp index 0f98123e471..b5a706d67ec 100644 --- a/lldb/source/Expression/IRDynamicChecks.cpp +++ b/lldb/source/Expression/IRDynamicChecks.cpp @@ -8,9 +8,12 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/IRDynamicChecks.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" +#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/StackFrame.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Function.h" @@ -23,6 +26,9 @@ using namespace lldb_private; static char ID; +static const char valid_pointer_check_name[] = +"___clang_valid_pointer_check"; + static const char valid_pointer_check_text[] = "extern \"C\" void " "___clang_valid_pointer_check (unsigned char *ptr)" @@ -30,13 +36,57 @@ static const char valid_pointer_check_text[] = "unsigned char val = *ptr;" "}"; -static const char valid_pointer_check_name[] = - "___clang_valid_pointer_check"; +static const char objc_object_check_name[] = + "___clang_objc_object_check"; + +static bool FunctionExists(const SymbolContext &sym_ctx, const char *name) +{ + ConstString name_cs(name); + + SymbolContextList sym_ctxs; + + sym_ctx.FindFunctionsByName(name_cs, false, sym_ctxs); + + return (sym_ctxs.GetSize() != 0); +} + +static const char *objc_object_check_text(ExecutionContext &exe_ctx) +{ + std::string ret; + + if (!exe_ctx.frame) + return "extern \"C\" void ___clang_objc_object_check (unsigned char *obj) { }"; + + const SymbolContext &sym_ctx(exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything)); + + if (FunctionExists(sym_ctx, "gdb_object_getClass")) + { + return "extern \"C\" void " + "___clang_objc_object_check(uint8_t *obj)" + "{" + "" + "}"; + } + else if (FunctionExists(sym_ctx, "gdb_class_getClass")) + { + return "extern \"C\" void " + "___clang_objc_object_check(uint8_t *obj)" + "{" + "" + "}"; + } + else + { + return "extern \"C\" void " + "___clang_objc_object_check(uint8_t *obj)" + "{" + "" + "}"; + } +} DynamicCheckerFunctions::DynamicCheckerFunctions () { - m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text, - valid_pointer_check_name)); } DynamicCheckerFunctions::~DynamicCheckerFunctions () @@ -47,6 +97,9 @@ bool DynamicCheckerFunctions::Install(Stream &error_stream, ExecutionContext &exe_ctx) { + m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text, + valid_pointer_check_name)); + if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) return false; @@ -104,7 +157,8 @@ public: Instrumenter (llvm::Module &module, DynamicCheckerFunctions &checker_functions) : m_module(module), - m_checker_functions(checker_functions) + m_checker_functions(checker_functions), + m_i8ptr_ty(NULL) { } @@ -222,12 +276,42 @@ protected: return true; } + //------------------------------------------------------------------ + /// Build a function pointer for a function with signature + /// void (*)(uint8_t*) with a given address + /// + /// @param[in] start_address + /// The address of the function. + /// + /// @return + /// The function pointer, for use in a CallInst. + //------------------------------------------------------------------ + llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address) + { + std::vector<const llvm::Type*> params; + + const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), + (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32); + + if (!m_i8ptr_ty) + m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); + + params.push_back(m_i8ptr_ty); + + FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); + PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); + Constant *fun_addr_int = ConstantInt::get(intptr_ty, start_address, false); + return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); + } + typedef std::vector <llvm::Instruction *> InstVector; typedef InstVector::iterator InstIterator; InstVector m_to_instrument; ///< List of instructions the inspector found llvm::Module &m_module; ///< The module which is being instrumented DynamicCheckerFunctions &m_checker_functions; ///< The dynamic checker functions for the process + + const PointerType *m_i8ptr_ty; }; class ValidPointerChecker : public Instrumenter @@ -249,21 +333,7 @@ private: PrintValue(inst).c_str()); if (!m_valid_pointer_check_func) - { - std::vector<const llvm::Type*> params; - - const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(), - (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32); - - m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext()); - - params.push_back(m_i8ptr_ty); - - FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true); - PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty); - Constant *fun_addr_int = ConstantInt::get(intptr_ty, m_checker_functions.m_valid_pointer_check->StartAddress(), false); - m_valid_pointer_check_func = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); - } + m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress()); llvm::Value *dereferenced_ptr; @@ -305,6 +375,104 @@ private: } llvm::Value *m_valid_pointer_check_func; +}; + +class ObjcObjectChecker : public Instrumenter +{ +public: + ObjcObjectChecker(llvm::Module &module, + DynamicCheckerFunctions &checker_functions) : + Instrumenter(module, checker_functions), + m_objc_object_check_func(NULL) + { + } +private: + bool InstrumentInstruction(llvm::Instruction *inst) + { + CallInst *call_inst = dyn_cast<CallInst>(inst); + + if (!call_inst) + return false; // this really should be true, because otherwise InspectInstruction wouldn't have registered it + + if (!m_objc_object_check_func) + m_objc_object_check_func = BuildPointerValidatorFunc(m_checker_functions.m_objc_object_check->StartAddress()); + + llvm::Value *target_object; + + // id objc_msgSend(id theReceiver, SEL theSelector, ...) + + target_object = call_inst->getArgOperand(0); + + // Insert an instruction to cast the receiver id to int8_t* + + BitCastInst *bit_cast = new BitCastInst(target_object, + m_i8ptr_ty, + "", + inst); + + // Insert an instruction to call the helper with the result + + SmallVector <llvm::Value*, 1> args; + args.push_back(bit_cast); + + CallInst::Create(m_objc_object_check_func, + args.begin(), + args.end(), + "", + inst); + + return true; + } + + bool InspectInstruction(llvm::Instruction &i) + { + lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + CallInst *call_inst = dyn_cast<CallInst>(&i); + + if (call_inst) + { + // This metadata is set by IRForTarget::MaybeHandleCall(). + + MDNode *metadata = call_inst->getMetadata("lldb.call.realName"); + + if (!metadata) + return true; + + if (metadata->getNumOperands() != 1) + { + if (log) + log->Printf("Function call metadata has %d operands for [%p] %s", metadata->getNumOperands(), call_inst, PrintValue(call_inst).c_str()); + return false; + } + + ConstantArray *real_name = dyn_cast<ConstantArray>(metadata->getOperand(0)); + + if (!real_name) + { + if (log) + log->Printf("Function call metadata is not a ConstantArray for [%p] %s", call_inst, PrintValue(call_inst).c_str()); + return false; + } + + if (!real_name->isString()) + { + if (log) + log->Printf("Function call metadata is not a string for [%p] %s", call_inst, PrintValue(call_inst).c_str()); + return false; + } + + if (log) + log->Printf("Found call to %s: %s\n", real_name->getAsString().c_str(), PrintValue(call_inst).c_str()); + + if (real_name->getAsString().find("objc_msgSend") != std::string::npos) + RegisterInstruction(i); + } + + return true; + } + + llvm::Value *m_objc_object_check_func; const PointerType *m_i8ptr_ty; }; @@ -343,6 +511,16 @@ IRDynamicChecks::runOnModule(llvm::Module &M) if (!vpc.Instrument()) return false; + /* + ObjcObjectChecker ooc(M, m_checker_functions); + + if (!ooc.Inspect(*function)) + return false; + + if (!ooc.Instrument()) + return false; + */ + if (log) { std::string s; diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index e220b16f00c..f368b8dc027 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -32,12 +32,14 @@ static char ID; IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, const TargetData *target_data, + bool resolve_vars, const char *func_name) : ModulePass(&ID), m_decl_map(decl_map), m_target_data(target_data), m_sel_registerName(NULL), - m_func_name(func_name) + m_func_name(func_name), + m_resolve_vars(resolve_vars) { } @@ -65,7 +67,10 @@ IRForTarget::createResultVariable(llvm::Module &M, { lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); - // Find the result variable + if (!m_resolve_vars) + return true; + + // Find the result variable. If it doesn't exist, we can give up right here. Value *result_value = M.getNamedValue("___clang_expr_result"); @@ -73,9 +78,10 @@ IRForTarget::createResultVariable(llvm::Module &M, { if (log) log->PutCString("Couldn't find result variable"); - return false; + + return true; } - + if (log) log->Printf("Found result in the IR: %s", PrintValue(result_value, false).c_str()); @@ -429,6 +435,9 @@ bool IRForTarget::rewritePersistentAllocs(llvm::Module &M, llvm::BasicBlock &BB) { + if (!m_resolve_vars) + return true; + lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); BasicBlock::iterator ii; @@ -649,6 +658,17 @@ IRForTarget::MaybeHandleCall(Module &M, C->setCalledFunction(fun_addr_ptr); + ConstantArray *func_name = (ConstantArray*)ConstantArray::get(M.getContext(), fun->getName()); + + Value *values[1]; + values[0] = func_name; + MDNode *func_metadata = MDNode::get(M.getContext(), values, 1); + + C->setMetadata("lldb.call.realName", func_metadata); + + if (log) + log->Printf("Set metadata for %p [%d, %s]", C, func_name->isString(), func_name->getAsString().c_str()); + return true; } @@ -667,13 +687,16 @@ IRForTarget::resolveExternals(Module &M, BasicBlock &BB) { Instruction &inst = *ii; - if (LoadInst *load = dyn_cast<LoadInst>(&inst)) - if (!MaybeHandleVariable(M, load->getPointerOperand(), false)) - return false; + if (m_resolve_vars) + { + if (LoadInst *load = dyn_cast<LoadInst>(&inst)) + if (!MaybeHandleVariable(M, load->getPointerOperand(), false)) + return false; - if (StoreInst *store = dyn_cast<StoreInst>(&inst)) - if (!MaybeHandleVariable(M, store->getPointerOperand(), true)) - return false; + if (StoreInst *store = dyn_cast<StoreInst>(&inst)) + if (!MaybeHandleVariable(M, store->getPointerOperand(), true)) + return false; + } if (CallInst *call = dyn_cast<CallInst>(&inst)) if (!MaybeHandleCall(M, call)) @@ -886,6 +909,9 @@ UnfoldConstant(Constant *C, Value *new_value, Instruction *first_entry_instructi bool IRForTarget::replaceVariables(Module &M, Function &F) { + if (!m_resolve_vars) + return true; + lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); m_decl_map->DoStructLayout(); |