Skip to content

Commit d6def31

Browse files
Miro BuckoAlexisPerry
authored andcommitted
[lldb][API] Add Find(Ranges)InMemory() to Process SB API (llvm#96569)
This is a second attempt to land llvm#95007 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
1 parent b208c58 commit d6def31

File tree

11 files changed

+697
-6
lines changed

11 files changed

+697
-6
lines changed

lldb/bindings/python/python-typemaps.swig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ AND call SWIG_fail at the same time, because it will result in a double free.
257257
}
258258
// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput.
259259
%typemap(in) (const void *buf, size_t size),
260-
(const void *data, size_t data_len) {
260+
(const void *data, size_t data_len),
261+
(const void *buf, uint64_t size) {
261262
if (PythonString::Check($input)) {
262263
PythonString str(PyRefType::Borrowed, $input);
263264
$1 = (void *)str.GetString().data();

lldb/include/lldb/API/SBProcess.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,16 @@ class LLDB_API SBProcess {
209209

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

212+
lldb::SBAddressRangeList FindRangesInMemory(const void *buf, uint64_t size,
213+
const SBAddressRangeList &ranges,
214+
uint32_t alignment,
215+
uint32_t max_matches,
216+
SBError &error);
217+
218+
lldb::addr_t FindInMemory(const void *buf, uint64_t size,
219+
const SBAddressRange &range, uint32_t alignment,
220+
SBError &error);
221+
212222
// Events
213223
static lldb::StateType GetStateFromEvent(const lldb::SBEvent &event);
214224

lldb/include/lldb/Core/AddressRangeListImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include <cstddef>
1414

1515
namespace lldb {
16+
class SBAddressRangeList;
1617
class SBBlock;
18+
class SBProcess;
1719
}
1820

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

4143
private:
44+
friend class lldb::SBAddressRangeList;
4245
friend class lldb::SBBlock;
46+
friend class lldb::SBProcess;
4347

4448
AddressRanges &ref();
4549

lldb/include/lldb/Target/Process.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,6 +2685,15 @@ void PruneThreadPlans();
26852685
lldb::addr_t FindInMemory(lldb::addr_t low, lldb::addr_t high,
26862686
const uint8_t *buf, size_t size);
26872687

2688+
AddressRanges FindRangesInMemory(const uint8_t *buf, uint64_t size,
2689+
const AddressRanges &ranges,
2690+
size_t alignment, size_t max_matches,
2691+
Status &error);
2692+
2693+
lldb::addr_t FindInMemory(const uint8_t *buf, uint64_t size,
2694+
const AddressRange &range, size_t alignment,
2695+
Status &error);
2696+
26882697
protected:
26892698
friend class Trace;
26902699

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

2812+
virtual void DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr,
2813+
const uint8_t *buf, size_t size,
2814+
AddressRanges &matches, size_t alignment,
2815+
size_t max_matches);
2816+
28032817
/// DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has
28042818
/// removed non address bits from load_addr. Override this method in
28052819
/// subclasses of Process.

lldb/source/API/SBProcess.cpp

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "lldb/lldb-defines.h"
1515
#include "lldb/lldb-types.h"
1616

17+
#include "lldb/Core/AddressRangeListImpl.h"
1718
#include "lldb/Core/Debugger.h"
1819
#include "lldb/Core/Module.h"
1920
#include "lldb/Core/PluginManager.h"
@@ -26,6 +27,7 @@
2627
#include "lldb/Target/Target.h"
2728
#include "lldb/Target/Thread.h"
2829
#include "lldb/Utility/Args.h"
30+
#include "lldb/Utility/LLDBLog.h"
2931
#include "lldb/Utility/ProcessInfo.h"
3032
#include "lldb/Utility/State.h"
3133
#include "lldb/Utility/Stream.h"
@@ -320,8 +322,8 @@ void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const {
320322
if (process_sp) {
321323
StreamFile stream(out);
322324
const StateType event_state = SBProcess::GetStateFromEvent(event);
323-
stream.Printf("Process %" PRIu64 " %s\n",
324-
process_sp->GetID(), SBDebugger::StateAsCString(event_state));
325+
stream.Printf("Process %" PRIu64 " %s\n", process_sp->GetID(),
326+
SBDebugger::StateAsCString(event_state));
325327
}
326328
}
327329

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

381-
382383
return ret_val;
383384
}
384385

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

549-
550550
return byteOrder;
551551
}
552552

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

561-
562561
return size;
563562
}
564563

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

812+
lldb::SBAddressRangeList SBProcess::FindRangesInMemory(
813+
const void *buf, uint64_t size, const SBAddressRangeList &ranges,
814+
uint32_t alignment, uint32_t max_matches, SBError &error) {
815+
LLDB_INSTRUMENT_VA(this, buf, size, ranges, alignment, max_matches, error);
816+
817+
lldb::SBAddressRangeList matches;
818+
819+
ProcessSP process_sp(GetSP());
820+
if (!process_sp) {
821+
error.SetErrorString("SBProcess is invalid");
822+
return matches;
823+
}
824+
Process::StopLocker stop_locker;
825+
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
826+
error.SetErrorString("process is running");
827+
return matches;
828+
}
829+
std::lock_guard<std::recursive_mutex> guard(
830+
process_sp->GetTarget().GetAPIMutex());
831+
matches.m_opaque_up->ref() = process_sp->FindRangesInMemory(
832+
reinterpret_cast<const uint8_t *>(buf), size, ranges.ref().ref(),
833+
alignment, max_matches, error.ref());
834+
return matches;
835+
}
836+
837+
lldb::addr_t SBProcess::FindInMemory(const void *buf, uint64_t size,
838+
const SBAddressRange &range,
839+
uint32_t alignment, SBError &error) {
840+
LLDB_INSTRUMENT_VA(this, buf, size, range, alignment, error);
841+
842+
ProcessSP process_sp(GetSP());
843+
844+
if (!process_sp) {
845+
error.SetErrorString("SBProcess is invalid");
846+
return LLDB_INVALID_ADDRESS;
847+
}
848+
849+
Process::StopLocker stop_locker;
850+
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
851+
error.SetErrorString("process is running");
852+
return LLDB_INVALID_ADDRESS;
853+
}
854+
855+
std::lock_guard<std::recursive_mutex> guard(
856+
process_sp->GetTarget().GetAPIMutex());
857+
return process_sp->FindInMemory(reinterpret_cast<const uint8_t *>(buf), size,
858+
range.ref(), alignment, error.ref());
859+
}
860+
813861
size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
814862
SBError &sb_error) {
815863
LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);

lldb/source/Target/Process.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,129 @@ size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) {
20072007
}
20082008
}
20092009

2010+
void Process::DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr,
2011+
const uint8_t *buf, size_t size,
2012+
AddressRanges &matches, size_t alignment,
2013+
size_t max_matches) {
2014+
// Inputs are already validated in FindInMemory() functions.
2015+
assert(buf != nullptr);
2016+
assert(size > 0);
2017+
assert(alignment > 0);
2018+
assert(max_matches > 0);
2019+
assert(start_addr != LLDB_INVALID_ADDRESS);
2020+
assert(end_addr != LLDB_INVALID_ADDRESS);
2021+
assert(start_addr < end_addr);
2022+
2023+
lldb::addr_t start = llvm::alignTo(start_addr, alignment);
2024+
while (matches.size() < max_matches && (start + size) < end_addr) {
2025+
const lldb::addr_t found_addr = FindInMemory(start, end_addr, buf, size);
2026+
if (found_addr == LLDB_INVALID_ADDRESS)
2027+
break;
2028+
2029+
if (found_addr % alignment) {
2030+
// We need to check the alignment because the FindInMemory uses a special
2031+
// algorithm to efficiently search mememory but doesn't support alignment.
2032+
start = llvm::alignTo(start + 1, alignment);
2033+
continue;
2034+
}
2035+
2036+
matches.emplace_back(found_addr, size);
2037+
start = found_addr + alignment;
2038+
}
2039+
}
2040+
2041+
AddressRanges Process::FindRangesInMemory(const uint8_t *buf, uint64_t size,
2042+
const AddressRanges &ranges,
2043+
size_t alignment, size_t max_matches,
2044+
Status &error) {
2045+
AddressRanges matches;
2046+
if (buf == nullptr) {
2047+
error.SetErrorString("buffer is null");
2048+
return matches;
2049+
}
2050+
if (size == 0) {
2051+
error.SetErrorString("buffer size is zero");
2052+
return matches;
2053+
}
2054+
if (ranges.empty()) {
2055+
error.SetErrorString("empty ranges");
2056+
return matches;
2057+
}
2058+
if (alignment == 0) {
2059+
error.SetErrorString("alignment must be greater than zero");
2060+
return matches;
2061+
}
2062+
if (max_matches == 0) {
2063+
error.SetErrorString("max_matches must be greater than zero");
2064+
return matches;
2065+
}
2066+
2067+
int resolved_ranges = 0;
2068+
Target &target = GetTarget();
2069+
for (size_t i = 0; i < ranges.size(); ++i) {
2070+
if (matches.size() >= max_matches)
2071+
break;
2072+
const AddressRange &range = ranges[i];
2073+
if (range.IsValid() == false)
2074+
continue;
2075+
2076+
const lldb::addr_t start_addr =
2077+
range.GetBaseAddress().GetLoadAddress(&target);
2078+
if (start_addr == LLDB_INVALID_ADDRESS)
2079+
continue;
2080+
2081+
++resolved_ranges;
2082+
const lldb::addr_t end_addr = start_addr + range.GetByteSize();
2083+
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment,
2084+
max_matches);
2085+
}
2086+
2087+
if (resolved_ranges > 0)
2088+
error.Clear();
2089+
else
2090+
error.SetErrorString("unable to resolve any ranges");
2091+
2092+
return matches;
2093+
}
2094+
2095+
lldb::addr_t Process::FindInMemory(const uint8_t *buf, uint64_t size,
2096+
const AddressRange &range, size_t alignment,
2097+
Status &error) {
2098+
if (buf == nullptr) {
2099+
error.SetErrorString("buffer is null");
2100+
return LLDB_INVALID_ADDRESS;
2101+
}
2102+
if (size == 0) {
2103+
error.SetErrorString("buffer size is zero");
2104+
return LLDB_INVALID_ADDRESS;
2105+
}
2106+
if (!range.IsValid()) {
2107+
error.SetErrorString("range is invalid");
2108+
return LLDB_INVALID_ADDRESS;
2109+
}
2110+
if (alignment == 0) {
2111+
error.SetErrorString("alignment must be greater than zero");
2112+
return LLDB_INVALID_ADDRESS;
2113+
}
2114+
2115+
Target &target = GetTarget();
2116+
const lldb::addr_t start_addr =
2117+
range.GetBaseAddress().GetLoadAddress(&target);
2118+
if (start_addr == LLDB_INVALID_ADDRESS) {
2119+
error.SetErrorString("range load address is invalid");
2120+
return LLDB_INVALID_ADDRESS;
2121+
}
2122+
const lldb::addr_t end_addr = start_addr + range.GetByteSize();
2123+
2124+
AddressRanges matches;
2125+
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment, 1);
2126+
if (matches.empty())
2127+
return LLDB_INVALID_ADDRESS;
2128+
2129+
error.Clear();
2130+
return matches[0].GetBaseAddress().GetLoadAddress(&target);
2131+
}
2132+
20102133
size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
20112134
Status &error) {
20122135
char buf[256];
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules

0 commit comments

Comments
 (0)