diff options
Diffstat (limited to 'lldb')
4 files changed, 152 insertions, 16 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile new file mode 100644 index 00000000000..314f1cb2f07 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py new file mode 100644 index 00000000000..f7507c73c94 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py @@ -0,0 +1,59 @@ +""" +Test the 'memory find' command. +""" + +from __future__ import print_function + + + +import os, time +import re +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + +class MemoryFindTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// break here') + + def test_memory_find(self): + """Test the 'memory find' command.""" + self.build() + exe = os.path.join(os.getcwd(), "a.out") + self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) + + # Break in main() aftre the variables are assigned values. + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', 'stop reason = breakpoint']) + + # The breakpoint should have a hit count of 1. + self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE, + substrs = [' resolved, hit count = 1']) + + # Test the memory find commands. + + self.expect('memory find -s "in const" `stringdata` `stringdata+(int)strlen(stringdata)`', + substrs = ['data found at location: 0x', '69 6e 20 63', 'in const']) + + self.expect('memory find -e "(uint8_t)0x22" `&bytedata[0]` `&bytedata[15]`', + substrs = ['data found at location: 0x', '22 33 44 55 66']) + + self.expect('memory find -e "(uint8_t)0x22" `&bytedata[0]` `&bytedata[2]`', + substrs = ['data not found within the range.']) + + self.expect('memory find -s "nothere" `stringdata` `stringdata+5`', + substrs = ['data not found within the range.']) + + self.expect('memory find -s "nothere" `stringdata` `stringdata+10`', + substrs = ['data not found within the range.']) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp new file mode 100644 index 00000000000..250f359c76e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/memory/find/main.cpp @@ -0,0 +1,17 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#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 +} diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 20b15cfe26e..fa89da11904 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -1088,6 +1088,45 @@ public: } protected: + class ProcessMemoryIterator + { + public: + ProcessMemoryIterator (ProcessSP process_sp, + lldb::addr_t base) : + m_process_sp(process_sp), + m_base_addr(base), + m_is_valid(true) + { + lldbassert(process_sp); + } + + bool + IsValid () + { + return m_is_valid; + } + + uint8_t + operator [](lldb::addr_t offset) + { + if (!IsValid()) + return 0; + + uint8_t retval = 0; + Error error; + if (0 == m_process_sp->ReadMemory(m_base_addr+offset, &retval, 1, error)) + { + m_is_valid = false; + return 0; + } + + return retval; + } + private: + ProcessSP m_process_sp; + lldb::addr_t m_base_addr; + bool m_is_valid; + }; bool DoExecute (Args& command, CommandReturnObject &result) override { @@ -1185,7 +1224,7 @@ protected: bool ever_found = false; while (count) { - found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); + found_location = FastSearch(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize()); if (found_location == LLDB_INVALID_ADDRESS) { if (!ever_found) @@ -1218,24 +1257,40 @@ protected: } lldb::addr_t - Search (lldb::addr_t low, - lldb::addr_t high, - uint8_t* buffer, - size_t buffer_size) + FastSearch (lldb::addr_t low, + lldb::addr_t high, + uint8_t *buffer, + size_t buffer_size) { - Process *process = m_exe_ctx.GetProcessPtr(); - DataBufferHeap heap(buffer_size, 0); - for (auto ptr = low; - ptr < high; - ptr++) + const size_t region_size = high-low; + + if (region_size < buffer_size) + return LLDB_INVALID_ADDRESS; + + std::vector<size_t> bad_char_heuristic(256, buffer_size); + ProcessSP process_sp = m_exe_ctx.GetProcessSP(); + ProcessMemoryIterator iterator(process_sp, low); + + for (size_t idx = 0; + idx < buffer_size-1; + idx++) { - Error error; - process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error); - if (error.Fail()) - return LLDB_INVALID_ADDRESS; - if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0) - return ptr; + decltype(bad_char_heuristic)::size_type bcu_idx = buffer[idx]; + bad_char_heuristic[bcu_idx] = buffer_size - idx - 1; + } + for (size_t s = 0; + s <= (region_size - buffer_size); + ) + { + int64_t j = buffer_size-1; + while (j >= 0 && buffer[j] == iterator[s + j]) + j--; + if (j < 0) + return low+s; + else + s += bad_char_heuristic[iterator[s + buffer_size - 1]]; } + return LLDB_INVALID_ADDRESS; } |