14b169a6bSchristos /* Target memory searching 24b169a6bSchristos 3*5ba1f45fSchristos Copyright (C) 2020-2024 Free Software Foundation, Inc. 44b169a6bSchristos 54b169a6bSchristos This file is part of GDB. 64b169a6bSchristos 74b169a6bSchristos This program is free software; you can redistribute it and/or modify 84b169a6bSchristos it under the terms of the GNU General Public License as published by 94b169a6bSchristos the Free Software Foundation; either version 3 of the License, or 104b169a6bSchristos (at your option) any later version. 114b169a6bSchristos 124b169a6bSchristos This program is distributed in the hope that it will be useful, 134b169a6bSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144b169a6bSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154b169a6bSchristos GNU General Public License for more details. 164b169a6bSchristos 174b169a6bSchristos You should have received a copy of the GNU General Public License 184b169a6bSchristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194b169a6bSchristos 204b169a6bSchristos 214b169a6bSchristos #include "gdbsupport/search.h" 224b169a6bSchristos #include "gdbsupport/byte-vector.h" 234b169a6bSchristos 244b169a6bSchristos /* This implements a basic search of memory, reading target memory and 254b169a6bSchristos performing the search here (as opposed to performing the search in on the 264b169a6bSchristos target side with, for example, gdbserver). */ 274b169a6bSchristos 284b169a6bSchristos int 294b169a6bSchristos simple_search_memory 304b169a6bSchristos (gdb::function_view<target_read_memory_ftype> read_memory, 314b169a6bSchristos CORE_ADDR start_addr, ULONGEST search_space_len, 324b169a6bSchristos const gdb_byte *pattern, ULONGEST pattern_len, 334b169a6bSchristos CORE_ADDR *found_addrp) 344b169a6bSchristos { 354b169a6bSchristos const unsigned chunk_size = SEARCH_CHUNK_SIZE; 364b169a6bSchristos /* Buffer to hold memory contents for searching. */ 374b169a6bSchristos unsigned search_buf_size; 384b169a6bSchristos 394b169a6bSchristos search_buf_size = chunk_size + pattern_len - 1; 404b169a6bSchristos 414b169a6bSchristos /* No point in trying to allocate a buffer larger than the search space. */ 424b169a6bSchristos if (search_space_len < search_buf_size) 434b169a6bSchristos search_buf_size = search_space_len; 444b169a6bSchristos 454b169a6bSchristos gdb::byte_vector search_buf (search_buf_size); 464b169a6bSchristos 474b169a6bSchristos /* Prime the search buffer. */ 484b169a6bSchristos 494b169a6bSchristos if (!read_memory (start_addr, search_buf.data (), search_buf_size)) 504b169a6bSchristos { 514b169a6bSchristos warning (_("Unable to access %s bytes of target " 524b169a6bSchristos "memory at %s, halting search."), 534b169a6bSchristos pulongest (search_buf_size), hex_string (start_addr)); 544b169a6bSchristos return -1; 554b169a6bSchristos } 564b169a6bSchristos 574b169a6bSchristos /* Perform the search. 584b169a6bSchristos 594b169a6bSchristos The loop is kept simple by allocating [N + pattern-length - 1] bytes. 604b169a6bSchristos When we've scanned N bytes we copy the trailing bytes to the start and 614b169a6bSchristos read in another N bytes. */ 624b169a6bSchristos 634b169a6bSchristos while (search_space_len >= pattern_len) 644b169a6bSchristos { 654b169a6bSchristos gdb_byte *found_ptr; 664b169a6bSchristos unsigned nr_search_bytes 674b169a6bSchristos = std::min (search_space_len, (ULONGEST) search_buf_size); 684b169a6bSchristos 694b169a6bSchristos found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes, 704b169a6bSchristos pattern, pattern_len); 714b169a6bSchristos 724b169a6bSchristos if (found_ptr != NULL) 734b169a6bSchristos { 744b169a6bSchristos CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ()); 754b169a6bSchristos 764b169a6bSchristos *found_addrp = found_addr; 774b169a6bSchristos return 1; 784b169a6bSchristos } 794b169a6bSchristos 804b169a6bSchristos /* Not found in this chunk, skip to next chunk. */ 814b169a6bSchristos 824b169a6bSchristos /* Don't let search_space_len wrap here, it's unsigned. */ 834b169a6bSchristos if (search_space_len >= chunk_size) 844b169a6bSchristos search_space_len -= chunk_size; 854b169a6bSchristos else 864b169a6bSchristos search_space_len = 0; 874b169a6bSchristos 884b169a6bSchristos if (search_space_len >= pattern_len) 894b169a6bSchristos { 904b169a6bSchristos unsigned keep_len = search_buf_size - chunk_size; 914b169a6bSchristos CORE_ADDR read_addr = start_addr + chunk_size + keep_len; 924b169a6bSchristos int nr_to_read; 934b169a6bSchristos 944b169a6bSchristos /* Copy the trailing part of the previous iteration to the front 954b169a6bSchristos of the buffer for the next iteration. */ 964b169a6bSchristos gdb_assert (keep_len == pattern_len - 1); 974b169a6bSchristos if (keep_len > 0) 984b169a6bSchristos memcpy (&search_buf[0], &search_buf[chunk_size], keep_len); 994b169a6bSchristos 1004b169a6bSchristos nr_to_read = std::min (search_space_len - keep_len, 1014b169a6bSchristos (ULONGEST) chunk_size); 1024b169a6bSchristos 1034b169a6bSchristos if (!read_memory (read_addr, &search_buf[keep_len], nr_to_read)) 1044b169a6bSchristos { 1054b169a6bSchristos warning (_("Unable to access %s bytes of target " 1064b169a6bSchristos "memory at %s, halting search."), 1074b169a6bSchristos plongest (nr_to_read), 1084b169a6bSchristos hex_string (read_addr)); 1094b169a6bSchristos return -1; 1104b169a6bSchristos } 1114b169a6bSchristos 1124b169a6bSchristos start_addr += chunk_size; 1134b169a6bSchristos } 1144b169a6bSchristos } 1154b169a6bSchristos 1164b169a6bSchristos /* Not found. */ 1174b169a6bSchristos 1184b169a6bSchristos return 0; 1194b169a6bSchristos } 120