Skip to content

[lldb][API] Add Find(Ranges)InMemory() to Process SB API #96569

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading