forked from OSchip/llvm-project
Expand the ABI prepare trivial function call to allow 6 simple args.
llvm-svn: 131334
This commit is contained in:
parent
a16b5be727
commit
2a48f525cd
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue