WatchPoint

Image link

How to search memory for a byte sequence with GDB command find?

 

In this GDB tutorial, we look at the GDB command find.

Sometimes, when you are debugging, you need to find a particular sequence of bytes in the memory space of the program. Perhaps, you want to see all the pointers to a specific object. So, every eight bytes in memory that corresponds to the byte sequence, is an address you want to identify.

Note that, the find command returns the addresses of all matches; so we must accept possible false positives.

That’s fine – I guess.

The find command offers you a different kind of inspection into your program.

Let’s dive in.

 

Hello, world!

First, let’s write a simple program that we can use for this GDB tutorial.

Open your favorite editor (e.g., emacs, or vi) and type the following lines.

#include <stdio.h>

int
main(void)
{
  printf(“Hello, world!\n”);
  printf(“That is all, goodbye.\n”);
  Return 0;
}

Save the program as hello.c

Compile it.

$ gcc -g3 hello.c

Load it.

$ gdb a.out

Start it.

(gdb) start

Done it.

Now let’s look at the GDB command find.

 

New call-to-action

The GDB find command

The syntax for the GDB command find is as follows:

find [/SIZE-CHAR] [/MAX-COUNT] START-ADDRESS, END-ADDRESS, EXPR1 [, EXPR2, ...]

Or,

find [/SIZE-CHAR] [/MAX-COUNT] START-ADDRESS, +LENGTH, EXPR1 [, EXPR2, ...]

You can search the memory space of a program for a particular sequence of bytes specified by EXPR1EXPR2, etc.

The search begins at a START-ADDRESS and continues for either +LENGTH bytes or until the END-ADDRESS.

Later in this GDB tutorial, I show how you get the memory mapping for your program and use it to determine the start and end addresses for your search query.

[ /SIZE-CHAR] and [/MAX-COUNT] are optional.

[/SIZE-CHAR] sets the size for each search value.

b bytes

h halfwords (two bytes)

w words (four bytes)

g giant words (eight bytes)

All search values are interpreted in the programming language of the program. For example, the source language of hello.c is C/C++; so when we later in this GDB tutorial search for the string “Hello, world!”, it includes the trailing ‘\0’.

If we don’t specify the [/SIZE-CHAR], then the size is taken from the value-type in the source language. This is useful when you want to specify the search pattern as a mixture of value types.

[/MAX-COUNT] sets the maximum number of matches to return. The default is to print all finds.

You can use strings as search values. Make sure to quote them with double-quotes (“). The string value is copied into the search pattern byte by byte, regardless of the byte order of the target and the size specification.

The address of each match found is returned as well as a count of the number of matches.

 

Show Memory Maps

If you want to search in the address space of your program, you need to get the memory mapping for your process and determine the start address, and depending on which find command syntax you use, the end address.

How do we give GDB an address range to search?

We can use the info proc command to get helpful information about the process. If you expand the command as follows:

(gdb) info proc mappings

This GDB command gives you all the memory mappings of the process; all the virtual address ranges, in our case the program hello.c, can access.

 

Taking an educated guess, the “Hello, world!” string I am searching for must live somewhere in the address range from 0x555555554000 to 0x555555559000. But, and this is really important, the address 0x555555559000 is NOT the actual end address. It is the address of the first byte that is not mapped! Using this address in our search will result in an error because it searches outside of the mapped address range. I show you that in my video. So, do step one byte back; 0x555555558fff.

Now, type this.

(gdb) find 0x555555554000 to 0x555555558fff, “Hello, world!”

The result in this example is two possible instances of the string in memory.

 

To check, type this:

(gdb) print (char*) 0x555555556004

Here you go, we found our string “Hello, world!”.

 

 

New call-to-action

 

Some final tips

Besides making sure that you search in a mapped memory range, there are other things to remember.

If you do search for a string, then you must map the exact pattern. In my video, for example, I forget to type the explanation-mark in my search, which you will see returns no match because it hits the trailing ‘\0’ terminator.

 

The find command searches for the full pattern up to the ‘\0’.

You can search for other patterns than strings, for example, a sequence of characters.

(gdb) find 0x555555554000 to 0x555555558fff, ‘H’, ‘e’, ‘l’, ‘l’, ‘o’

Note the single-quotes (‘).

 

That’s it!

The find help command offers some extra search options and parameters. Take some time to try these out too. I am sure that you do agree that the GDB command find gives you a useful way to get a different kind of inspection for debugging your program.

Don’t forget to share your takeaways from this GDB tutorial with your project members so everyone benefits!

Don’t miss my next C++ debugging tutorial: sign up to my WatchPoint mailing list below.
Get tutorials straight to your inbox

Become a GDB Power User. Get Greg’s debugging tips directly in your inbox every 2 weeks.

Want GDB pro tips directly in your inbox?

Share this tutorial