Expand the ABI prepare trivial function call to allow 6 simple args.

llvm-svn: 131334
This commit is contained in:
Greg Clayton 2011-05-14 01:50:35 +00:00
parent a16b5be727
commit 2a48f525cd
12 changed files with 417 additions and 107 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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)
if (arg2_ptr)
{
reg_value.SetUInt32(*arg2_ptr);
if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value))
return false;
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)
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"

View File

@ -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,

View File

@ -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();

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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))