https://github.com/labath updated https://github.com/llvm/llvm-project/pull/104193
>From a537a48c444e9dec3a85241d9726d6f3187a43cf Mon Sep 17 00:00:00 2001 From: Pavel Labath <pa...@labath.sk> Date: Wed, 14 Aug 2024 19:58:27 +0200 Subject: [PATCH] [WIP] memory find speedup+bugfix --- lldb/source/Target/Process.cpp | 58 ++++++------- .../memory/find/TestMemoryFind.py | 10 +++ .../API/functionalities/memory/find/main.cpp | 82 +++++++++++++++++-- 3 files changed, 108 insertions(+), 42 deletions(-) diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index e3c4f2ee398cc4..4e3d7651a066ec 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -114,33 +114,6 @@ class ProcessOptionValueProperties } }; -class ProcessMemoryIterator { -public: - ProcessMemoryIterator(Process &process, lldb::addr_t base) - : m_process(process), m_base_addr(base) {} - - bool IsValid() { return m_is_valid; } - - uint8_t operator[](lldb::addr_t offset) { - if (!IsValid()) - return 0; - - uint8_t retval = 0; - Status error; - if (0 == m_process.ReadMemory(m_base_addr + offset, &retval, 1, error)) { - m_is_valid = false; - return 0; - } - - return retval; - } - -private: - Process &m_process; - const lldb::addr_t m_base_addr; - bool m_is_valid = true; -}; - static constexpr OptionEnumValueElement g_follow_fork_mode_values[] = { { eFollowParent, @@ -3368,20 +3341,37 @@ lldb::addr_t Process::FindInMemory(lldb::addr_t low, lldb::addr_t high, return LLDB_INVALID_ADDRESS; std::vector<size_t> bad_char_heuristic(256, size); - ProcessMemoryIterator iterator(*this, low); - for (size_t idx = 0; idx < size - 1; idx++) { decltype(bad_char_heuristic)::size_type bcu_idx = buf[idx]; bad_char_heuristic[bcu_idx] = size - idx - 1; } - for (size_t s = 0; s <= (region_size - size);) { + + llvm::SmallVector<uint8_t, 0> mem; + addr_t mem_pos = low; + const size_t read_size = std::max<size_t>(size, 0x10000); + + for (addr_t s = low; s <= (high - size);) { + if (s + size >= mem.size() + mem_pos) { + mem.resize_for_overwrite(read_size); + Status error; + mem.resize( + ReadMemory(s, mem.data(), std::min(mem.size(), high - s), error)); + mem_pos = s; + if (error.Fail()) { + MemoryRegionInfo info; + error = GetMemoryRegionInfo(s, info); + if (error.Fail()) + return LLDB_INVALID_ADDRESS; + s = info.GetRange().GetRangeEnd(); + continue; + } + } int64_t j = size - 1; - while (j >= 0 && buf[j] == iterator[s + j]) + while (j >= 0 && buf[j] == mem[s + j - mem_pos]) j--; if (j < 0) - return low + s; - else - s += bad_char_heuristic[iterator[s + size - 1]]; + return s; + s += bad_char_heuristic[mem[s + size - 1 - mem_pos]]; } return LLDB_INVALID_ADDRESS; diff --git a/lldb/test/API/functionalities/memory/find/TestMemoryFind.py b/lldb/test/API/functionalities/memory/find/TestMemoryFind.py index 09611cc808777d..a606899498b722 100644 --- a/lldb/test/API/functionalities/memory/find/TestMemoryFind.py +++ b/lldb/test/API/functionalities/memory/find/TestMemoryFind.py @@ -79,3 +79,13 @@ def test_memory_find(self): 'memory find -s "nothere" `stringdata` `stringdata+10`', substrs=["data not found within the range."], ) + + pagesize = self.frame().FindVariable("pagesize").GetValueAsUnsigned() + mem_with_holes = self.frame().FindVariable("mem_with_holes").GetValueAsUnsigned() + matches_var = self.frame().FindVariable("matches") + self.assertEqual(matches_var.GetNumChildren(), 4) + matches = [f'data found at location: {matches_var.GetChildAtIndex(i).GetValueAsUnsigned():#x}' for i in range(4)] + self.expect( + 'memory find -c 5 -s "needle" `mem_with_holes` `mem_with_holes+5*pagesize`', + substrs=matches + ["no more matches within the range"], + ) diff --git a/lldb/test/API/functionalities/memory/find/main.cpp b/lldb/test/API/functionalities/memory/find/main.cpp index e3dcfc762ee0f9..e5525e3ca1f73f 100644 --- a/lldb/test/API/functionalities/memory/find/main.cpp +++ b/lldb/test/API/functionalities/memory/find/main.cpp @@ -1,9 +1,75 @@ -#include <stdio.h> -#include <stdint.h> - -int main (int argc, char const *argv[]) -{ - const char* stringdata = "hello world; I like to write text in const char pointers"; - uint8_t bytedata[] = {0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99}; - return 0; // break here +#include <cstdint> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <initializer_list> + +#ifdef _WIN32 +#include "Windows.h" + +int getpagesize() { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwPageSize; +} + +void *allocate_memory_with_holes() { + int pagesize = getpagesize(); + void *mem = VirtualAlloc(nullptr, 5 * pagesize, MEM_RESERVE, PAGE_NOACCESS); + if (!mem) { + std::cerr << std::system_category().message(GetLastError()) << std::endl; + exit(1); + } + char *bytes = static_cast<char *>(mem); + for (int page : {0, 2, 4}) { + if (!VirtualAlloc(bytes + page * pagesize, pagesize, MEM_COMMIT, + PAGE_READWRITE)) { + std::cerr << std::system_category().message(GetLastError()) << std::endl; + exit(1); + } + } + return bytes; +} +#else +#include "sys/mman.h" +#include "unistd.h" + +char *allocate_memory_with_holes() { + int pagesize = getpagesize(); + void *mem = mmap(nullptr, 5 * pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem == MAP_FAILED) { + perror("mmap"); + exit(1); + } + char *bytes = static_cast<char *>(mem); + for (int page : {1, 3}) { + if (munmap(bytes + page * pagesize, pagesize) != 0) { + perror("munmap"); + exit(1); + } + } + return bytes; +} +#endif + +int main(int argc, char const *argv[]) { + const char *stringdata = + "hello world; I like to write text in const char pointers"; + uint8_t bytedata[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, + 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99}; + + char *mem_with_holes = allocate_memory_with_holes(); + int pagesize = getpagesize(); + char *matches[] = { + mem_with_holes, // Beginning of memory + mem_with_holes + 2 * pagesize, // After a hole + mem_with_holes + 2 * pagesize + + pagesize / 2, // Middle of a block, after an existing match. + mem_with_holes + 5 * pagesize - 7, // End of memory + }; + for (char *m : matches) + strcpy(m, "needle"); + + return 0; // break here } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits