Skip to content

Commit da8f23b

Browse files
author
Miro Bucko
committed
[lldb][API] Add Find(Ranges)InMemory() to Process SB API
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 f26bc5f commit da8f23b

File tree

11 files changed

+509
-6
lines changed

11 files changed

+509
-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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ 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+
SBAddressRangeList &ranges,
214+
uint32_t alignment,
215+
uint32_t max_matches);
216+
217+
lldb::addr_t FindInMemory(const void *buf, uint64_t size,
218+
SBAddressRange &range, uint32_t alignment);
219+
212220
// Events
213221
static lldb::StateType GetStateFromEvent(const lldb::SBEvent &event);
214222

lldb/include/lldb/Core/AddressRangeListImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
namespace lldb {
1616
class SBBlock;
17+
class SBProcess;
1718
}
1819

1920
namespace lldb_private {
@@ -40,6 +41,7 @@ class AddressRangeListImpl {
4041

4142
private:
4243
friend class lldb::SBBlock;
44+
friend class lldb::SBProcess;
4345

4446
AddressRanges &ref();
4547

lldb/include/lldb/Target/Process.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2685,6 +2685,13 @@ 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+
Status FindInMemory(AddressRanges &matches, const uint8_t *buf, size_t size,
2689+
const AddressRanges &ranges, size_t alignment,
2690+
size_t max_count);
2691+
2692+
lldb::addr_t FindInMemory(const AddressRange &range, const uint8_t *buf,
2693+
size_t size, size_t alignment);
2694+
26882695
protected:
26892696
friend class Trace;
26902697

@@ -2800,6 +2807,10 @@ void PruneThreadPlans();
28002807
virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
28012808
Status &error) = 0;
28022809

2810+
void DoFindInMemory(lldb::addr_t start_addr, lldb::addr_t end_addr,
2811+
const uint8_t *buf, size_t size, AddressRanges &matches,
2812+
size_t alignment, size_t max_count);
2813+
28032814
/// DoGetMemoryRegionInfo is called by GetMemoryRegionInfo after it has
28042815
/// removed non address bits from load_addr. Override this method in
28052816
/// subclasses of Process.

lldb/source/API/SBProcess.cpp

Lines changed: 110 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,112 @@ const char *SBProcess::GetBroadcasterClass() {
810809
return ConstString(Process::GetStaticBroadcasterClass()).AsCString();
811810
}
812811

812+
lldb::SBAddressRangeList
813+
SBProcess::FindRangesInMemory(const void *buf, uint64_t size,
814+
SBAddressRangeList &ranges, uint32_t alignment,
815+
uint32_t max_matches) {
816+
LLDB_INSTRUMENT_VA(this, buf, size, ranges, alignment, max_matches);
817+
818+
Log *log = GetLog(LLDBLog::Process);
819+
lldb::SBAddressRangeList matches;
820+
821+
if (alignment == 0) {
822+
LLDB_LOGF(log, "SBProcess::%s allignmet is 0, Must be greater than 0.",
823+
__FUNCTION__);
824+
return matches;
825+
}
826+
827+
if (buf == nullptr) {
828+
LLDB_LOGF(log, "SBProcess::%s provided 'buffer' is nullptr.", __FUNCTION__);
829+
return matches;
830+
}
831+
832+
if (size == 0) {
833+
LLDB_LOGF(log, "SBProcess::%s buffer size is 0.", __FUNCTION__);
834+
return matches;
835+
}
836+
837+
if (ranges.GetSize() == 0) {
838+
LLDB_LOGF(log, "SBProcess::%s provided 'range' is invalid.", __FUNCTION__);
839+
return matches;
840+
}
841+
842+
ProcessSP process_sp(GetSP());
843+
if (!process_sp) {
844+
LLDB_LOGF(log, "SBProcess::%s SBProcess is invalid.", __FUNCTION__);
845+
return matches;
846+
}
847+
Process::StopLocker stop_locker;
848+
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
849+
LLDB_LOGF(
850+
log,
851+
"SBProcess::%s Cannot find process in memory while process is running.",
852+
__FUNCTION__);
853+
return matches;
854+
}
855+
std::lock_guard<std::recursive_mutex> guard(
856+
process_sp->GetTarget().GetAPIMutex());
857+
lldb::SBError error;
858+
error.ref() = process_sp->FindInMemory(
859+
matches.m_opaque_up->ref(), static_cast<const uint8_t *>(buf), size,
860+
ranges.m_opaque_up->ref(), alignment, max_matches);
861+
if (error.Fail()) {
862+
LLDB_LOGF(log, "SBProcess::%s failed to find pattern in memory.",
863+
__FUNCTION__);
864+
}
865+
return matches;
866+
}
867+
868+
lldb::addr_t SBProcess::FindInMemory(const void *buf, uint64_t size,
869+
SBAddressRange &range,
870+
uint32_t alignment) {
871+
LLDB_INSTRUMENT_VA(this, buf, size, range, alignment);
872+
873+
Log *log = GetLog(LLDBLog::Process);
874+
875+
if (alignment == 0) {
876+
LLDB_LOGF(log, "SBProcess::%s allignmet is 0, Must be greater than 0.",
877+
__FUNCTION__);
878+
return LLDB_INVALID_ADDRESS;
879+
}
880+
881+
if (buf == nullptr) {
882+
LLDB_LOGF(log, "SBProcess::%s provided 'buffer' is nullptr.", __FUNCTION__);
883+
return LLDB_INVALID_ADDRESS;
884+
}
885+
886+
if (size == 0) {
887+
LLDB_LOGF(log, "SBProcess::%s buffer size is 0.", __FUNCTION__);
888+
return LLDB_INVALID_ADDRESS;
889+
}
890+
891+
if (!range.IsValid()) {
892+
LLDB_LOGF(log, "SBProcess::%s provided 'range' is invalid.", __FUNCTION__);
893+
return LLDB_INVALID_ADDRESS;
894+
}
895+
896+
ProcessSP process_sp(GetSP());
897+
898+
if (!process_sp) {
899+
LLDB_LOGF(log, "SBProcess::%s SBProcess is invalid.", __FUNCTION__);
900+
return LLDB_INVALID_ADDRESS;
901+
}
902+
903+
Process::StopLocker stop_locker;
904+
if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
905+
LLDB_LOGF(
906+
log,
907+
"SBProcess::%s Cannot find process in memory while process is running.",
908+
__FUNCTION__);
909+
return LLDB_INVALID_ADDRESS;
910+
}
911+
912+
std::lock_guard<std::recursive_mutex> guard(
913+
process_sp->GetTarget().GetAPIMutex());
914+
return process_sp->FindInMemory(
915+
*range.m_opaque_up, static_cast<const uint8_t *>(buf), size, alignment);
916+
}
917+
813918
size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
814919
SBError &sb_error) {
815920
LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);

lldb/source/Target/Process.cpp

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,123 @@ 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_count) {
2014+
// Inputs are already validated in FindInMemory() functions.
2015+
assert(buf != nullptr);
2016+
assert(size > 0);
2017+
assert(alignment > 0);
2018+
assert(max_count > 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 = start_addr;
2024+
while (matches.size() < max_count && (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+
matches.emplace_back(found_addr, size);
2029+
start = found_addr + alignment;
2030+
}
2031+
}
2032+
2033+
Status Process::FindInMemory(AddressRanges &matches, const uint8_t *buf,
2034+
size_t size, const AddressRanges &ranges,
2035+
size_t alignment, size_t max_count) {
2036+
Status error;
2037+
if (alignment == 0) {
2038+
error.SetErrorStringWithFormat(
2039+
"invalid alignment %zu, must be greater than 0", alignment);
2040+
return error;
2041+
}
2042+
if (buf == nullptr) {
2043+
error.SetErrorStringWithFormat("buffer is null");
2044+
return error;
2045+
}
2046+
if (size == 0) {
2047+
error.SetErrorStringWithFormat("size is zero");
2048+
return error;
2049+
}
2050+
if (ranges.empty()) {
2051+
error.SetErrorStringWithFormat("ranges in empty");
2052+
return error;
2053+
}
2054+
if (max_count == 0) {
2055+
error.SetErrorStringWithFormat(
2056+
"invalid max_count %zu, must be greater than 0", max_count);
2057+
return error;
2058+
}
2059+
2060+
Target &target = GetTarget();
2061+
Log *log = GetLog(LLDBLog::Process);
2062+
for (size_t i = 0; i < ranges.size(); ++i) {
2063+
if (matches.size() >= max_count) {
2064+
break;
2065+
}
2066+
const AddressRange &range = ranges[i];
2067+
if (range.IsValid() == false) {
2068+
LLDB_LOGF(log, "Process::%s range is invalid", __FUNCTION__);
2069+
continue;
2070+
}
2071+
2072+
const lldb::addr_t start_addr =
2073+
range.GetBaseAddress().GetLoadAddress(&target);
2074+
if (start_addr == LLDB_INVALID_ADDRESS) {
2075+
LLDB_LOGF(log,
2076+
"Process::%s range load start address is invalid, skipping",
2077+
__FUNCTION__);
2078+
continue;
2079+
}
2080+
const lldb::addr_t end_addr = start_addr + range.GetByteSize();
2081+
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment,
2082+
max_count);
2083+
}
2084+
2085+
return Status();
2086+
}
2087+
2088+
lldb::addr_t Process::FindInMemory(const AddressRange &range,
2089+
const uint8_t *buf, size_t size,
2090+
size_t alignment) {
2091+
Log *log = GetLog(LLDBLog::Process);
2092+
if (buf == nullptr) {
2093+
LLDB_LOGF(log, "Process::%s buffer is null", __FUNCTION__);
2094+
return LLDB_INVALID_ADDRESS;
2095+
}
2096+
if (size == 0) {
2097+
LLDB_LOGF(log, "Process::%s size is zero", __FUNCTION__);
2098+
return LLDB_INVALID_ADDRESS;
2099+
}
2100+
if (alignment == 0) {
2101+
LLDB_LOGF(log, "Process::%s alignment is zero, returning", __FUNCTION__);
2102+
return LLDB_INVALID_ADDRESS;
2103+
}
2104+
if (range.IsValid() == false) {
2105+
LLDB_LOGF(log, "Process::%s range is invalid", __FUNCTION__);
2106+
return LLDB_INVALID_ADDRESS;
2107+
}
2108+
2109+
Target &target = GetTarget();
2110+
const lldb::addr_t start_addr =
2111+
range.GetBaseAddress().GetLoadAddress(&target);
2112+
if (start_addr == LLDB_INVALID_ADDRESS) {
2113+
LLDB_LOGF(log, "Process::%s range load start address is invalid, returning",
2114+
__FUNCTION__);
2115+
return LLDB_INVALID_ADDRESS;
2116+
}
2117+
const lldb::addr_t end_addr = start_addr + range.GetByteSize();
2118+
2119+
AddressRanges matches;
2120+
DoFindInMemory(start_addr, end_addr, buf, size, matches, alignment, 1);
2121+
if (matches.empty())
2122+
return LLDB_INVALID_ADDRESS;
2123+
2124+
return matches[0].GetBaseAddress().GetLoadAddress(&target);
2125+
}
2126+
20102127
size_t Process::ReadCStringFromMemory(addr_t addr, std::string &out_str,
20112128
Status &error) {
20122129
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)