Skip to content

Commit

Permalink
[lldb][API] Add Find(Ranges)InMemory() to Process SB API (#95007)
Browse files Browse the repository at this point in the history
Test Plan:
llvm-lit
llvm-project/lldb/test/API/python_api/find_in_memory/TestFindInMemory.py

llvm-project/lldb/test/API/python_api/find_in_memory/TestFindRangesInMemory.py

Reviewers: clayborg

Tasks: lldb
  • Loading branch information
mbucko committed Jun 24, 2024
1 parent db9e9ea commit 10bd5ad
Show file tree
Hide file tree
Showing 11 changed files with 661 additions and 6 deletions.
3 changes: 2 additions & 1 deletion lldb/bindings/python/python-typemaps.swig
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ AND call SWIG_fail at the same time, because it will result in a double free.
}
// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput.
%typemap(in) (const void *buf, size_t size),
(const void *data, size_t data_len) {
(const void *data, size_t data_len),
(const void *buf, uint64_t size) {
if (PythonString::Check($input)) {
PythonString str(PyRefType::Borrowed, $input);
$1 = (void *)str.GetString().data();
Expand Down
10 changes: 10 additions & 0 deletions lldb/include/lldb/API/SBProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,16 @@ class LLDB_API SBProcess {

lldb::addr_t ReadPointerFromMemory(addr_t addr, lldb::SBError &error);

lldb::SBAddressRangeList FindRangesInMemory(const void *buf, uint64_t size,
const SBAddressRangeList &ranges,
uint32_t alignment,
uint32_t max_matches,
SBError &error);

lldb::addr_t FindInMemory(const void *buf, uint64_t size,
const SBAddressRange &range, uint32_t alignment,
SBError &error);

// Events
static lldb::StateType GetStateFromEvent(const lldb::SBEvent &event);

Expand Down
4 changes: 4 additions & 0 deletions lldb/include/lldb/Core/AddressRangeListImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include <cstddef>

namespace lldb {
class SBAddressRangeList;
class SBBlock;
class SBProcess;
}

namespace lldb_private {
Expand All @@ -39,7 +41,9 @@ class AddressRangeListImpl {
lldb_private::AddressRange GetAddressRangeAtIndex(size_t index);

private:
friend class lldb::SBAddressRangeList;
friend class lldb::SBBlock;
friend class lldb::SBProcess;

AddressRanges &ref();

Expand Down
14 changes: 14 additions & 0 deletions lldb/include/lldb/Target/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -2685,6 +2685,15 @@ void PruneThreadPlans();
lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
const uint8_t *buf, size_t size);

AddressRanges FindRangesInMemory(const uint8_t *buf, uint64_t size,
const AddressRanges &ranges,
size_t alignment, size_t max_matches,
Status &error);

lldb::addr_t FindInMemory(const uint8_t *buf, uint64_t size,
const AddressRange &range, size_t alignment,
Status &error);

protected:
friend class Trace;

Expand Down Expand Up @@ -2800,6 +2809,11 @@ void PruneThreadPlans();
virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
Status &error) = 0;

virtual void DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr,
const uint8_t *buf, size_t size,
AddressRanges &matches, size_t alignment,
size_t max_matches);

/// DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has
/// removed non address bits from load_addr. Override this method in
/// subclasses of Process.
Expand Down
58 changes: 53 additions & 5 deletions lldb/source/API/SBProcess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"

#include "lldb/Core/AddressRangeListImpl.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
Expand All @@ -26,6 +27,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
Expand Down Expand Up @@ -320,8 +322,8 @@ void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const {
if (process_sp) {
StreamFile stream(out);
const StateType event_state = SBProcess::GetStateFromEvent(event);
stream.Printf("Process %" PRIu64 " %s\n",
process_sp->GetID(), SBDebugger::StateAsCString(event_state));
stream.Printf("Process %" PRIu64 " %s\n", process_sp->GetID(),
SBDebugger::StateAsCString(event_state));
}
}

Expand Down Expand Up @@ -378,7 +380,6 @@ bool SBProcess::SetSelectedThreadByIndexID(uint32_t index_id) {
ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID(index_id);
}


return ret_val;
}

Expand Down Expand Up @@ -546,7 +547,6 @@ ByteOrder SBProcess::GetByteOrder() const {
if (process_sp)
byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder();


return byteOrder;
}

Expand All @@ -558,7 +558,6 @@ uint32_t SBProcess::GetAddressByteSize() const {
if (process_sp)
size = process_sp->GetTarget().GetArchitecture().GetAddressByteSize();


return size;
}

Expand Down Expand Up @@ -810,6 +809,55 @@ const char *SBProcess::GetBroadcasterClass() {
return ConstString(Process::GetStaticBroadcasterClass()).AsCString();
}

lldb::SBAddressRangeList SBProcess::FindRangesInMemory(
const void *buf, uint64_t size, const SBAddressRangeList &ranges,
uint32_t alignment, uint32_t max_matches, SBError &error) {
LLDB_INSTRUMENT_VA(this, buf, size, ranges, alignment, max_matches, error);

lldb::SBAddressRangeList matches;

ProcessSP process_sp(GetSP());
if (!process_sp) {
error.SetErrorString("SBProcess is invalid");
return matches;
}
Process::StopLocker stop_locker;
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
error.SetErrorString("process is running");
return matches;
}
std::lock_guard<std::recursive_mutex> guard(
process_sp->GetTarget().GetAPIMutex());
matches.m_opaque_up->ref() = process_sp->FindRangesInMemory(
reinterpret_cast<const uint8_t *>(buf), size, ranges.ref().ref(),
alignment, max_matches, error.ref());
return matches;
}

lldb::addr_t SBProcess::FindInMemory(const void *buf, uint64_t size,
const SBAddressRange &range,
uint32_t alignment, SBError &error) {
LLDB_INSTRUMENT_VA(this, buf, size, range, alignment, error);

ProcessSP process_sp(GetSP());

if (!process_sp) {
error.SetErrorString("SBProcess is invalid");
return LLDB_INVALID_ADDRESS;
}

Process::StopLocker stop_locker;
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
error.SetErrorString("process is running");
return LLDB_INVALID_ADDRESS;
}

std::lock_guard<std::recursive_mutex> guard(
process_sp->GetTarget().GetAPIMutex());
return process_sp->FindInMemory(reinterpret_cast<const uint8_t *>(buf), size,
range.ref(), alignment, error.ref());
}

size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
SBError &sb_error) {
LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);
Expand Down
123 changes: 123 additions & 0 deletions lldb/source/Target/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2007,6 +2007,129 @@ size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) {
}
}

void Process::DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr,
const uint8_t *buf, size_t size,
AddressRanges &matches, size_t alignment,
size_t max_matches) {
// Inputs are already validated in FindInMemory() functions.
assert(buf != nullptr);
assert(size > 0);
assert(alignment > 0);
assert(max_matches > 0);
assert(start_addr != LLDB_INVALID_ADDRESS);
assert(end_addr != LLDB_INVALID_ADDRESS);
assert(start_addr < end_addr);

lldb::addr_t start = llvm::alignTo(start_addr, alignment);
while (matches.size() < max_matches && (start + size) < end_addr) {
const lldb::addr_t found_addr = FindInMemory(start, end_addr, buf, size);
if (found_addr == LLDB_INVALID_ADDRESS)
break;

if (found_addr % alignment) {
// We need to check the alignment because the FindInMemory uses a special
// algorithm to efficiently search mememory but doesn't support alignment.
start = llvm::alignTo(start + 1, alignment);
continue;
}

matches.emplace_back(found_addr, size);
start = found_addr + alignment;
}
}

AddressRanges Process::FindRangesInMemory(const uint8_t *buf, uint64_t size,
const AddressRanges &ranges,
size_t alignment, size_t max_matches,
Status &error) {
AddressRanges matches;
if (buf == nullptr) {
error.SetErrorString("buffer is null");
return matches;
}
if (size == 0) {
error.SetErrorString("buffer size is zero");
return matches;
}
if (ranges.empty()) {
error.SetErrorString("empty ranges");
return matches;
}
if (alignment == 0) {
error.SetErrorString("alignment must be greater than zero");
return matches;
}
if (max_matches == 0) {
error.SetErrorString("max_matches must be greater than zero");
return matches;
}

int resolved_ranges = 0;
Target &target = GetTarget();
for (size_t i = 0; i < ranges.size(); ++i) {
if (matches.size() >= max_matches)
break;
const AddressRange &range = ranges[i];
if (range.IsValid() == false)
continue;

const lldb::addr_t start_addr =
range.GetBaseAddress().GetLoadAddress(&target);
if (start_addr == LLDB_INVALID_ADDRESS)
continue;

++resolved_ranges;
const lldb::addr_t end_addr = start_addr + range.GetByteSize();
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment,
max_matches);
}

if (resolved_ranges > 0)
error.Clear();
else
error.SetErrorString("unable to resolve any ranges");

return matches;
}

lldb::addr_t Process::FindInMemory(const uint8_t *buf, uint64_t size,
const AddressRange &range, size_t alignment,
Status &error) {
if (buf == nullptr) {
error.SetErrorString("buffer is null");
return LLDB_INVALID_ADDRESS;
}
if (size == 0) {
error.SetErrorString("buffer size is zero");
return LLDB_INVALID_ADDRESS;
}
if (!range.IsValid()) {
error.SetErrorString("range is invalid");
return LLDB_INVALID_ADDRESS;
}
if (alignment == 0) {
error.SetErrorString("alignment must be greater than zero");
return LLDB_INVALID_ADDRESS;
}

Target &target = GetTarget();
const lldb::addr_t start_addr =
range.GetBaseAddress().GetLoadAddress(&target);
if (start_addr == LLDB_INVALID_ADDRESS) {
error.SetErrorString("range load address is invalid");
return LLDB_INVALID_ADDRESS;
}
const lldb::addr_t end_addr = start_addr + range.GetByteSize();

AddressRanges matches;
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment, 1);
if (matches.empty())
return LLDB_INVALID_ADDRESS;

error.Clear();
return matches[0].GetBaseAddress().GetLoadAddress(&target);
}

size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
Status &error) {
char buf[256];
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/python_api/find_in_memory/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
Loading

0 comments on commit 10bd5ad

Please sign in to comment.