diff options
-rw-r--r-- | lldb/include/lldb/Core/Address.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/Symbol.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Process.h | 22 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanCallFunction.h | 4 | ||||
-rw-r--r-- | lldb/include/lldb/lldb-enumerations.h | 1 | ||||
-rw-r--r-- | lldb/source/Core/Address.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Core/Module.cpp | 14 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 61 | ||||
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 13 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h | 3 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp | 69 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h | 2 | ||||
-rw-r--r-- | lldb/source/Symbol/Symbol.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanCallFunction.cpp | 4 | ||||
-rw-r--r-- | lldb/test/lang/c/strings/TestCStrings.py | 2 |
16 files changed, 196 insertions, 27 deletions
diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h index 6a97e87b87c..6bb186b6fb7 100644 --- a/lldb/include/lldb/Core/Address.h +++ b/lldb/include/lldb/Core/Address.h @@ -302,7 +302,7 @@ public: /// the address is currently not loaded. //------------------------------------------------------------------ lldb::addr_t - GetCallableLoadAddress (Target *target) const; + GetCallableLoadAddress (Target *target, bool is_indirect = false) const; //------------------------------------------------------------------ /// Get the load address as an opcode load address. diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h index 6cc72afff9f..8235a8875be 100644 --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -205,6 +205,9 @@ public: bool IsTrampoline () const; + bool + IsIndirect () const; + lldb::addr_t GetByteSize () const; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index ea163fb394f..19540ec25b9 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2894,6 +2894,28 @@ public: lldb::addr_t AllocateMemory (size_t size, uint32_t permissions, Error &error); + + //------------------------------------------------------------------ + /// Resolve dynamically loaded indirect functions. + /// + /// @param[in] address + /// The load address of the indirect function to resolve. + /// + /// @param[out] error + /// An error value in case the resolve fails. + /// + /// @return + /// The address of the resolved function. + /// LLDB_INVALID_ADDRESS if the resolution failed. + //------------------------------------------------------------------ + + virtual lldb::addr_t + ResolveIndirectFunction(const Address *address, Error &error) + { + error.SetErrorStringWithFormat("error: %s does not support indirect functions in the debug process", GetShortPluginName()); + return LLDB_INVALID_ADDRESS; + } + virtual Error GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index d3ca83b4710..f22f88df9db 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -27,7 +27,7 @@ class ThreadPlanCallFunction : public ThreadPlan // return type, otherwise just pass in an invalid ClangASTType. public: ThreadPlanCallFunction (Thread &thread, - Address &function, + const Address &function, const ClangASTType &return_type, lldb::addr_t arg, bool stop_other_threads, @@ -37,7 +37,7 @@ public: lldb::addr_t *cmd_arg = 0); ThreadPlanCallFunction (Thread &thread, - Address &function, + const Address &function, const ClangASTType &return_type, bool stop_other_threads, bool unwind_on_error, diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index b3feb8e65f2..fb246ec29d1 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -455,6 +455,7 @@ namespace lldb { eSymbolTypeInvalid = 0, eSymbolTypeAbsolute, eSymbolTypeCode, + eSymbolTypeResolver, eSymbolTypeData, eSymbolTypeTrampoline, eSymbolTypeRuntime, diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp index 66093bcc2e1..abde4ac42c9 100644 --- a/lldb/source/Core/Address.cpp +++ b/lldb/source/Core/Address.cpp @@ -311,8 +311,15 @@ Address::GetLoadAddress (Target *target) const } addr_t -Address::GetCallableLoadAddress (Target *target) const +Address::GetCallableLoadAddress (Target *target, bool is_indirect) const { + if (is_indirect && target) { + ProcessSP processSP = target->GetProcessSP(); + Error error; + if (processSP.get()) + return processSP->ResolveIndirectFunction(this, error); + } + addr_t code_addr = GetLoadAddress (target); if (target) diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 953a81bfdbe..2341144132b 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -606,7 +606,7 @@ Module::FindFunctions (const ConstString &name, if (symtab) { std::vector<uint32_t> symbol_indexes; - symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); + symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const size_t num_matches = symbol_indexes.size(); if (num_matches) { @@ -615,7 +615,10 @@ Module::FindFunctions (const ConstString &name, for (size_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); - sc_list.AppendIfUnique (sc, merge_symbol_into_function); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } @@ -649,7 +652,7 @@ Module::FindFunctions (const RegularExpression& regex, if (symtab) { std::vector<uint32_t> symbol_indexes; - symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); + symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const size_t num_matches = symbol_indexes.size(); if (num_matches) { @@ -658,7 +661,10 @@ Module::FindFunctions (const RegularExpression& regex, for (size_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); - sc_list.AppendIfUnique (sc, merge_symbol_into_function); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index db1ef1684dd..6bcab761143 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -696,11 +696,32 @@ FindCodeSymbolInContext SymbolContextList &sc_list ) { + SymbolContextList temp_sc_list; if (sym_ctx.module_sp) - sym_ctx.module_sp->FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list); + sym_ctx.module_sp->FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list); - if (!sc_list.GetSize()) - sym_ctx.target_sp->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list); + if (!sc_list.GetSize() && sym_ctx.target_sp) + sym_ctx.target_sp->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, temp_sc_list); + + unsigned temp_sc_list_size = temp_sc_list.GetSize(); + for (unsigned i = 0; i < temp_sc_list_size; i++) + { + SymbolContext sym_ctx; + temp_sc_list.GetContextAtIndex(i, sym_ctx); + if (sym_ctx.symbol) + { + switch (sym_ctx.symbol->GetType()) + { + case eSymbolTypeCode: + case eSymbolTypeResolver: + sc_list.Append(sym_ctx); + break; + + default: + break; + } + } + } } bool @@ -724,7 +745,7 @@ ClangExpressionDeclMap::GetFunctionAddress SymbolContextList sc_list; FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, sc_list); - + if (!sc_list.GetSize()) { // We occasionally get debug information in which a const function is reported @@ -746,23 +767,25 @@ ClangExpressionDeclMap::GetFunctionAddress if (!sc_list.GetSize()) return false; - + SymbolContext sym_ctx; sc_list.GetContextAtIndex(0, sym_ctx); - + const Address *func_so_addr = NULL; - + bool is_indirect_function = false; + if (sym_ctx.function) func_so_addr = &sym_ctx.function->GetAddressRange().GetBaseAddress(); - else if (sym_ctx.symbol) + else if (sym_ctx.symbol) { func_so_addr = &sym_ctx.symbol->GetAddress(); - else + is_indirect_function = sym_ctx.symbol->IsIndirect(); + } else return false; - + if (!func_so_addr || !func_so_addr->IsValid()) return false; - - func_addr = func_so_addr->GetCallableLoadAddress (target); + + func_addr = func_so_addr->GetCallableLoadAddress (target, is_indirect_function); return true; } @@ -795,7 +818,11 @@ ClangExpressionDeclMap::GetSymbolAddress (Target &target, Process *process, cons case eSymbolTypeTrampoline: symbol_load_addr = sym_address->GetCallableLoadAddress (&target); break; - + + case eSymbolTypeResolver: + symbol_load_addr = sym_address->GetCallableLoadAddress (&target, true); + break; + case eSymbolTypeData: case eSymbolTypeRuntime: case eSymbolTypeVariable: @@ -2467,6 +2494,7 @@ ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, case eSymbolTypeCompiler: case eSymbolTypeInstrumentation: case eSymbolTypeUndefined: + case eSymbolTypeResolver: break; } } @@ -3540,7 +3568,9 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, // only valid for Functions, not for Symbols void *fun_opaque_type = NULL; ASTContext *fun_ast_context = NULL; - + + bool is_indirect_function = false; + if (fun) { Type *fun_type = fun->GetType(); @@ -3586,6 +3616,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, { fun_address = &symbol->GetAddress(); fun_decl = context.AddGenericFunDecl(); + is_indirect_function = symbol->IsIndirect(); } else { @@ -3596,7 +3627,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); - lldb::addr_t load_addr = fun_address->GetCallableLoadAddress(target); + lldb::addr_t load_addr = fun_address->GetCallableLoadAddress(target, is_indirect_function); fun_location->SetValueType(Value::eValueTypeLoadAddress); fun_location->GetScalar() = load_addr; diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 2cee5c01da9..42bfefe8d62 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -784,6 +784,12 @@ ParseSymbols(Symtab *symtab, // STB_LOCAL symbols for the file, if it is present. symbol_type = eSymbolTypeObjectFile; break; + + case STT_GNU_IFUNC: + // The symbol is associated with an indirect function. The actual + // function will be resolved if it is referenced. + symbol_type = eSymbolTypeResolver; + break; } } diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index c65f95c883d..0a741bca1de 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -483,6 +483,19 @@ ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr) return error; } +addr_t +ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error) +{ + addr_t function_addr = LLDB_INVALID_ADDRESS; + if (address == NULL) { + error.SetErrorStringWithFormat("unable to determine direct function call for NULL address"); + } else if (!InferiorCall(this, address, function_addr)) { + function_addr = LLDB_INVALID_ADDRESS; + error.SetErrorStringWithFormat("unable to determine direct function call for indirect function with address %x", address); + } + return function_addr; +} + size_t ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site) { diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h index d12e063c312..068686df99f 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.h @@ -96,6 +96,9 @@ public: virtual lldb_private::Error DoDeallocateMemory(lldb::addr_t ptr); + virtual lldb::addr_t + ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error); + virtual size_t GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site); diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index 905ab251446..ba1d3b6eb95 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "InferiorCallPOSIX.h" +#include "lldb/Core/Address.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/ClangASTContext.h" @@ -119,6 +120,11 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr, if (allocated_addr == UINT32_MAX) return false; } + else if (process->GetAddressByteSize() == 8) + { + if (allocated_addr == UINT64_MAX) + return false; + } return true; } } @@ -203,3 +209,66 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr, return false; } + +bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) { + Thread *thread = process->GetThreadList().GetSelectedThread().get(); + if (thread == NULL || address == NULL) + return false; + + const bool stop_other_threads = true; + const bool unwind_on_error = true; + const bool ignore_breakpoints = true; + const bool try_all_threads = true; + const uint32_t timeout_usec = 500000; + + ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); + lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); + ThreadPlanCallFunction *call_function_thread_plan + = new ThreadPlanCallFunction (*thread, + *address, + ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type), + stop_other_threads, + unwind_on_error, + ignore_breakpoints); + lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan); + if (call_plan_sp) + { + StreamFile error_strm; + // This plan is a utility plan, so set it to discard itself when done. + call_plan_sp->SetIsMasterPlan (true); + call_plan_sp->SetOkayToDiscard(true); + + StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + if (frame) + { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext (exe_ctx); + ExecutionResults result = process->RunThreadPlan (exe_ctx, + call_plan_sp, + stop_other_threads, + try_all_threads, + unwind_on_error, + ignore_breakpoints, + timeout_usec, + error_strm); + if (result == eExecutionCompleted) + { + returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (process->GetAddressByteSize() == 4) + { + if (returned_func == UINT32_MAX) + return false; + } + else if (process->GetAddressByteSize() == 8) + { + if (returned_func == UINT64_MAX) + return false; + } + return true; + } + } + } + + return false; +} diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h index a85db72ec03..d8b6d0ed57f 100644 --- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h +++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.h @@ -36,6 +36,8 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr, bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length); +bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func); + } // namespace lldb_private #endif // lldb_InferiorCallPOSIX_h_ diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp index db4ceb24c80..0fe0ceb57d7 100644 --- a/lldb/source/Symbol/Symbol.cpp +++ b/lldb/source/Symbol/Symbol.cpp @@ -184,6 +184,12 @@ Symbol::IsTrampoline () const return m_type == eSymbolTypeTrampoline; } +bool +Symbol::IsIndirect () const +{ + return m_type == eSymbolTypeResolver; +} + void Symbol::GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const { @@ -273,7 +279,7 @@ Symbol::Dump(Stream *s, Target *target, uint32_t index) const uint32_t Symbol::GetPrologueByteSize () { - if (m_type == eSymbolTypeCode) + if (m_type == eSymbolTypeCode || m_type == eSymbolTypeResolver) { if (!m_type_data_resolved) { diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index c48f4fb7fe9..9247bcee6a2 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -119,7 +119,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread, } ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, - Address &function, + const Address &function, const ClangASTType &return_type, addr_t arg, bool stop_other_threads, @@ -182,7 +182,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, - Address &function, + const Address &function, const ClangASTType &return_type, bool stop_other_threads, bool unwind_on_error, diff --git a/lldb/test/lang/c/strings/TestCStrings.py b/lldb/test/lang/c/strings/TestCStrings.py index 0a1a826674a..481f8b01cfe 100644 --- a/lldb/test/lang/c/strings/TestCStrings.py +++ b/lldb/test/lang/c/strings/TestCStrings.py @@ -16,7 +16,6 @@ class CStringsTestCase(TestBase): self.buildDsym() self.static_method_commands() - @expectedFailureLinux # bugzilla 14437 @dwarf_test def test_with_dwarf_and_run_command(self): """Tests that C strings work as expected in expressions""" @@ -43,6 +42,7 @@ class CStringsTestCase(TestBase): self.expect("expression -- z[2]", startstr = "(const char) $1 = 'x'") + # On Linux, the expression below will test GNU indirect function calls. self.expect("expression -- (int)strlen(\"hello\")", startstr = "(int) $2 = 5") |