diff options
Diffstat (limited to 'lldb/source/Plugins')
5 files changed, 93 insertions, 0 deletions
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_ |