forked from OSchip/llvm-project
Added new lldb_private::Process memory read/write functions to stop a bunch
of duplicated code from appearing all over LLDB: lldb::addr_t Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error); bool Process::WritePointerToMemory (lldb::addr_t vm_addr, lldb::addr_t ptr_value, Error &error); size_t Process::ReadScalarIntegerFromMemory (lldb::addr_t addr, uint32_t byte_size, bool is_signed, Scalar &scalar, Error &error); size_t Process::WriteScalarToMemory (lldb::addr_t vm_addr, const Scalar &scalar, uint32_t size, Error &error); in lldb_private::Process the following functions were renamed: From: uint64_t Process::ReadUnsignedInteger (lldb::addr_t load_addr, size_t byte_size, Error &error); To: uint64_t Process::ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Error &error); Cleaned up a lot of code that was manually doing what the above functions do to use the functions listed above. Added the ability to get a scalar value as a buffer that can be written down to a process (byte swapping the Scalar value if needed): uint32_t Scalar::GetAsMemoryData (void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Error &error) const; The "dst_len" can be smaller that the size of the scalar and the least significant bytes will be written. "dst_len" can also be larger and the most significant bytes will be padded with zeroes. Centralized the code that adds or removes address bits for callable and opcode addresses into lldb_private::Target: lldb::addr_t Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const; lldb::addr_t Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const; All necessary lldb_private::Address functions now use the target versions so changes should only need to happen in one place if anything needs updating. Fixed up a lot of places that were calling : addr_t Address::GetLoadAddress(Target*); to call the Address::GetCallableLoadAddress() or Address::GetOpcodeLoadAddress() as needed. There were many places in the breakpoint code where things could go wrong for ARM if these weren't used. llvm-svn: 131878
This commit is contained in:
parent
5c51177981
commit
f3ef3d2af9
|
@ -63,12 +63,18 @@ public:
|
||||||
static size_t
|
static size_t
|
||||||
GetMaxByteSize()
|
GetMaxByteSize()
|
||||||
{
|
{
|
||||||
return std::max (sizeof(long double), sizeof (unsigned long long));
|
return sizeof(ValueData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetData (DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
|
GetData (DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const;
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
GetAsMemoryData (void *dst,
|
||||||
|
uint32_t dst_len,
|
||||||
|
lldb::ByteOrder dst_byte_order,
|
||||||
|
Error &error) const;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsZero() const;
|
IsZero() const;
|
||||||
|
|
||||||
|
|
|
@ -2083,6 +2083,9 @@ public:
|
||||||
/// @param[in] byte_size
|
/// @param[in] byte_size
|
||||||
/// The size in byte of the integer to read.
|
/// The size in byte of the integer to read.
|
||||||
///
|
///
|
||||||
|
/// @param[in] fail_value
|
||||||
|
/// The value to return if we fail to read an integer.
|
||||||
|
///
|
||||||
/// @param[out] error
|
/// @param[out] error
|
||||||
/// An error that indicates the success or failure of this
|
/// An error that indicates the success or failure of this
|
||||||
/// operation. If error indicates success (error.Success()),
|
/// operation. If error indicates success (error.Success()),
|
||||||
|
@ -2098,9 +2101,20 @@ public:
|
||||||
/// order.
|
/// order.
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
uint64_t
|
uint64_t
|
||||||
ReadUnsignedInteger (lldb::addr_t load_addr,
|
ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr,
|
||||||
size_t byte_size,
|
size_t byte_size,
|
||||||
Error &error);
|
uint64_t fail_value,
|
||||||
|
Error &error);
|
||||||
|
|
||||||
|
lldb::addr_t
|
||||||
|
ReadPointerFromMemory (lldb::addr_t vm_addr,
|
||||||
|
Error &error);
|
||||||
|
|
||||||
|
bool
|
||||||
|
WritePointerToMemory (lldb::addr_t vm_addr,
|
||||||
|
lldb::addr_t ptr_value,
|
||||||
|
Error &error);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// Actually do the writing of memory to a process.
|
/// Actually do the writing of memory to a process.
|
||||||
///
|
///
|
||||||
|
@ -2115,12 +2129,60 @@ public:
|
||||||
/// @param[in] size
|
/// @param[in] size
|
||||||
/// The number of bytes to write.
|
/// The number of bytes to write.
|
||||||
///
|
///
|
||||||
|
/// @param[out] error
|
||||||
|
/// An error value in case the memory write fails.
|
||||||
|
///
|
||||||
/// @return
|
/// @return
|
||||||
/// The number of bytes that were actually written.
|
/// The number of bytes that were actually written.
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
virtual size_t
|
virtual size_t
|
||||||
DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) = 0;
|
DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) = 0;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
/// Write all or part of a scalar value to memory.
|
||||||
|
///
|
||||||
|
/// The value contained in \a scalar will be swapped to match the
|
||||||
|
/// byte order of the process that is being debugged. If \a size is
|
||||||
|
/// less than the size of scalar, the least significate \a size bytes
|
||||||
|
/// from scalar will be written. If \a size is larger than the byte
|
||||||
|
/// size of scalar, then the extra space will be padded with zeros
|
||||||
|
/// and the scalar value will be placed in the least significant
|
||||||
|
/// bytes in memory.
|
||||||
|
///
|
||||||
|
/// @param[in] vm_addr
|
||||||
|
/// A virtual load address that indicates where to start writing
|
||||||
|
/// memory to.
|
||||||
|
///
|
||||||
|
/// @param[in] scalar
|
||||||
|
/// The scalar to write to the debugged process.
|
||||||
|
///
|
||||||
|
/// @param[in] size
|
||||||
|
/// This value can be smaller or larger than the scalar value
|
||||||
|
/// itself. If \a size is smaller than the size of \a scalar,
|
||||||
|
/// the least significant bytes in \a scalar will be used. If
|
||||||
|
/// \a size is larger than the byte size of \a scalar, then
|
||||||
|
/// the extra space will be padded with zeros. If \a size is
|
||||||
|
/// set to UINT32_MAX, then the size of \a scalar will be used.
|
||||||
|
///
|
||||||
|
/// @param[out] error
|
||||||
|
/// An error value in case the memory write fails.
|
||||||
|
///
|
||||||
|
/// @return
|
||||||
|
/// The number of bytes that were actually written.
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
size_t
|
||||||
|
WriteScalarToMemory (lldb::addr_t vm_addr,
|
||||||
|
const Scalar &scalar,
|
||||||
|
uint32_t size,
|
||||||
|
Error &error);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ReadScalarIntegerFromMemory (lldb::addr_t addr,
|
||||||
|
uint32_t byte_size,
|
||||||
|
bool is_signed,
|
||||||
|
Scalar &scalar,
|
||||||
|
Error &error);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
/// Write memory to a process.
|
/// Write memory to a process.
|
||||||
///
|
///
|
||||||
|
|
|
@ -280,6 +280,36 @@ public:
|
||||||
void
|
void
|
||||||
ModulesDidUnload (ModuleList &module_list);
|
ModulesDidUnload (ModuleList &module_list);
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
/// Get \a load_addr as a callable code load address for this target
|
||||||
|
///
|
||||||
|
/// Take \a load_addr and potentially add any address bits that are
|
||||||
|
/// needed to make the address callable. For ARM this can set bit
|
||||||
|
/// zero (if it already isn't) if \a load_addr is a thumb function.
|
||||||
|
/// If \a addr_class is set to eAddressClassInvalid, then the address
|
||||||
|
/// adjustment will always happen. If it is set to an address class
|
||||||
|
/// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
|
||||||
|
/// returned.
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
lldb::addr_t
|
||||||
|
GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class = lldb_private::eAddressClassInvalid) const;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
/// Get \a load_addr as an opcode for this target.
|
||||||
|
///
|
||||||
|
/// Take \a load_addr and potentially strip any address bits that are
|
||||||
|
/// needed to make the address point to an opcode. For ARM this can
|
||||||
|
/// clear bit zero (if it already isn't) if \a load_addr is a
|
||||||
|
/// thumb function and load_addr is in code.
|
||||||
|
/// If \a addr_class is set to eAddressClassInvalid, then the address
|
||||||
|
/// adjustment will always happen. If it is set to an address class
|
||||||
|
/// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
|
||||||
|
/// returned.
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
lldb::addr_t
|
||||||
|
GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class = lldb_private::eAddressClassInvalid) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void
|
void
|
||||||
ModuleAdded (lldb::ModuleSP &module_sp);
|
ModuleAdded (lldb::ModuleSP &module_sp);
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
bool stop_others);
|
bool stop_others);
|
||||||
|
|
||||||
ThreadPlanRunToAddress (Thread &thread,
|
ThreadPlanRunToAddress (Thread &thread,
|
||||||
std::vector<lldb::addr_t> &addresses,
|
const std::vector<lldb::addr_t> &addresses,
|
||||||
bool stop_others);
|
bool stop_others);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ BreakpointLocation::BreakpointLocation
|
||||||
lldb::tid_t tid,
|
lldb::tid_t tid,
|
||||||
bool hardware
|
bool hardware
|
||||||
) :
|
) :
|
||||||
StoppointLocation (loc_id, addr.GetLoadAddress(&owner.GetTarget()), hardware),
|
StoppointLocation (loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()), hardware),
|
||||||
m_address (addr),
|
m_address (addr),
|
||||||
m_owner (owner),
|
m_owner (owner),
|
||||||
m_options_ap (),
|
m_options_ap (),
|
||||||
|
@ -53,7 +53,7 @@ BreakpointLocation::~BreakpointLocation()
|
||||||
lldb::addr_t
|
lldb::addr_t
|
||||||
BreakpointLocation::GetLoadAddress () const
|
BreakpointLocation::GetLoadAddress () const
|
||||||
{
|
{
|
||||||
return m_address.GetLoadAddress(&m_owner.GetTarget());
|
return m_address.GetOpcodeLoadAddress (&m_owner.GetTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
Address &
|
Address &
|
||||||
|
@ -290,7 +290,7 @@ BreakpointLocation::ResolveBreakpointSite ()
|
||||||
LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
|
LogSP log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
|
||||||
if (log)
|
if (log)
|
||||||
log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
|
log->Warning ("Tried to add breakpoint site at 0x%llx but it was already present.\n",
|
||||||
m_address.GetLoadAddress(&m_owner.GetTarget()));
|
m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ BreakpointLocation::Dump(Stream *s) const
|
||||||
"hw_index = %i hit_count = %-4u ignore_count = %-4u",
|
"hw_index = %i hit_count = %-4u ignore_count = %-4u",
|
||||||
GetID(),
|
GetID(),
|
||||||
GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
|
GetOptionsNoCreate()->GetThreadSpecNoCreate()->GetTID(),
|
||||||
(uint64_t) m_address.GetLoadAddress (&m_owner.GetTarget()),
|
(uint64_t) m_address.GetOpcodeLoadAddress (&m_owner.GetTarget()),
|
||||||
(m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
|
(m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled()) ? "enabled " : "disabled",
|
||||||
IsHardware() ? "hardware" : "software",
|
IsHardware() ? "hardware" : "software",
|
||||||
GetHardwareIndex(),
|
GetHardwareIndex(),
|
||||||
|
|
|
@ -300,37 +300,9 @@ addr_t
|
||||||
Address::GetCallableLoadAddress (Target *target) const
|
Address::GetCallableLoadAddress (Target *target) const
|
||||||
{
|
{
|
||||||
addr_t code_addr = GetLoadAddress (target);
|
addr_t code_addr = GetLoadAddress (target);
|
||||||
|
|
||||||
// Make sure we have section, otherwise the call to GetAddressClass() will
|
if (target)
|
||||||
// fail because it uses the section to get to the module.
|
return target->GetCallableLoadAddress (code_addr, GetAddressClass());
|
||||||
if (m_section && code_addr != LLDB_INVALID_ADDRESS)
|
|
||||||
{
|
|
||||||
switch (target->GetArchitecture().GetMachine())
|
|
||||||
{
|
|
||||||
case llvm::Triple::arm:
|
|
||||||
case llvm::Triple::thumb:
|
|
||||||
// Check if bit zero it no set?
|
|
||||||
if ((code_addr & 1ull) == 0)
|
|
||||||
{
|
|
||||||
// Bit zero isn't set, check if the address is a multiple of 2?
|
|
||||||
if (code_addr & 2ull)
|
|
||||||
{
|
|
||||||
// The address is a multiple of 2 so it must be thumb, set bit zero
|
|
||||||
code_addr |= 1ull;
|
|
||||||
}
|
|
||||||
else if (GetAddressClass() == eAddressClassCodeAlternateISA)
|
|
||||||
{
|
|
||||||
// We checked the address and the address claims to be the alternate ISA
|
|
||||||
// which means thumb, so set bit zero.
|
|
||||||
code_addr |= 1ull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code_addr;
|
return code_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,57 +311,19 @@ Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target)
|
||||||
{
|
{
|
||||||
if (SetLoadAddress (load_addr, target))
|
if (SetLoadAddress (load_addr, target))
|
||||||
{
|
{
|
||||||
switch (target->GetArchitecture().GetMachine())
|
if (target)
|
||||||
{
|
m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass());
|
||||||
case llvm::Triple::arm:
|
|
||||||
case llvm::Triple::thumb:
|
|
||||||
// Check if bit zero it no set?
|
|
||||||
if ((m_offset & 1ull) == 0)
|
|
||||||
{
|
|
||||||
// Bit zero isn't set, check if the address is a multiple of 2?
|
|
||||||
if (m_offset & 2ull)
|
|
||||||
{
|
|
||||||
// The address is a multiple of 2 so it must be thumb, set bit zero
|
|
||||||
m_offset |= 1ull;
|
|
||||||
}
|
|
||||||
else if (GetAddressClass() == eAddressClassCodeAlternateISA)
|
|
||||||
{
|
|
||||||
// We checked the address and the address claims to be the alternate ISA
|
|
||||||
// which means thumb, so set bit zero.
|
|
||||||
m_offset |= 1ull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
addr_t
|
addr_t
|
||||||
Address::GetOpcodeLoadAddress (Target *target) const
|
Address::GetOpcodeLoadAddress (Target *target) const
|
||||||
{
|
{
|
||||||
addr_t code_addr = GetLoadAddress (target);
|
addr_t code_addr = GetLoadAddress (target);
|
||||||
|
|
||||||
if (code_addr != LLDB_INVALID_ADDRESS)
|
if (code_addr != LLDB_INVALID_ADDRESS)
|
||||||
{
|
code_addr = target->GetOpcodeLoadAddress (code_addr, GetAddressClass());
|
||||||
switch (target->GetArchitecture().GetMachine())
|
|
||||||
{
|
|
||||||
case llvm::Triple::arm:
|
|
||||||
case llvm::Triple::thumb:
|
|
||||||
// Strip bit zero to make sure we end up on an opcode boundary
|
|
||||||
return code_addr & ~(1ull);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return code_addr;
|
return code_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,17 +332,8 @@ Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target)
|
||||||
{
|
{
|
||||||
if (SetLoadAddress (load_addr, target))
|
if (SetLoadAddress (load_addr, target))
|
||||||
{
|
{
|
||||||
switch (target->GetArchitecture().GetMachine())
|
if (target)
|
||||||
{
|
m_offset = target->GetOpcodeLoadAddress (m_offset, GetAddressClass());
|
||||||
case llvm::Triple::arm:
|
|
||||||
case llvm::Triple::thumb:
|
|
||||||
// Make sure bit zero is clear
|
|
||||||
m_offset &= ~(1ull);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1063,7 +1063,7 @@ DataExtractor::CopyByteOrderedData (uint32_t src_offset,
|
||||||
const uint8_t* src = (const uint8_t *)PeekData (src_offset, src_len);
|
const uint8_t* src = (const uint8_t *)PeekData (src_offset, src_len);
|
||||||
if (src)
|
if (src)
|
||||||
{
|
{
|
||||||
if (src_len >= dst_len)
|
if (dst_len >= src_len)
|
||||||
{
|
{
|
||||||
// We are copying the entire value from src into dst.
|
// We are copying the entire value from src into dst.
|
||||||
// Calculate how many, if any, zeroes we need for the most
|
// Calculate how many, if any, zeroes we need for the most
|
||||||
|
|
|
@ -1989,6 +1989,34 @@ Scalar::SignExtend (uint32_t sign_bit_pos)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
Scalar::GetAsMemoryData (void *dst,
|
||||||
|
uint32_t dst_len,
|
||||||
|
lldb::ByteOrder dst_byte_order,
|
||||||
|
Error &error) const
|
||||||
|
{
|
||||||
|
// Get a data extractor that points to the native scalar data
|
||||||
|
DataExtractor data;
|
||||||
|
if (!GetData(data))
|
||||||
|
{
|
||||||
|
error.SetErrorString ("invalid scalar value");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t src_len = data.GetByteSize();
|
||||||
|
|
||||||
|
// Prepare a memory buffer that contains some or all of the register value
|
||||||
|
const uint32_t bytes_copied = data.CopyByteOrderedData (0, // src offset
|
||||||
|
src_len, // src length
|
||||||
|
dst, // dst buffer
|
||||||
|
dst_len, // dst length
|
||||||
|
dst_byte_order); // dst byte order
|
||||||
|
if (bytes_copied == 0)
|
||||||
|
error.SetErrorString ("failed to copy data");
|
||||||
|
|
||||||
|
return bytes_copied;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
lldb_private::operator== (const Scalar& lhs, const Scalar& rhs)
|
lldb_private::operator== (const Scalar& lhs, const Scalar& rhs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -680,7 +680,6 @@ ClangExpressionDeclMap::GetObjectPointer
|
||||||
{
|
{
|
||||||
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
||||||
uint32_t address_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
|
uint32_t address_byte_size = exe_ctx.target->GetArchitecture().GetAddressByteSize();
|
||||||
lldb::ByteOrder address_byte_order = exe_ctx.process->GetByteOrder();
|
|
||||||
|
|
||||||
if (ClangASTType::GetClangTypeBitWidth(m_struct_vars->m_object_pointer_type.GetASTContext(),
|
if (ClangASTType::GetClangTypeBitWidth(m_struct_vars->m_object_pointer_type.GetASTContext(),
|
||||||
m_struct_vars->m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
|
m_struct_vars->m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
|
||||||
|
@ -689,22 +688,13 @@ ClangExpressionDeclMap::GetObjectPointer
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBufferHeap data;
|
|
||||||
data.SetByteSize(address_byte_size);
|
|
||||||
Error read_error;
|
Error read_error;
|
||||||
|
object_ptr = exe_ctx.process->ReadPointerFromMemory (value_addr, read_error);
|
||||||
if (exe_ctx.process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
|
if (read_error.Fail() || object_ptr == LLDB_INVALID_ADDRESS)
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Coldn't read '%s' from the target: %s", object_name.GetCString(), read_error.AsCString());
|
err.SetErrorStringWithFormat("Coldn't read '%s' from the target: %s", object_name.GetCString(), read_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataExtractor extractor(data.GetBytes(), data.GetByteSize(), address_byte_order, address_byte_size);
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
|
|
||||||
object_ptr = extractor.GetPointer(&offset);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Value::eValueTypeScalar:
|
case Value::eValueTypeScalar:
|
||||||
|
@ -812,16 +802,18 @@ ClangExpressionDeclMap::DumpMaterializedStruct
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lldb::DataBufferSP data(new DataBufferHeap(m_struct_vars->m_struct_size, 0));
|
lldb::DataBufferSP data_sp(new DataBufferHeap(m_struct_vars->m_struct_size, 0));
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
if (exe_ctx.process->ReadMemory (m_material_vars->m_materialized_location, data->GetBytes(), data->GetByteSize(), error) != data->GetByteSize())
|
if (exe_ctx.process->ReadMemory (m_material_vars->m_materialized_location,
|
||||||
|
data_sp->GetBytes(),
|
||||||
|
data_sp->GetByteSize(), error) != data_sp->GetByteSize())
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't read struct from the target: %s", error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataExtractor extractor(data, exe_ctx.process->GetByteOrder(), exe_ctx.target->GetArchitecture().GetAddressByteSize());
|
DataExtractor extractor(data_sp, exe_ctx.process->GetByteOrder(), exe_ctx.target->GetArchitecture().GetAddressByteSize());
|
||||||
|
|
||||||
for (size_t member_idx = 0, num_members = m_struct_members.GetSize();
|
for (size_t member_idx = 0, num_members = m_struct_members.GetSize();
|
||||||
member_idx < num_members;
|
member_idx < num_members;
|
||||||
|
@ -1000,63 +992,6 @@ ClangExpressionDeclMap::DoMaterialize
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool WriteAddressInto
|
|
||||||
(
|
|
||||||
ExecutionContext &exe_ctx,
|
|
||||||
lldb::addr_t target,
|
|
||||||
lldb::addr_t address,
|
|
||||||
Error &err
|
|
||||||
)
|
|
||||||
{
|
|
||||||
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
|
|
||||||
|
|
||||||
StreamString str (0 | Stream::eBinary,
|
|
||||||
pointer_byte_size,
|
|
||||||
exe_ctx.process->GetByteOrder());
|
|
||||||
|
|
||||||
switch (pointer_byte_size)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
assert(!"Unhandled byte size");
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
uint32_t address32 = address & 0xffffffffll;
|
|
||||||
str.PutRawBytes(&address32, sizeof(address32), endian::InlHostByteOrder(), eByteOrderInvalid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
{
|
|
||||||
uint64_t address64 = address;
|
|
||||||
str.PutRawBytes(&address64, sizeof(address64), endian::InlHostByteOrder(), eByteOrderInvalid);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (exe_ctx.process->WriteMemory (target, str.GetData(), pointer_byte_size, err) == pointer_byte_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static lldb::addr_t ReadAddressFrom
|
|
||||||
(
|
|
||||||
ExecutionContext &exe_ctx,
|
|
||||||
lldb::addr_t source,
|
|
||||||
Error &err
|
|
||||||
)
|
|
||||||
{
|
|
||||||
size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
|
|
||||||
|
|
||||||
DataBufferHeap *buf = new DataBufferHeap(pointer_byte_size, 0);
|
|
||||||
DataBufferSP buf_sp(buf);
|
|
||||||
|
|
||||||
if (exe_ctx.process->ReadMemory (source, buf->GetBytes(), pointer_byte_size, err) != pointer_byte_size)
|
|
||||||
return LLDB_INVALID_ADDRESS;
|
|
||||||
|
|
||||||
DataExtractor extractor (buf_sp, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
|
|
||||||
return (lldb::addr_t)extractor.GetPointer(&offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
||||||
(
|
(
|
||||||
|
@ -1098,7 +1033,7 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
||||||
// Get the location of the target out of the struct.
|
// Get the location of the target out of the struct.
|
||||||
|
|
||||||
Error read_error;
|
Error read_error;
|
||||||
mem = ReadAddressFrom(exe_ctx, addr, read_error);
|
mem = exe_ctx.process->ReadPointerFromMemory (addr, read_error);
|
||||||
|
|
||||||
if (mem == LLDB_INVALID_ADDRESS)
|
if (mem == LLDB_INVALID_ADDRESS)
|
||||||
{
|
{
|
||||||
|
@ -1243,19 +1178,19 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
||||||
if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
|
if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
|
||||||
var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
|
var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
|
||||||
{
|
{
|
||||||
mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
|
|
||||||
|
|
||||||
// Now write the location of the area into the struct.
|
// Now write the location of the area into the struct.
|
||||||
|
|
||||||
Error write_error;
|
Error write_error;
|
||||||
if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
|
if (!exe_ctx.process->WriteScalarToMemory (addr,
|
||||||
|
var_sp->m_live_sp->GetValue().GetScalar(),
|
||||||
|
exe_ctx.process->GetAddressByteSize(),
|
||||||
|
write_error))
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
|
log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), var_sp->m_live_sp->GetValue().GetScalar().ULongLong());
|
||||||
}
|
}
|
||||||
else if (!(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
|
else if (!(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
|
||||||
{
|
{
|
||||||
|
@ -1308,7 +1243,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
if (!GetSymbolAddress(*exe_ctx.target, name, location_load_addr))
|
if (!GetSymbolAddress(*exe_ctx.target, name, location_load_addr))
|
||||||
{
|
{
|
||||||
if (log)
|
if (log)
|
||||||
err.SetErrorStringWithFormat("Couldn't find value for global symbol %s", name.GetCString());
|
err.SetErrorStringWithFormat ("Couldn't find value for global symbol %s",
|
||||||
|
name.GetCString());
|
||||||
}
|
}
|
||||||
|
|
||||||
location_value->SetValueType(Value::eValueTypeLoadAddress);
|
location_value->SetValueType(Value::eValueTypeLoadAddress);
|
||||||
|
@ -1316,7 +1252,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't find %s with appropriate type", name.GetCString());
|
err.SetErrorStringWithFormat ("Couldn't find %s with appropriate type",
|
||||||
|
name.GetCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,7 +1265,10 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
type.GetOpaqueQualType(),
|
type.GetOpaqueQualType(),
|
||||||
&my_stream_string);
|
&my_stream_string);
|
||||||
|
|
||||||
log->Printf("%s %s with type %s", (dematerialize ? "Dematerializing" : "Materializing"), name.GetCString(), my_stream_string.GetString().c_str());
|
log->Printf ("%s %s with type %s",
|
||||||
|
dematerialize ? "Dematerializing" : "Materializing",
|
||||||
|
name.GetCString(),
|
||||||
|
my_stream_string.GetString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!location_value.get())
|
if (!location_value.get())
|
||||||
|
@ -1352,7 +1292,9 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
|
|
||||||
location_value->Dump(&ss);
|
location_value->Dump(&ss);
|
||||||
|
|
||||||
err.SetErrorStringWithFormat("%s has a value of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
|
err.SetErrorStringWithFormat ("%s has a value of unhandled type: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
ss.GetString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1360,16 +1302,16 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
{
|
{
|
||||||
if (!dematerialize)
|
if (!dematerialize)
|
||||||
{
|
{
|
||||||
lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
|
Error write_error;
|
||||||
|
|
||||||
Error error;
|
|
||||||
|
|
||||||
if (!WriteAddressInto(exe_ctx,
|
if (!exe_ctx.process->WriteScalarToMemory (addr,
|
||||||
addr,
|
location_value->GetScalar(),
|
||||||
value_addr,
|
exe_ctx.process->GetAddressByteSize(),
|
||||||
error))
|
write_error))
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
write_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1382,17 +1324,18 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
StreamString ss;
|
StreamString ss;
|
||||||
location_value->Dump(&ss);
|
location_value->Dump(&ss);
|
||||||
|
|
||||||
err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
|
err.SetErrorStringWithFormat ("%s is a scalar of unhandled type: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
ss.GetString().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
lldb::addr_t reg_addr = LLDB_INVALID_ADDRESS; // The address of a spare memory area aused to hold the variable.
|
|
||||||
|
|
||||||
RegisterInfo *reg_info = location_value->GetRegisterInfo();
|
RegisterInfo *reg_info = location_value->GetRegisterInfo();
|
||||||
|
|
||||||
if (!reg_info)
|
if (!reg_info)
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't get the register information for %s", name.GetCString());
|
err.SetErrorStringWithFormat ("Couldn't get the register information for %s",
|
||||||
|
name.GetCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1402,7 +1345,9 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
|
|
||||||
if (!reg_ctx)
|
if (!reg_ctx)
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't read register context to read %s from %s", name.GetCString(), reg_info->name);
|
err.SetErrorStringWithFormat ("Couldn't read register context to read %s from %s",
|
||||||
|
name.GetCString(),
|
||||||
|
reg_info->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,25 +1369,32 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_addr = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
|
Scalar ®_addr = expr_var->m_live_sp->GetValue().GetScalar();
|
||||||
|
|
||||||
err = reg_ctx->ReadRegisterValueFromMemory (reg_info, reg_addr, value_byte_size, reg_value);
|
err = reg_ctx->ReadRegisterValueFromMemory (reg_info,
|
||||||
|
reg_addr.ULongLong(),
|
||||||
|
value_byte_size,
|
||||||
|
reg_value);
|
||||||
if (err.Fail())
|
if (err.Fail())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!reg_ctx->WriteRegister (reg_info, reg_value))
|
if (!reg_ctx->WriteRegister (reg_info, reg_value))
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't write %s to register %s", name.GetCString(), reg_info->name);
|
err.SetErrorStringWithFormat ("Couldn't write %s to register %s",
|
||||||
|
name.GetCString(),
|
||||||
|
reg_info->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deallocate the spare area and clear the variable's live data.
|
// Deallocate the spare area and clear the variable's live data.
|
||||||
|
|
||||||
Error deallocate_error = exe_ctx.process->DeallocateMemory(reg_addr);
|
Error deallocate_error = exe_ctx.process->DeallocateMemory(reg_addr.ULongLong());
|
||||||
|
|
||||||
if (!deallocate_error.Success())
|
if (!deallocate_error.Success())
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't deallocate spare memory area for %s: %s", name.GetCString(), deallocate_error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't deallocate spare memory area for %s: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
deallocate_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,13 +1407,15 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
|
|
||||||
Error allocate_error;
|
Error allocate_error;
|
||||||
|
|
||||||
reg_addr = exe_ctx.process->AllocateMemory (value_byte_size,
|
Scalar reg_addr (exe_ctx.process->AllocateMemory (value_byte_size,
|
||||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||||
allocate_error);
|
allocate_error));
|
||||||
|
|
||||||
if (reg_addr == LLDB_INVALID_ADDRESS)
|
if (reg_addr.ULongLong() == LLDB_INVALID_ADDRESS)
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't allocate a memory area to store %s: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
allocate_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1471,66 +1425,47 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
||||||
type.GetASTContext(),
|
type.GetASTContext(),
|
||||||
type.GetOpaqueQualType(),
|
type.GetOpaqueQualType(),
|
||||||
name,
|
name,
|
||||||
reg_addr,
|
reg_addr.ULongLong(),
|
||||||
eAddressTypeLoad,
|
eAddressTypeLoad,
|
||||||
value_byte_size);
|
value_byte_size);
|
||||||
|
|
||||||
// Now write the location of the area into the struct.
|
// Now write the location of the area into the struct.
|
||||||
|
|
||||||
Error write_error;
|
Error write_error;
|
||||||
if (!WriteAddressInto(exe_ctx, addr, reg_addr, write_error))
|
|
||||||
|
if (!exe_ctx.process->WriteScalarToMemory (addr,
|
||||||
|
reg_addr,
|
||||||
|
exe_ctx.process->GetAddressByteSize(),
|
||||||
|
write_error))
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
|
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s",
|
||||||
|
name.GetCString(),
|
||||||
|
write_error.AsCString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moving from a register into addr
|
|
||||||
//
|
|
||||||
// Case 1: addr_byte_size and register_byte_size are the same
|
|
||||||
//
|
|
||||||
// |AABBCCDD| Register contents
|
|
||||||
// |AABBCCDD| Address contents
|
|
||||||
//
|
|
||||||
// Case 2: addr_byte_size is bigger than register_byte_size
|
|
||||||
//
|
|
||||||
// Error! (The register should always be big enough to hold the data)
|
|
||||||
//
|
|
||||||
// Case 3: register_byte_size is bigger than addr_byte_size
|
|
||||||
//
|
|
||||||
// |AABBCCDD| Register contents
|
|
||||||
// |AABB| Address contents on little-endian hardware
|
|
||||||
// |CCDD| Address contents on big-endian hardware
|
|
||||||
|
|
||||||
if (value_byte_size > register_byte_size)
|
if (value_byte_size > register_byte_size)
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), reg_info->name);
|
err.SetErrorStringWithFormat ("%s is too big to store in %s",
|
||||||
|
name.GetCString(),
|
||||||
|
reg_info->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t register_offset;
|
|
||||||
|
|
||||||
switch (exe_ctx.process->GetByteOrder())
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
err.SetErrorStringWithFormat("%s is stored with an unhandled byte order", name.GetCString());
|
|
||||||
return false;
|
|
||||||
case lldb::eByteOrderLittle:
|
|
||||||
register_offset = 0;
|
|
||||||
break;
|
|
||||||
case lldb::eByteOrderBig:
|
|
||||||
register_offset = register_byte_size - value_byte_size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterValue reg_value;
|
RegisterValue reg_value;
|
||||||
|
|
||||||
if (!reg_ctx->ReadRegister (reg_info, reg_value))
|
if (!reg_ctx->ReadRegister (reg_info, reg_value))
|
||||||
{
|
{
|
||||||
err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), reg_info->name);
|
err.SetErrorStringWithFormat ("Couldn't read %s from %s",
|
||||||
|
name.GetCString(),
|
||||||
|
reg_info->name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = reg_ctx->WriteRegisterValueToMemory(reg_info, reg_addr, value_byte_size, reg_value);
|
err = reg_ctx->WriteRegisterValueToMemory (reg_info,
|
||||||
|
reg_addr.ULongLong(),
|
||||||
|
value_byte_size,
|
||||||
|
reg_value);
|
||||||
if (err.Fail())
|
if (err.Fail())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,7 +654,7 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
|
||||||
if (exc_context.process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
|
if (exc_context.process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
|
||||||
{
|
{
|
||||||
err.SetErrorToGenericError();
|
err.SetErrorToGenericError();
|
||||||
err.SetErrorStringWithFormat("Couldn't copy JITted function into the target: %s", write_error.AsCString("unknown error"));
|
err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error"));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,12 +314,10 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This is fake, and just assumes that it matches that architecture.
|
// TODO: verify fun_addr needs to be a callable address
|
||||||
// Make a data extractor and put the address into the right byte order & size.
|
Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.target));
|
||||||
|
|
||||||
uint64_t fun_addr = function_address.GetLoadAddress(exe_ctx.target);
|
|
||||||
int first_offset = m_member_offsets[0];
|
int first_offset = m_member_offsets[0];
|
||||||
process->WriteMemory(args_addr_ref + first_offset, &fun_addr, 8, error);
|
process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
|
||||||
|
|
||||||
// FIXME: We will need to extend this for Variadic functions.
|
// FIXME: We will need to extend this for Variadic functions.
|
||||||
|
|
||||||
|
@ -350,13 +348,8 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
|
||||||
|
|
||||||
const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext());
|
const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext());
|
||||||
|
|
||||||
int byte_size = arg_scalar.GetByteSize();
|
if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error))
|
||||||
std::vector<uint8_t> buffer;
|
return false;
|
||||||
buffer.resize(byte_size);
|
|
||||||
DataExtractor value_data;
|
|
||||||
arg_scalar.GetData (value_data);
|
|
||||||
value_data.ExtractBytes(0, byte_size, process->GetByteOrder(), &buffer.front());
|
|
||||||
process->WriteMemory(args_addr_ref + offset, &buffer.front(), byte_size, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -420,8 +413,6 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
|
||||||
// Read the return value - it is the last field in the struct:
|
// Read the return value - it is the last field in the struct:
|
||||||
// FIXME: How does clang tell us there's no return value? We need to handle that case.
|
// FIXME: How does clang tell us there's no return value? We need to handle that case.
|
||||||
|
|
||||||
std::vector<uint8_t> data_buffer;
|
|
||||||
data_buffer.resize(m_return_size);
|
|
||||||
Process *process = exe_ctx.process;
|
Process *process = exe_ctx.process;
|
||||||
|
|
||||||
if (process == NULL)
|
if (process == NULL)
|
||||||
|
@ -430,25 +421,13 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
size_t bytes_read = process->ReadMemory(args_addr + m_return_offset, &data_buffer.front(), m_return_size, error);
|
ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error);
|
||||||
|
|
||||||
if (bytes_read == 0)
|
if (error.Fail())
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_read < m_return_size)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
DataExtractor data(&data_buffer.front(), m_return_size, process->GetByteOrder(), process->GetAddressByteSize());
|
|
||||||
// FIXME: Assuming an integer scalar for now:
|
|
||||||
|
|
||||||
uint32_t offset = 0;
|
|
||||||
uint64_t return_integer = data.GetMaxU64(&offset, m_return_size);
|
|
||||||
|
|
||||||
ret_value.SetContext (Value::eContextTypeClangType, m_function_return_qual_type);
|
ret_value.SetContext (Value::eContextTypeClangType, m_function_return_qual_type);
|
||||||
ret_value.SetValueType(Value::eValueTypeScalar);
|
ret_value.SetValueType(Value::eValueTypeScalar);
|
||||||
ret_value.GetScalar() = return_integer;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,29 +269,11 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
|
||||||
{
|
{
|
||||||
// Arguments 5 on up are on the stack
|
// Arguments 5 on up are on the stack
|
||||||
const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
|
const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
|
||||||
if (arg_byte_size <= sizeof(uint64_t))
|
Error error;
|
||||||
{
|
if (!thread.GetProcess().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error))
|
||||||
uint8_t arg_data[sizeof(uint64_t)];
|
return false;
|
||||||
Error error;
|
|
||||||
thread.GetProcess().ReadMemory(sp, arg_data, sizeof(arg_data), error);
|
|
||||||
DataExtractor arg_data_extractor (arg_data, sizeof(arg_data),
|
|
||||||
thread.GetProcess().GetTarget().GetArchitecture().GetByteOrder(),
|
|
||||||
thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize());
|
|
||||||
uint32_t offset = 0;
|
|
||||||
if (arg_byte_size <= 4)
|
|
||||||
value->GetScalar() = arg_data_extractor.GetMaxU32 (&offset, arg_byte_size);
|
|
||||||
else if (arg_byte_size <= 8)
|
|
||||||
value->GetScalar() = arg_data_extractor.GetMaxU64 (&offset, arg_byte_size);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (offset == 0 || offset == UINT32_MAX)
|
sp += arg_byte_size;
|
||||||
return false;
|
|
||||||
|
|
||||||
if (is_signed)
|
|
||||||
value->GetScalar().SignExtend (bit_width);
|
|
||||||
sp += arg_byte_size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -397,84 +397,22 @@ ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ReadIntegerArgument(Scalar &scalar,
|
static bool
|
||||||
unsigned int bit_width,
|
ReadIntegerArgument (Scalar &scalar,
|
||||||
bool is_signed,
|
unsigned int bit_width,
|
||||||
Process &process,
|
bool is_signed,
|
||||||
addr_t ¤t_stack_argument)
|
Process &process,
|
||||||
|
addr_t ¤t_stack_argument)
|
||||||
{
|
{
|
||||||
if (bit_width > 64)
|
|
||||||
return false; // Scalar can't hold large integer arguments
|
|
||||||
|
|
||||||
uint64_t arg_contents;
|
uint32_t byte_size = (bit_width + (8-1))/8;
|
||||||
uint32_t read_data;
|
|
||||||
Error error;
|
Error error;
|
||||||
|
if (process.ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
|
||||||
if (bit_width > 32)
|
|
||||||
{
|
{
|
||||||
if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
|
current_stack_argument += byte_size;
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
arg_contents = read_data;
|
|
||||||
|
|
||||||
if (process.ReadMemory(current_stack_argument + 4, &read_data, sizeof(read_data), error) != sizeof(read_data))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
arg_contents |= ((uint64_t)read_data) << 32;
|
|
||||||
|
|
||||||
current_stack_argument += 8;
|
|
||||||
}
|
}
|
||||||
else {
|
return false;
|
||||||
if (process.ReadMemory(current_stack_argument, &read_data, sizeof(read_data), error) != sizeof(read_data))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
arg_contents = read_data;
|
|
||||||
|
|
||||||
current_stack_argument += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_signed)
|
|
||||||
{
|
|
||||||
switch (bit_width)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
case 8:
|
|
||||||
scalar = (int8_t)(arg_contents & 0xff);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
scalar = (int16_t)(arg_contents & 0xffff);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
scalar = (int32_t)(arg_contents & 0xffffffff);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
scalar = (int64_t)arg_contents;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (bit_width)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
case 8:
|
|
||||||
scalar = (uint8_t)(arg_contents & 0xff);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
scalar = (uint16_t)(arg_contents & 0xffff);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
scalar = (uint32_t)(arg_contents & 0xffffffff);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
scalar = (uint64_t)arg_contents;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -194,69 +194,24 @@ static bool ReadIntegerArgument(Scalar &scalar,
|
||||||
if (bit_width > 64)
|
if (bit_width > 64)
|
||||||
return false; // Scalar can't hold large integer arguments
|
return false; // Scalar can't hold large integer arguments
|
||||||
|
|
||||||
uint64_t arg_contents;
|
|
||||||
|
|
||||||
if (current_argument_register < 6)
|
if (current_argument_register < 6)
|
||||||
{
|
{
|
||||||
arg_contents = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
|
scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
|
||||||
current_argument_register++;
|
current_argument_register++;
|
||||||
|
if (is_signed)
|
||||||
|
scalar.SignExtend (bit_width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint8_t arg_data[sizeof(arg_contents)];
|
uint32_t byte_size = (bit_width + (8-1))/8;
|
||||||
Error error;
|
Error error;
|
||||||
thread.GetProcess().ReadMemory(current_stack_argument, arg_data, sizeof(arg_contents), error);
|
if (thread.GetProcess().ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
|
||||||
DataExtractor arg_data_extractor (arg_data, sizeof(arg_contents),
|
|
||||||
thread.GetProcess().GetTarget().GetArchitecture().GetByteOrder(),
|
|
||||||
thread.GetProcess().GetTarget().GetArchitecture().GetAddressByteSize());
|
|
||||||
uint32_t offset = 0;
|
|
||||||
arg_contents = arg_data_extractor.GetMaxU64(&offset, bit_width / 8);
|
|
||||||
if (!offset)
|
|
||||||
return false;
|
|
||||||
current_stack_argument += (bit_width / 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_signed)
|
|
||||||
{
|
|
||||||
switch (bit_width)
|
|
||||||
{
|
{
|
||||||
default:
|
current_stack_argument += byte_size;
|
||||||
return false;
|
return true;
|
||||||
case 8:
|
|
||||||
scalar = (int8_t)(arg_contents & 0xff);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
scalar = (int16_t)(arg_contents & 0xffff);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
scalar = (int32_t)(arg_contents & 0xffffffff);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
scalar = (int64_t)arg_contents;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (bit_width)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
case 8:
|
|
||||||
scalar = (uint8_t)(arg_contents & 0xffu);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
scalar = (uint16_t)(arg_contents & 0xffffu);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
scalar = (uint32_t)(arg_contents & 0xffffffffu);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
scalar = (uint64_t)arg_contents;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &object)
|
||||||
|
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
AppleObjCRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope)
|
AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionContextScope *exe_scope)
|
||||||
{
|
{
|
||||||
if (!m_read_objc_library)
|
if (!m_read_objc_library)
|
||||||
return false;
|
return false;
|
||||||
|
@ -88,7 +88,7 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionCont
|
||||||
clang::QualType value_type = clang::QualType::getFromOpaquePtr (value.GetClangType());
|
clang::QualType value_type = clang::QualType::getFromOpaquePtr (value.GetClangType());
|
||||||
if (!value_type->isObjCObjectPointerType())
|
if (!value_type->isObjCObjectPointerType())
|
||||||
{
|
{
|
||||||
str.Printf ("Value doesn't point to an ObjC object.\n");
|
strm.Printf ("Value doesn't point to an ObjC object.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,35 +138,22 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionCont
|
||||||
ret);
|
ret);
|
||||||
if (results != eExecutionCompleted)
|
if (results != eExecutionCompleted)
|
||||||
{
|
{
|
||||||
str.Printf("Error evaluating Print Object function: %d.\n", results);
|
strm.Printf("Error evaluating Print Object function: %d.\n", results);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
|
addr_t result_ptr = ret.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
|
||||||
|
|
||||||
// FIXME: poor man's strcpy - we should have a "read memory as string interface...
|
char buf[512];
|
||||||
|
size_t cstr_len = 0;
|
||||||
Error error;
|
size_t curr_len = sizeof(buf);
|
||||||
std::vector<char> desc;
|
while (curr_len == sizeof(buf))
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
char byte = '\0';
|
curr_len = exe_ctx.process->ReadCStringFromMemory(result_ptr + cstr_len, buf, sizeof(buf));
|
||||||
if (exe_ctx.process->ReadMemory(result_ptr + desc.size(), &byte, 1, error) != 1)
|
strm.Write (buf, curr_len);
|
||||||
break;
|
cstr_len += curr_len;
|
||||||
|
|
||||||
desc.push_back(byte);
|
|
||||||
|
|
||||||
if (byte == '\0')
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return cstr_len > 0;
|
||||||
if (!desc.empty())
|
|
||||||
{
|
|
||||||
str.PutCString(&desc.front());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Address *
|
Address *
|
||||||
|
|
|
@ -220,9 +220,9 @@ AppleObjCRuntimeV2::RunFunctionToFindClassName(lldb::addr_t object_addr, Thread
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
||||||
lldb::DynamicValueType use_dynamic,
|
lldb::DynamicValueType use_dynamic,
|
||||||
TypeAndOrName &class_type_or_name,
|
TypeAndOrName &class_type_or_name,
|
||||||
Address &address)
|
Address &address)
|
||||||
{
|
{
|
||||||
// The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
|
// The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
|
||||||
assert (in_value.GetUpdatePoint().GetProcess() == m_process);
|
assert (in_value.GetUpdatePoint().GetProcess() == m_process);
|
||||||
|
@ -244,9 +244,11 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
||||||
Target *target = m_process->CalculateTarget();
|
Target *target = m_process->CalculateTarget();
|
||||||
|
|
||||||
char memory_buffer[16];
|
char memory_buffer[16];
|
||||||
DataExtractor data(memory_buffer, sizeof(memory_buffer),
|
DataExtractor data (memory_buffer,
|
||||||
m_process->GetByteOrder(),
|
sizeof(memory_buffer),
|
||||||
m_process->GetAddressByteSize());
|
m_process->GetByteOrder(),
|
||||||
|
m_process->GetAddressByteSize());
|
||||||
|
|
||||||
size_t address_byte_size = m_process->GetAddressByteSize();
|
size_t address_byte_size = m_process->GetAddressByteSize();
|
||||||
Error error;
|
Error error;
|
||||||
size_t bytes_read = m_process->ReadMemory (original_ptr,
|
size_t bytes_read = m_process->ReadMemory (original_ptr,
|
||||||
|
@ -258,10 +260,10 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t offset_ptr = 0;
|
uint32_t offset = 0;
|
||||||
lldb::addr_t isa_addr = data.GetAddress (&offset_ptr);
|
lldb::addr_t isa_addr = data.GetAddress (&offset);
|
||||||
|
|
||||||
if (offset_ptr == 0)
|
if (offset == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make sure the class address is readable, otherwise this is not a good object:
|
// Make sure the class address is readable, otherwise this is not a good object:
|
||||||
|
|
|
@ -340,8 +340,8 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
|
||||||
if (m_objc_module_sp)
|
if (m_objc_module_sp)
|
||||||
{
|
{
|
||||||
ConstString trampoline_name ("gdb_objc_trampolines");
|
ConstString trampoline_name ("gdb_objc_trampolines");
|
||||||
const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(trampoline_name,
|
const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
|
||||||
eSymbolTypeData);
|
eSymbolTypeData);
|
||||||
if (trampoline_symbol != NULL)
|
if (trampoline_symbol != NULL)
|
||||||
{
|
{
|
||||||
if (!trampoline_symbol->GetValue().IsValid())
|
if (!trampoline_symbol->GetValue().IsValid())
|
||||||
|
@ -353,18 +353,17 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
|
||||||
|
|
||||||
// Next look up the "changed" symbol and set a breakpoint on that...
|
// Next look up the "changed" symbol and set a breakpoint on that...
|
||||||
ConstString changed_name ("gdb_objc_trampolines_changed");
|
ConstString changed_name ("gdb_objc_trampolines_changed");
|
||||||
const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(changed_name,
|
const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
|
||||||
eSymbolTypeCode);
|
eSymbolTypeCode);
|
||||||
if (changed_symbol != NULL)
|
if (changed_symbol != NULL)
|
||||||
{
|
{
|
||||||
if (!changed_symbol->GetValue().IsValid())
|
if (!changed_symbol->GetValue().IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
lldb::addr_t changed_addr = changed_symbol->GetValue().GetLoadAddress(&target);
|
lldb::addr_t changed_addr = changed_symbol->GetValue().GetOpcodeLoadAddress (&target);
|
||||||
if (changed_addr != LLDB_INVALID_ADDRESS)
|
if (changed_addr != LLDB_INVALID_ADDRESS)
|
||||||
{
|
{
|
||||||
BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr,
|
BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true);
|
||||||
true);
|
|
||||||
if (trampolines_changed_bp_sp != NULL)
|
if (trampolines_changed_bp_sp != NULL)
|
||||||
{
|
{
|
||||||
m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
|
m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
|
||||||
|
@ -427,18 +426,11 @@ AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
|
||||||
m_regions.clear();
|
m_regions.clear();
|
||||||
if (!InitializeVTableSymbols())
|
if (!InitializeVTableSymbols())
|
||||||
return false;
|
return false;
|
||||||
char memory_buffer[8];
|
|
||||||
DataExtractor data(memory_buffer, sizeof(memory_buffer),
|
|
||||||
m_process_sp->GetByteOrder(),
|
|
||||||
m_process_sp->GetAddressByteSize());
|
|
||||||
Error error;
|
Error error;
|
||||||
size_t bytes_read = m_process_sp->ReadMemory (m_trampoline_header, memory_buffer, m_process_sp->GetAddressByteSize(), error);
|
lldb::addr_t region_addr = m_process_sp->ReadPointerFromMemory (m_trampoline_header, error);
|
||||||
if (bytes_read != m_process_sp->GetAddressByteSize())
|
if (error.Success())
|
||||||
return false;
|
return ReadRegions (region_addr);
|
||||||
|
return false;
|
||||||
uint32_t offset_ptr = 0;
|
|
||||||
lldb::addr_t region_addr = data.GetPointer(&offset_ptr);
|
|
||||||
return ReadRegions (region_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -535,13 +527,13 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (ProcessSP process_sp, Mo
|
||||||
const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
|
const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
|
||||||
|
|
||||||
if (class_getMethodImplementation)
|
if (class_getMethodImplementation)
|
||||||
m_impl_fn_addr = class_getMethodImplementation->GetValue().GetLoadAddress(target);
|
m_impl_fn_addr = class_getMethodImplementation->GetValue().GetOpcodeLoadAddress (target);
|
||||||
if (class_getMethodImplementation_stret)
|
if (class_getMethodImplementation_stret)
|
||||||
m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetLoadAddress(target);
|
m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetOpcodeLoadAddress (target);
|
||||||
if (msg_forward)
|
if (msg_forward)
|
||||||
m_msg_forward_addr = msg_forward->GetValue().GetLoadAddress(target);
|
m_msg_forward_addr = msg_forward->GetValue().GetOpcodeLoadAddress(target);
|
||||||
if (msg_forward_stret)
|
if (msg_forward_stret)
|
||||||
m_msg_forward_stret_addr = msg_forward_stret->GetValue().GetLoadAddress(target);
|
m_msg_forward_stret_addr = msg_forward_stret->GetValue().GetOpcodeLoadAddress(target);
|
||||||
|
|
||||||
// FIXME: Do some kind of logging here.
|
// FIXME: Do some kind of logging here.
|
||||||
if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
|
if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
|
||||||
|
|
|
@ -1708,29 +1708,36 @@ Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &err
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
Process::ReadUnsignedInteger (lldb::addr_t vm_addr, size_t integer_byte_size, Error &error)
|
Process::ReadUnsignedIntegerFromMemory (lldb::addr_t vm_addr, size_t integer_byte_size, uint64_t fail_value, Error &error)
|
||||||
{
|
{
|
||||||
if (integer_byte_size > sizeof(uint64_t))
|
Scalar scalar;
|
||||||
{
|
if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, false, scalar, error))
|
||||||
error.SetErrorString ("unsupported integer size");
|
return scalar.ULongLong(fail_value);
|
||||||
}
|
return fail_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_t
|
||||||
|
Process::ReadPointerFromMemory (lldb::addr_t vm_addr, Error &error)
|
||||||
|
{
|
||||||
|
Scalar scalar;
|
||||||
|
if (ReadScalarIntegerFromMemory(vm_addr, GetAddressByteSize(), false, scalar, error))
|
||||||
|
return scalar.ULongLong(LLDB_INVALID_ADDRESS);
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Process::WritePointerToMemory (lldb::addr_t vm_addr,
|
||||||
|
lldb::addr_t ptr_value,
|
||||||
|
Error &error)
|
||||||
|
{
|
||||||
|
Scalar scalar;
|
||||||
|
const uint32_t addr_byte_size = GetAddressByteSize();
|
||||||
|
if (addr_byte_size <= 4)
|
||||||
|
scalar = (uint32_t)ptr_value;
|
||||||
else
|
else
|
||||||
{
|
scalar = ptr_value;
|
||||||
uint8_t tmp[sizeof(uint64_t)];
|
return WriteScalarToMemory(vm_addr, scalar, addr_byte_size, error) == addr_byte_size;
|
||||||
DataExtractor data (tmp,
|
|
||||||
integer_byte_size,
|
|
||||||
m_target.GetArchitecture().GetByteOrder(),
|
|
||||||
m_target.GetArchitecture().GetAddressByteSize());
|
|
||||||
if (ReadMemory (vm_addr, tmp, integer_byte_size, error) == integer_byte_size)
|
|
||||||
{
|
|
||||||
uint32_t offset = 0;
|
|
||||||
return data.GetMaxU64 (&offset, integer_byte_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Any plug-in that doesn't return success a memory read with the number
|
|
||||||
// of bytes that were requested should be setting the error
|
|
||||||
assert (error.Fail());
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
@ -1831,6 +1838,61 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
|
||||||
|
|
||||||
return bytes_written;
|
return bytes_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Process::WriteScalarToMemory (addr_t addr, const Scalar &scalar, uint32_t byte_size, Error &error)
|
||||||
|
{
|
||||||
|
if (byte_size == UINT32_MAX)
|
||||||
|
byte_size = scalar.GetByteSize();
|
||||||
|
if (byte_size > 0)
|
||||||
|
{
|
||||||
|
uint8_t buf[32];
|
||||||
|
const size_t mem_size = scalar.GetAsMemoryData (buf, byte_size, GetByteOrder(), error);
|
||||||
|
if (mem_size > 0)
|
||||||
|
return WriteMemory(addr, buf, mem_size, error);
|
||||||
|
else
|
||||||
|
error.SetErrorString ("failed to get scalar as memory data");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error.SetErrorString ("invalid scalar value");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Process::ReadScalarIntegerFromMemory (addr_t addr,
|
||||||
|
uint32_t byte_size,
|
||||||
|
bool is_signed,
|
||||||
|
Scalar &scalar,
|
||||||
|
Error &error)
|
||||||
|
{
|
||||||
|
uint64_t uval;
|
||||||
|
|
||||||
|
if (byte_size <= sizeof(uval))
|
||||||
|
{
|
||||||
|
size_t bytes_read = ReadMemory (addr, &uval, byte_size, error);
|
||||||
|
if (bytes_read == byte_size)
|
||||||
|
{
|
||||||
|
DataExtractor data (&uval, sizeof(uval), GetByteOrder(), GetAddressByteSize());
|
||||||
|
uint32_t offset = 0;
|
||||||
|
if (byte_size <= 4)
|
||||||
|
scalar = data.GetMaxU32 (&offset, byte_size);
|
||||||
|
else
|
||||||
|
scalar = data.GetMaxU64 (&offset, byte_size);
|
||||||
|
|
||||||
|
if (is_signed)
|
||||||
|
scalar.SignExtend(byte_size * 8);
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error.SetErrorStringWithFormat ("byte size of %u is too large for integer scalar type", byte_size);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define USE_ALLOCATE_MEMORY_CACHE 1
|
#define USE_ALLOCATE_MEMORY_CACHE 1
|
||||||
addr_t
|
addr_t
|
||||||
Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
|
Process::AllocateMemory(size_t size, uint32_t permissions, Error &error)
|
||||||
|
|
|
@ -1014,6 +1014,81 @@ Target::EvaluateExpression
|
||||||
return execution_results;
|
return execution_results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lldb::addr_t
|
||||||
|
Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const
|
||||||
|
{
|
||||||
|
addr_t code_addr = load_addr;
|
||||||
|
switch (m_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
case llvm::Triple::thumb:
|
||||||
|
switch (addr_class)
|
||||||
|
{
|
||||||
|
case eAddressClassData:
|
||||||
|
case eAddressClassDebug:
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
|
||||||
|
case eAddressClassUnknown:
|
||||||
|
case eAddressClassInvalid:
|
||||||
|
case eAddressClassCode:
|
||||||
|
case eAddressClassCodeAlternateISA:
|
||||||
|
case eAddressClassRuntime:
|
||||||
|
// Check if bit zero it no set?
|
||||||
|
if ((code_addr & 1ull) == 0)
|
||||||
|
{
|
||||||
|
// Bit zero isn't set, check if the address is a multiple of 2?
|
||||||
|
if (code_addr & 2ull)
|
||||||
|
{
|
||||||
|
// The address is a multiple of 2 so it must be thumb, set bit zero
|
||||||
|
code_addr |= 1ull;
|
||||||
|
}
|
||||||
|
else if (addr_class == eAddressClassCodeAlternateISA)
|
||||||
|
{
|
||||||
|
// We checked the address and the address claims to be the alternate ISA
|
||||||
|
// which means thumb, so set bit zero.
|
||||||
|
code_addr |= 1ull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return code_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
lldb::addr_t
|
||||||
|
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const
|
||||||
|
{
|
||||||
|
addr_t opcode_addr = load_addr;
|
||||||
|
switch (m_arch.GetMachine())
|
||||||
|
{
|
||||||
|
case llvm::Triple::arm:
|
||||||
|
case llvm::Triple::thumb:
|
||||||
|
switch (addr_class)
|
||||||
|
{
|
||||||
|
case eAddressClassData:
|
||||||
|
case eAddressClassDebug:
|
||||||
|
return LLDB_INVALID_ADDRESS;
|
||||||
|
|
||||||
|
case eAddressClassInvalid:
|
||||||
|
case eAddressClassUnknown:
|
||||||
|
case eAddressClassCode:
|
||||||
|
case eAddressClassCodeAlternateISA:
|
||||||
|
case eAddressClassRuntime:
|
||||||
|
opcode_addr &= ~(1ull);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return opcode_addr;
|
||||||
|
}
|
||||||
|
|
||||||
lldb::user_id_t
|
lldb::user_id_t
|
||||||
Target::AddStopHook (Target::StopHookSP &new_hook_sp)
|
Target::AddStopHook (Target::StopHookSP &new_hook_sp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress
|
||||||
m_addresses (),
|
m_addresses (),
|
||||||
m_break_ids ()
|
m_break_ids ()
|
||||||
{
|
{
|
||||||
m_addresses.push_back (address.GetLoadAddress(&m_thread.GetProcess().GetTarget()));
|
m_addresses.push_back (address.GetOpcodeLoadAddress (&m_thread.GetProcess().GetTarget()));
|
||||||
SetInitialBreakpoints();
|
SetInitialBreakpoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress
|
||||||
m_addresses (),
|
m_addresses (),
|
||||||
m_break_ids ()
|
m_break_ids ()
|
||||||
{
|
{
|
||||||
m_addresses.push_back(address);
|
m_addresses.push_back(m_thread.GetProcess().GetTarget().GetOpcodeLoadAddress(address));
|
||||||
SetInitialBreakpoints();
|
SetInitialBreakpoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPlanRunToAddress::ThreadPlanRunToAddress
|
ThreadPlanRunToAddress::ThreadPlanRunToAddress
|
||||||
(
|
(
|
||||||
Thread &thread,
|
Thread &thread,
|
||||||
std::vector<lldb::addr_t> &addresses,
|
const std::vector<lldb::addr_t> &addresses,
|
||||||
bool stop_others
|
bool stop_others
|
||||||
) :
|
) :
|
||||||
ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
|
ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
|
||||||
|
@ -69,6 +69,13 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress
|
||||||
m_addresses (addresses),
|
m_addresses (addresses),
|
||||||
m_break_ids ()
|
m_break_ids ()
|
||||||
{
|
{
|
||||||
|
// Convert all addressses into opcode addresses to make sure we set
|
||||||
|
// breakpoints at the correct address.
|
||||||
|
Target &target = thread.GetProcess().GetTarget();
|
||||||
|
std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
|
||||||
|
for (pos = m_addresses.begin(); pos != end; ++pos)
|
||||||
|
*pos = target.GetOpcodeLoadAddress (*pos);
|
||||||
|
|
||||||
SetInitialBreakpoints();
|
SetInitialBreakpoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -698,70 +698,3 @@ MachThread::GetName ()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
//const char *
|
|
||||||
//MachThread::GetDispatchQueueName()
|
|
||||||
//{
|
|
||||||
// if (GetIdentifierInfo ())
|
|
||||||
// {
|
|
||||||
// if (m_ident_info.dispatch_qaddr == 0)
|
|
||||||
// return NULL;
|
|
||||||
//
|
|
||||||
// uint8_t memory_buffer[8];
|
|
||||||
// DNBDataRef data(memory_buffer, sizeof(memory_buffer), false);
|
|
||||||
// ModuleSP module_sp(GetProcess()->GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib")));
|
|
||||||
// if (module_sp.get() == NULL)
|
|
||||||
// return NULL;
|
|
||||||
//
|
|
||||||
// lldb::addr_t dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
|
|
||||||
// const Symbol *dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (ConstString("dispatch_queue_offsets"), eSymbolTypeData);
|
|
||||||
// if (dispatch_queue_offsets_symbol)
|
|
||||||
// dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetValue().GetLoadAddress(GetProcess());
|
|
||||||
//
|
|
||||||
// if (dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
|
|
||||||
// return NULL;
|
|
||||||
//
|
|
||||||
// // Excerpt from src/queue_private.h
|
|
||||||
// struct dispatch_queue_offsets_s
|
|
||||||
// {
|
|
||||||
// uint16_t dqo_version;
|
|
||||||
// uint16_t dqo_label;
|
|
||||||
// uint16_t dqo_label_size;
|
|
||||||
// } dispatch_queue_offsets;
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// if (GetProcess()->ReadMemory (dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets)) == sizeof(dispatch_queue_offsets))
|
|
||||||
// {
|
|
||||||
// uint32_t data_offset = 0;
|
|
||||||
// if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
|
|
||||||
// {
|
|
||||||
// if (GetProcess()->ReadMemory (m_ident_info.dispatch_qaddr, &memory_buffer, data.GetAddressByteSize()) == data.GetAddressByteSize())
|
|
||||||
// {
|
|
||||||
// data_offset = 0;
|
|
||||||
// lldb::addr_t queue_addr = data.GetAddress(&data_offset);
|
|
||||||
// lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
|
|
||||||
// const size_t chunk_size = 32;
|
|
||||||
// uint32_t label_pos = 0;
|
|
||||||
// m_dispatch_queue_name.resize(chunk_size, '\0');
|
|
||||||
// while (1)
|
|
||||||
// {
|
|
||||||
// size_t bytes_read = GetProcess()->ReadMemory (label_addr + label_pos, &m_dispatch_queue_name[label_pos], chunk_size);
|
|
||||||
//
|
|
||||||
// if (bytes_read <= 0)
|
|
||||||
// break;
|
|
||||||
//
|
|
||||||
// if (m_dispatch_queue_name.find('\0', label_pos) != std::string::npos)
|
|
||||||
// break;
|
|
||||||
// label_pos += bytes_read;
|
|
||||||
// }
|
|
||||||
// m_dispatch_queue_name.erase(m_dispatch_queue_name.find('\0'));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (m_dispatch_queue_name.empty())
|
|
||||||
// return NULL;
|
|
||||||
// return m_dispatch_queue_name.c_str();
|
|
||||||
//}
|
|
||||||
|
|
Loading…
Reference in New Issue