diff options
Diffstat (limited to 'lldb')
12 files changed, 417 insertions, 107 deletions
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h index 1b744a7214d..a493fbc4657 100644 --- a/lldb/include/lldb/Target/ABI.h +++ b/lldb/include/lldb/Target/ABI.h @@ -34,10 +34,13 @@ public: lldb::addr_t sp, lldb::addr_t functionAddress, lldb::addr_t returnAddress, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const = 0; - + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL) const = 0; + virtual bool GetArgumentValues (Thread &thread, ValueList &values) const = 0; diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index 8ce3fa8e4ab..127e17a9a52 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -30,7 +30,18 @@ public: bool discard_on_error = true, lldb::addr_t *this_arg = 0, lldb::addr_t *cmd_arg = 0); - + + ThreadPlanCallFunction (Thread &thread, + Address &function, + bool stop_other_threads, + bool discard_on_error, + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL); + virtual ~ThreadPlanCallFunction (); @@ -106,9 +117,7 @@ private: bool m_stop_other_threads; Address m_function_addr; Address m_start_addr; - lldb::addr_t m_arg_addr; lldb::addr_t m_function_sp; - ValueList *m_args; Process &m_process; Thread &m_thread; Thread::RegisterCheckpoint m_register_backup; diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index ce9a9c3067d..074c31666fd 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -65,9 +65,12 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, addr_t sp, addr_t function_addr, addr_t return_addr, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const + addr_t *arg1_ptr, + addr_t *arg2_ptr, + addr_t *arg3_ptr, + addr_t *arg4_ptr, + addr_t *arg5_ptr, + addr_t *arg6_ptr) const { RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -84,25 +87,41 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, reg_value.SetUInt32(*arg1_ptr); if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r0"), reg_value)) return false; - } - - if (arg2_ptr) - { - assert (arg1_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) - reg_value.SetUInt32(*arg2_ptr); - if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value)) - return false; - } - - if (arg3_ptr) - { - assert (arg1_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) - assert (arg2_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) + if (arg2_ptr) + { + reg_value.SetUInt32(*arg2_ptr); + if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value)) + return false; - reg_value.SetUInt32(*arg3_ptr); - if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r2"), reg_value)) - return false; + if (arg3_ptr) + { + reg_value.SetUInt32(*arg3_ptr); + if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r2"), reg_value)) + return false; + if (arg4_ptr) + { + reg_value.SetUInt32(*arg4_ptr); + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3"); + if (!reg_ctx->WriteRegister (reg_info, reg_value)) + return false; + if (arg5_ptr) + { + reg_value.SetUInt32(*arg5_ptr); + sp -= 4; + if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp, reg_info->byte_size, reg_value).Fail()) + return false; + if (arg6_ptr) + { + reg_value.SetUInt32(*arg6_ptr); + sp -= 4; + if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp, reg_info->byte_size, reg_value).Fail()) + return false; + } + } + } + } + } } // Set "lr" to the return address into "lr" diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index d7a2f3ee66e..ffa2170c6a1 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -30,9 +30,12 @@ public: lldb::addr_t sp, lldb::addr_t func_addr, lldb::addr_t returnAddress, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const; + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL) const; virtual bool GetArgumentValues (lldb_private::Thread &thread, diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 609618bcf31..0217f2fd197 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -57,15 +57,15 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch) bool ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t return_addr, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const -// lldb::addr_t arg, -// lldb::addr_t *this_arg, -// lldb::addr_t *cmd_arg) const + addr_t sp, + addr_t func_addr, + addr_t return_addr, + addr_t *arg1_ptr, + addr_t *arg2_ptr, + addr_t *arg3_ptr, + addr_t *arg4_ptr, + addr_t *arg5_ptr, + addr_t *arg6_ptr) const { RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -85,12 +85,30 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, RegisterValue reg_value; // Write any arguments onto the stack - if (arg1_ptr && arg2_ptr && arg3_ptr) - sp -= 12; - else if (arg1_ptr && arg2_ptr) - sp -= 8; - else if (arg1_ptr) + if (arg1_ptr) + { sp -= 4; + if (arg2_ptr) + { + sp -= 4; + if (arg3_ptr) + { + sp -= 4; + if (arg4_ptr) + { + sp -= 4; + if (arg5_ptr) + { + sp -= 4; + if (arg6_ptr) + { + sp -= 4; + } + } + } + } + } + } // Align the SP sp &= ~(0xfull); // 16-byte alignment @@ -107,7 +125,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, if (arg2_ptr) { - assert (arg1_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) reg_value.SetUInt32(*arg2_ptr); // The register info used to write memory just needs to have the correct // size of a 32 bit register, the actual register it pertains to is not @@ -121,8 +138,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, if (arg3_ptr) { - assert (arg1_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) - assert (arg2_ptr != NULL); // Remove this after we know the assertion isn't firing (5/11/2011) reg_value.SetUInt32(*arg3_ptr); // The register info used to write memory just needs to have the correct // size of a 32 bit register, the actual register it pertains to is not @@ -133,6 +148,46 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, reg_value); if (error.Fail()) return false; + + if (arg4_ptr) + { + reg_value.SetUInt32(*arg4_ptr); + // The register info used to write memory just needs to have the correct + // size of a 32 bit register, the actual register it pertains to is not + // important, just the size needs to be correct. Here we use "eax"... + error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, + sp + 12, + reg_info_32->byte_size, + reg_value); + if (error.Fail()) + return false; + if (arg5_ptr) + { + reg_value.SetUInt32(*arg5_ptr); + // The register info used to write memory just needs to have the correct + // size of a 32 bit register, the actual register it pertains to is not + // important, just the size needs to be correct. Here we use "eax"... + error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, + sp + 16, + reg_info_32->byte_size, + reg_value); + if (error.Fail()) + return false; + if (arg6_ptr) + { + reg_value.SetUInt32(*arg6_ptr); + // The register info used to write memory just needs to have the correct + // size of a 32 bit register, the actual register it pertains to is not + // important, just the size needs to be correct. Here we use "eax"... + error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, + sp + 20, + reg_info_32->byte_size, + reg_value); + if (error.Fail()) + return false; + } + } + } } } } @@ -164,9 +219,9 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, bool ABIMacOSX_i386::PrepareNormalCall (Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t return_addr, + addr_t sp, + addr_t func_addr, + addr_t return_addr, ValueList &args) const { RegisterContext *reg_ctx = thread.GetRegisterContext().get(); diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index 5bc820620fc..62490ab8fed 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -146,9 +146,12 @@ public: lldb::addr_t sp, lldb::addr_t func_addr, lldb::addr_t return_addr, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const; + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL) const; virtual bool PrepareNormalCall (lldb_private::Thread &thread, diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index a943bcd9d46..d0b85039c57 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -60,13 +60,19 @@ ABISysV_x86_64::CreateInstance (const ArchSpec &arch) bool ABISysV_x86_64::PrepareTrivialCall (Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t return_addr, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const + addr_t sp, + addr_t func_addr, + addr_t return_addr, + addr_t *arg1_ptr, + addr_t *arg2_ptr, + addr_t *arg3_ptr, + addr_t *arg4_ptr, + addr_t *arg5_ptr, + addr_t *arg6_ptr) const { + if (arg4_ptr || arg5_ptr || arg6_ptr) + return false; + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (log) diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index d47cbf8381f..4cc702f98a3 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -172,9 +172,12 @@ public: lldb::addr_t sp, lldb::addr_t functionAddress, lldb::addr_t returnAddress, - lldb::addr_t *arg1_ptr, - lldb::addr_t *arg2_ptr, - lldb::addr_t *arg3_ptr) const; + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL) const; virtual bool GetArgumentValues (lldb_private::Thread &thread, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index f8eb8de7bb8..5e685e000c7 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -45,6 +45,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_supports_vCont_s (eLazyBoolCalculate), m_supports_vCont_S (eLazyBoolCalculate), m_qHostInfo_is_valid (eLazyBoolCalculate), + m_supports__m (eLazyBoolCalculate), + m_supports__M (eLazyBoolCalculate), m_supports_qProcessInfoPID (true), m_supports_qfProcessInfo (true), m_supports_qUserName (true), @@ -130,6 +132,9 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_vCont_s = eLazyBoolCalculate; m_supports_vCont_S = eLazyBoolCalculate; m_qHostInfo_is_valid = eLazyBoolCalculate; + m_supports__m = eLazyBoolCalculate; + m_supports__M = eLazyBoolCalculate; + m_supports_qProcessInfoPID = true; m_supports_qfProcessInfo = true; m_supports_qUserName = true; @@ -1016,17 +1021,23 @@ GDBRemoteCommunicationClient::GetHostArchitecture () addr_t GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions) { - char packet[64]; - const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size, - permissions & lldb::ePermissionsReadable ? "r" : "", - permissions & lldb::ePermissionsWritable ? "w" : "", - permissions & lldb::ePermissionsExecutable ? "x" : ""); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + if (m_supports__M != eLazyBoolNo) { - if (!response.IsErrorResponse()) - return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); + m_supports__M = eLazyBoolYes; + char packet[64]; + const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size, + permissions & lldb::ePermissionsReadable ? "r" : "", + permissions & lldb::ePermissionsWritable ? "w" : "", + permissions & lldb::ePermissionsExecutable ? "x" : ""); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + if (response.IsUnsupportedResponse()) + m_supports__M = eLazyBoolNo; + else if (!response.IsErrorResponse()) + return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); + } } return LLDB_INVALID_ADDRESS; } @@ -1034,14 +1045,20 @@ GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions) bool GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr) { - char packet[64]; - const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr); - assert (packet_len < sizeof(packet)); - StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + if (m_supports__m != eLazyBoolNo) { - if (response.IsOKResponse()) - return true; + m_supports__m = eLazyBoolYes; + char packet[64]; + const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + if (response.IsOKResponse()) + return true; + else if (response.IsUnsupportedResponse()) + m_supports__m = eLazyBoolNo; + } } return false; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index d8f317ae7e1..e1d17be8105 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -305,6 +305,18 @@ public: bool SetCurrentThreadForRun (int tid); + lldb_private::LazyBool + SupportsAllocateMemory () const + { + return m_supports__M; + } + + lldb_private::LazyBool + SupportsDeallocateMemory () const + { + return m_supports__m; + } + protected: //------------------------------------------------------------------ @@ -319,6 +331,9 @@ protected: lldb_private::LazyBool m_supports_vCont_s; lldb_private::LazyBool m_supports_vCont_S; lldb_private::LazyBool m_qHostInfo_is_valid; + lldb_private::LazyBool m_supports__m; + lldb_private::LazyBool m_supports__M; + bool m_supports_qProcessInfoPID:1, m_supports_qfProcessInfo:1, @@ -330,6 +345,7 @@ protected: m_supports_z2:1, m_supports_z3:1, m_supports_z4:1; + lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index cba830ebad9..14f31004a85 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -11,8 +11,9 @@ #include <errno.h> #include <spawn.h> #include <stdlib.h> -#include <sys/types.h> +#include <sys/mman.h> // for mmap #include <sys/stat.h> +#include <sys/types.h> #include <time.h> // C++ Includes @@ -38,6 +39,7 @@ #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" +#include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Utility/PseudoTerminal.h" // Project includes @@ -1541,7 +1543,93 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro lldb::addr_t ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) { - addr_t allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); + addr_t allocated_addr = LLDB_INVALID_ADDRESS; + + LazyBool supported = m_gdb_comm.SupportsAllocateMemory(); + switch (supported) + { + case eLazyBoolCalculate: + case eLazyBoolYes: + allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); + if (allocated_addr != LLDB_INVALID_ADDRESS || supported == eLazyBoolYes) + return allocated_addr; + + case eLazyBoolNo: + // Call mmap() to create executable memory in the inferior.. + { + Thread *thread = GetThreadList().GetSelectedThread().get(); + if (thread == NULL) + thread = GetThreadList().GetThreadAtIndex(0).get(); + + const bool append = true; + const bool include_symbols = true; + SymbolContextList sc_list; + const uint32_t count = m_target.GetImages().FindFunctions (ConstString ("mmap"), + eFunctionNameTypeFull, + include_symbols, + append, + sc_list); + if (count > 0) + { + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) + { + const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol; + const bool use_inline_block_range = false; + const bool stop_other_threads = true; + const bool discard_on_error = true; + const bool try_all_threads = true; + const uint32_t single_thread_timeout_usec = 500000; + addr_t arg1_addr = 0; + addr_t arg2_len = size; + addr_t arg3_prot = PROT_NONE; + addr_t arg4_flags = MAP_ANON; + addr_t arg5_fd = -1; + addr_t arg6_offset = 0; + if (permissions & lldb::ePermissionsReadable) + arg3_prot |= PROT_READ; + if (permissions & lldb::ePermissionsWritable) + arg3_prot |= PROT_WRITE; + if (permissions & lldb::ePermissionsExecutable) + arg3_prot |= PROT_EXEC; + + AddressRange mmap_range; + if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range)) + { + lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, + mmap_range.GetBaseAddress(), + stop_other_threads, + discard_on_error, + &arg1_addr, + &arg2_len, + &arg3_prot, + &arg4_flags, + &arg5_fd, + &arg6_offset)); + if (call_plan_sp) + { + StreamFile error_strm; + StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + if (frame) + { + ExecutionContext exe_ctx; + frame->CalculateExecutionContext (exe_ctx); + ExecutionResults results = RunThreadPlan (exe_ctx, + call_plan_sp, + stop_other_threads, + try_all_threads, + discard_on_error, + single_thread_timeout_usec, + error_strm); + } + } + } + } + } + } + break; + } + if (allocated_addr == LLDB_INVALID_ADDRESS) error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %u", size, permissions); else diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 1da0e7b7945..fee0cbd1c7c 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -37,20 +37,18 @@ using namespace lldb_private; ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, Address &function, - lldb::addr_t arg, + addr_t arg, bool stop_other_threads, bool discard_on_error, - lldb::addr_t *this_arg, - lldb::addr_t *cmd_arg) : + addr_t *this_arg, + addr_t *cmd_arg) : ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), m_valid (false), m_stop_other_threads (stop_other_threads), - m_arg_addr (arg), - m_args (NULL), m_process (thread.GetProcess()), m_thread (thread), m_takedown_done (false), - m_function_sp(NULL) + m_function_sp (NULL) { SetOkayToDiscard (discard_on_error); @@ -92,7 +90,7 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, } } - lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); + addr_t start_load_addr = m_start_addr.GetLoadAddress(&target); // Checkpoint the thread state so we can restore it later. if (log && log->GetVerbose()) @@ -108,17 +106,17 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, thread.SetStopInfoToNothing(); m_function_addr = function; - lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); + addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); if (this_arg && cmd_arg) { if (!abi->PrepareTrivialCall (thread, m_function_sp, FunctionLoadAddr, - StartLoadAddr, + start_load_addr, this_arg, cmd_arg, - &m_arg_addr)) + &arg)) return; } else if (this_arg) @@ -126,10 +124,9 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, if (!abi->PrepareTrivialCall (thread, m_function_sp, FunctionLoadAddr, - StartLoadAddr, + start_load_addr, this_arg, - &m_arg_addr, - NULL)) + &arg)) return; } else @@ -137,10 +134,104 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, if (!abi->PrepareTrivialCall (thread, m_function_sp, FunctionLoadAddr, - StartLoadAddr, - &m_arg_addr, - NULL, - NULL)) + start_load_addr, + &arg)) + return; + } + + ReportRegisterState ("Function call was set up. Register state was:"); + + m_valid = true; +} + + +ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, + Address &function, + bool stop_other_threads, + bool discard_on_error, + addr_t *arg1_ptr, + addr_t *arg2_ptr, + addr_t *arg3_ptr, + addr_t *arg4_ptr, + addr_t *arg5_ptr, + addr_t *arg6_ptr) : + ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), + m_valid (false), + m_stop_other_threads (stop_other_threads), + m_process (thread.GetProcess()), + m_thread (thread), + m_takedown_done (false), + m_function_sp(NULL) +{ + SetOkayToDiscard (discard_on_error); + + Process& process = thread.GetProcess(); + Target& target = process.GetTarget(); + const ABI *abi = process.GetABI().get(); + + if (!abi) + return; + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + + SetBreakpoints(); + + m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); + + ModuleSP executableModuleSP (target.GetExecutableModule()); + + if (!executableModuleSP) + { + log->Printf ("Can't execute code without an executable module."); + return; + } + else + { + ObjectFile *objectFile = executableModuleSP->GetObjectFile(); + if (!objectFile) + { + log->Printf ("Could not find object file for module \"%s\".", + executableModuleSP->GetFileSpec().GetFilename().AsCString()); + return; + } + m_start_addr = objectFile->GetEntryPointAddress(); + if (!m_start_addr.IsValid()) + { + log->Printf ("Could not find entry point address for executable module \"%s\".", + executableModuleSP->GetFileSpec().GetFilename().AsCString()); + return; + } + } + + addr_t start_load_addr = m_start_addr.GetLoadAddress(&target); + + // Checkpoint the thread state so we can restore it later. + if (log && log->GetVerbose()) + ReportRegisterState ("About to checkpoint thread before function call. Original register state was:"); + + if (!thread.CheckpointThreadState (m_stored_thread_state)) + { + if (log) + log->Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state."); + return; + } + // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding... + thread.SetStopInfoToNothing(); + + m_function_addr = function; + addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); + + if (!abi->PrepareTrivialCall (thread, + m_function_sp, + FunctionLoadAddr, + start_load_addr, + arg1_ptr, + arg2_ptr, + arg3_ptr, + arg4_ptr, + arg5_ptr, + arg6_ptr)) + { return; } @@ -205,18 +296,15 @@ ThreadPlanCallFunction::WillPop () } void -ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) +ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level) { - if (level == lldb::eDescriptionLevelBrief) + if (level == eDescriptionLevelBrief) { s->Printf("Function call thread plan"); } else { - if (m_args) - s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); - else - s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); + s->Printf("Thread plan to call 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget())); } } @@ -248,12 +336,12 @@ ThreadPlanCallFunction::PlanExplainsStop () // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on. // If it is not an internal breakpoint, consult OkayToDiscard. - lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); + StopInfoSP stop_info_sp = GetPrivateStopReason(); if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { uint64_t break_site_id = stop_info_sp->GetValue(); - lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id); + BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id); if (bp_site_sp) { uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); @@ -386,7 +474,7 @@ ThreadPlanCallFunction::ClearBreakpoints () bool ThreadPlanCallFunction::BreakpointsExplainStop() { - lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); + StopInfoSP stop_info_sp = GetPrivateStopReason(); if (m_cxx_language_runtime && m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) |

