1 /* Target memory searching 2 3 Copyright (C) 2020-2024 Free Software Foundation, Inc. 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 21 #include "gdbsupport/search.h" 22 #include "gdbsupport/byte-vector.h" 23 24 /* This implements a basic search of memory, reading target memory and 25 performing the search here (as opposed to performing the search in on the 26 target side with, for example, gdbserver). */ 27 28 int 29 simple_search_memory 30 (gdb::function_view<target_read_memory_ftype> read_memory, 31 CORE_ADDR start_addr, ULONGEST search_space_len, 32 const gdb_byte *pattern, ULONGEST pattern_len, 33 CORE_ADDR *found_addrp) 34 { 35 const unsigned chunk_size = SEARCH_CHUNK_SIZE; 36 /* Buffer to hold memory contents for searching. */ 37 unsigned search_buf_size; 38 39 search_buf_size = chunk_size + pattern_len - 1; 40 41 /* No point in trying to allocate a buffer larger than the search space. */ 42 if (search_space_len < search_buf_size) 43 search_buf_size = search_space_len; 44 45 gdb::byte_vector search_buf (search_buf_size); 46 47 /* Prime the search buffer. */ 48 49 if (!read_memory (start_addr, search_buf.data (), search_buf_size)) 50 { 51 warning (_("Unable to access %s bytes of target " 52 "memory at %s, halting search."), 53 pulongest (search_buf_size), hex_string (start_addr)); 54 return -1; 55 } 56 57 /* Perform the search. 58 59 The loop is kept simple by allocating [N + pattern-length - 1] bytes. 60 When we've scanned N bytes we copy the trailing bytes to the start and 61 read in another N bytes. */ 62 63 while (search_space_len >= pattern_len) 64 { 65 gdb_byte *found_ptr; 66 unsigned nr_search_bytes 67 = std::min (search_space_len, (ULONGEST) search_buf_size); 68 69 found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes, 70 pattern, pattern_len); 71 72 if (found_ptr != NULL) 73 { 74 CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ()); 75 76 *found_addrp = found_addr; 77 return 1; 78 } 79 80 /* Not found in this chunk, skip to next chunk. */ 81 82 /* Don't let search_space_len wrap here, it's unsigned. */ 83 if (search_space_len >= chunk_size) 84 search_space_len -= chunk_size; 85 else 86 search_space_len = 0; 87 88 if (search_space_len >= pattern_len) 89 { 90 unsigned keep_len = search_buf_size - chunk_size; 91 CORE_ADDR read_addr = start_addr + chunk_size + keep_len; 92 int nr_to_read; 93 94 /* Copy the trailing part of the previous iteration to the front 95 of the buffer for the next iteration. */ 96 gdb_assert (keep_len == pattern_len - 1); 97 if (keep_len > 0) 98 memcpy (&search_buf[0], &search_buf[chunk_size], keep_len); 99 100 nr_to_read = std::min (search_space_len - keep_len, 101 (ULONGEST) chunk_size); 102 103 if (!read_memory (read_addr, &search_buf[keep_len], nr_to_read)) 104 { 105 warning (_("Unable to access %s bytes of target " 106 "memory at %s, halting search."), 107 plongest (nr_to_read), 108 hex_string (read_addr)); 109 return -1; 110 } 111 112 start_addr += chunk_size; 113 } 114 } 115 116 /* Not found. */ 117 118 return 0; 119 } 120