Commit | Line | Data |
---|---|---|
4a72de73 TT |
1 | /* Target memory searching |
2 | ||
3666a048 | 3 | Copyright (C) 2020-2021 Free Software Foundation, Inc. |
4a72de73 TT |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "gdbsupport/common-defs.h" | |
21 | ||
22 | #include "gdbsupport/search.h" | |
23 | #include "gdbsupport/byte-vector.h" | |
24 | ||
25 | /* This implements a basic search of memory, reading target memory and | |
26 | performing the search here (as opposed to performing the search in on the | |
27 | target side with, for example, gdbserver). */ | |
28 | ||
29 | int | |
30 | simple_search_memory | |
31 | (gdb::function_view<target_read_memory_ftype> read_memory, | |
32 | CORE_ADDR start_addr, ULONGEST search_space_len, | |
33 | const gdb_byte *pattern, ULONGEST pattern_len, | |
34 | CORE_ADDR *found_addrp) | |
35 | { | |
36 | const unsigned chunk_size = SEARCH_CHUNK_SIZE; | |
37 | /* Buffer to hold memory contents for searching. */ | |
38 | unsigned search_buf_size; | |
39 | ||
40 | search_buf_size = chunk_size + pattern_len - 1; | |
41 | ||
42 | /* No point in trying to allocate a buffer larger than the search space. */ | |
43 | if (search_space_len < search_buf_size) | |
44 | search_buf_size = search_space_len; | |
45 | ||
46 | gdb::byte_vector search_buf (search_buf_size); | |
47 | ||
48 | /* Prime the search buffer. */ | |
49 | ||
50 | if (!read_memory (start_addr, search_buf.data (), search_buf_size)) | |
51 | { | |
52 | warning (_("Unable to access %s bytes of target " | |
53 | "memory at %s, halting search."), | |
54 | pulongest (search_buf_size), hex_string (start_addr)); | |
55 | return -1; | |
56 | } | |
57 | ||
58 | /* Perform the search. | |
59 | ||
60 | The loop is kept simple by allocating [N + pattern-length - 1] bytes. | |
61 | When we've scanned N bytes we copy the trailing bytes to the start and | |
62 | read in another N bytes. */ | |
63 | ||
64 | while (search_space_len >= pattern_len) | |
65 | { | |
66 | gdb_byte *found_ptr; | |
67 | unsigned nr_search_bytes | |
68 | = std::min (search_space_len, (ULONGEST) search_buf_size); | |
69 | ||
70 | found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes, | |
71 | pattern, pattern_len); | |
72 | ||
73 | if (found_ptr != NULL) | |
74 | { | |
75 | CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ()); | |
76 | ||
77 | *found_addrp = found_addr; | |
78 | return 1; | |
79 | } | |
80 | ||
81 | /* Not found in this chunk, skip to next chunk. */ | |
82 | ||
83 | /* Don't let search_space_len wrap here, it's unsigned. */ | |
84 | if (search_space_len >= chunk_size) | |
85 | search_space_len -= chunk_size; | |
86 | else | |
87 | search_space_len = 0; | |
88 | ||
89 | if (search_space_len >= pattern_len) | |
90 | { | |
91 | unsigned keep_len = search_buf_size - chunk_size; | |
92 | CORE_ADDR read_addr = start_addr + chunk_size + keep_len; | |
93 | int nr_to_read; | |
94 | ||
95 | /* Copy the trailing part of the previous iteration to the front | |
96 | of the buffer for the next iteration. */ | |
97 | gdb_assert (keep_len == pattern_len - 1); | |
98 | if (keep_len > 0) | |
99 | memcpy (&search_buf[0], &search_buf[chunk_size], keep_len); | |
100 | ||
101 | nr_to_read = std::min (search_space_len - keep_len, | |
102 | (ULONGEST) chunk_size); | |
103 | ||
104 | if (!read_memory (read_addr, &search_buf[keep_len], nr_to_read)) | |
105 | { | |
106 | warning (_("Unable to access %s bytes of target " | |
107 | "memory at %s, halting search."), | |
108 | plongest (nr_to_read), | |
109 | hex_string (read_addr)); | |
110 | return -1; | |
111 | } | |
112 | ||
113 | start_addr += chunk_size; | |
114 | } | |
115 | } | |
116 | ||
117 | /* Not found. */ | |
118 | ||
119 | return 0; | |
120 | } |