diff options
| author | Greg Clayton <gclayton@apple.com> | 2011-05-22 22:46:53 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2011-05-22 22:46:53 +0000 |
| commit | f3ef3d2af95e8cd20bb9bd9aeceb24b4bf8107ca (patch) | |
| tree | 1614e0a38827a33bfae37302a3567c9cec8a391b /lldb/source/Target | |
| parent | 5c51177981f6e482dbf2a99700fa8bc801f53401 (diff) | |
| download | bcm5719-llvm-f3ef3d2af95e8cd20bb9bd9aeceb24b4bf8107ca.tar.gz bcm5719-llvm-f3ef3d2af95e8cd20bb9bd9aeceb24b4bf8107ca.zip | |
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
Diffstat (limited to 'lldb/source/Target')
| -rw-r--r-- | lldb/source/Target/Process.cpp | 104 | ||||
| -rw-r--r-- | lldb/source/Target/Target.cpp | 75 | ||||
| -rw-r--r-- | lldb/source/Target/ThreadPlanRunToAddress.cpp | 13 |
3 files changed, 168 insertions, 24 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 9a7e2c65a49..7acb87e5080 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1708,29 +1708,36 @@ Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &err } 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)) - { - error.SetErrorString ("unsupported integer size"); - } + Scalar scalar; + if (ReadScalarIntegerFromMemory(vm_addr, integer_byte_size, false, scalar, error)) + 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 - { - uint8_t tmp[sizeof(uint64_t)]; - 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; + scalar = ptr_value; + return WriteScalarToMemory(vm_addr, scalar, addr_byte_size, error) == addr_byte_size; } size_t @@ -1831,6 +1838,61 @@ Process::WriteMemory (addr_t addr, const void *buf, size_t size, Error &error) 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 addr_t Process::AllocateMemory(size_t size, uint32_t permissions, Error &error) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 387a3363113..56b798bed08 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1014,6 +1014,81 @@ Target::EvaluateExpression 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 Target::AddStopHook (Target::StopHookSP &new_hook_sp) { diff --git a/lldb/source/Target/ThreadPlanRunToAddress.cpp b/lldb/source/Target/ThreadPlanRunToAddress.cpp index 23945453f00..0779a1fd322 100644 --- a/lldb/source/Target/ThreadPlanRunToAddress.cpp +++ b/lldb/source/Target/ThreadPlanRunToAddress.cpp @@ -39,7 +39,7 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress m_addresses (), m_break_ids () { - m_addresses.push_back (address.GetLoadAddress(&m_thread.GetProcess().GetTarget())); + m_addresses.push_back (address.GetOpcodeLoadAddress (&m_thread.GetProcess().GetTarget())); SetInitialBreakpoints(); } @@ -54,14 +54,14 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress m_addresses (), m_break_ids () { - m_addresses.push_back(address); + m_addresses.push_back(m_thread.GetProcess().GetTarget().GetOpcodeLoadAddress(address)); SetInitialBreakpoints(); } ThreadPlanRunToAddress::ThreadPlanRunToAddress ( Thread &thread, - std::vector<lldb::addr_t> &addresses, + const std::vector<lldb::addr_t> &addresses, bool stop_others ) : ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), @@ -69,6 +69,13 @@ ThreadPlanRunToAddress::ThreadPlanRunToAddress m_addresses (addresses), 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(); } |

