GDB Usage

Check memory layout

To check the memory layout of a binary in GDB, you can use different commands depending on whether the program is currently running or if you are just inspecting the static binary file.

1. If the Program is Running

The best command to see the virtual memory mappings (including the heap, stack, and loaded libraries) is:

info proc mappings

What it shows:

  • Start/End Addr: The virtual address range.
  • Size: The size of the mapped region.
  • Offset: Offset into the file (if file-backed).
  • Objfile: The specific file backing this memory (e.g., /bin/bash, [heap], [stack], or shared libraries like libc.so).

Example Output:

(gdb) info proc mappings
process 12345
Mapped address spaces:

          Start Addr           End Addr       Size     Offset objfile
      0x555555554000     0x555555558000     0x4000        0x0 /path/to/binary
      0x555555757000     0x555555758000     0x1000     0x3000 /path/to/binary
      0x555555758000     0x555555759000     0x1000     0x4000 /path/to/binary
      0x7ffff7dc0000     0x7ffff7fc0000   0x200000        0x0 [heap]
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]

2. If the Program is NOT Running (or for Section Headers)

If you want to see how the binary’s sections (like .text, .data, .bss) are laid out, use:

maintenance info sections

(Short form: maint info sections)

What it shows:

  • A list of all sections from the object file.
  • The memory flags (READONLY, CODE, DATA).
  • File offsets and virtual addresses.

Example Output:

(gdb) maint info sections
Exec file: `/path/to/binary', file type elf64-x86-64.
    0x00400238->0x00400254 at 0x00000238: .interp ALLOC LOAD READONLY DATA HAS_CONTENTS
    0x00400254->0x00400274 at 0x00000254: .note.ABI-tag ALLOC LOAD READONLY DATA HAS_CONTENTS
    0x004003e0->0x00400404 at 0x000003e0: .plt ALLOC LOAD READONLY CODE HAS_CONTENTS
    0x00400410->0x004005c2 at 0x00000410: .text ALLOC LOAD READONLY CODE HAS_CONTENTS

3. Alternative: info files

This command provides a summary of the current target file, including the entry point and the memory ranges for each section.

info files

Key Difference: It is less detailed than maint info sections regarding flags but is often cleaner if you just want to know where .text or .data starts and ends.

Summary of When to Use Which

CommandUsage Scenario
info proc mappingsBest for runtime analysis. Shows the real layout including Heap, Stack, and Shared Libs.
maint info sectionsBest for static analysis. Shows binary sections (.text, .bss) exactly as defined in the ELF/PE header.
info filesGood general overview of the loaded file and its entry point.

Set breakpoint at entrypoint

To set a breakpoint at the true entry point of a binary (which is before main()), you can use one of the following methods depending on your GDB version and whether the binary has symbols.

Method 1: The One-Liner (Best for GDB 8.1+)

If you just want to run the program and stop at the very first instruction immediately, use:

starti
  • What it does: It acts like run but automatically stops at the first instruction (the entry point).
  • Note: This is different from start, which stops at main.

Method 2: Breaking by Symbol (Standard)

For most Linux binaries, the entry point is labeled _start. You can simply break there:

break _start
  • Why _start? This is the actual assembly entry point that initializes the C runtime (setting up stack, environment) before calling your main function.

Method 3: Manual Address (If Symbols are Stripped)

If the binary is “stripped” (has no symbols) or you want to be precise, you can find the entry point address and break on it explicitly.

  1. Find the entry point address:
    Use the info files command inside GDB. (gdb) info files Look for the line that says “Entry point: 0x…” at the top of the output.
  2. Set the breakpoint:
    Use the * syntax before the address to tell GDB it is a memory location.
    gdb (gdb) break *0x401050
    (Replace 0x401050 with the actual address you found).

Summary Table

CommandDescription
startiEasiest. Starts program and stops at entry point immediately.
break _startSets a breakpoint at the standard entry label.
break *0x...Sets a breakpoint at a raw memory address (requires info files).

Inspect 2/4/8 bytes data

To inspect memory in specific byte chunks in GDB, you use the x (examine) command. The syntax generally looks like this:

x /<count><format><size> <address>

Here are the specific commands for 2, 4, and 8 bytes.

1. The Short Answer (Hex format)

Assuming you want to look at the address stored in the register $sp (stack pointer) or a raw address like 0x400500:

Data SizeGDB SuffixCommand ExampleExplanation
2 Bytesh (Halfword)x/xh $spExamine 1 unit of Hex, size Halfword
4 Bytesw (Word)x/xw $spExamine 1 unit of Hex, size Word
8 Bytesg (Giant)x/xg $spExamine 1 unit of Hex, size Giant

2. Detailed Syntax Explanation

The command is broken down as x /NFS addr:

  • N (Count): How many units to display (e.g., 1, 4, 10).
  • F (Format): How to display the data.
    • x = Hexadecimal (most common)
    • d = Decimal
    • u = Unsigned Decimal
    • i = Instruction (Assembly)
    • s = String
  • S (Size): The size of each unit.
    • b = Byte (1 byte)
    • h = Halfword (2 bytes)
    • w = Word (4 bytes) (Note: In GDB, a “word” is 4 bytes, unlike x86 assembly where it is often 2).
    • g = Giant (8 bytes)

3. Examples

Inspecting 2 Bytes (Halfword)

To see the value 0x1234 located at 0x7fffffffe000:

(gdb) x/1xh 0x7fffffffe000
0x7fffffffe000:    0x1234

Inspecting 4 Bytes (Word) in Decimal

To see a standard integer (4 bytes) at a variable’s address:

(gdb) x/1wd &my_integer
0x7fffffffe000:    500

Inspecting multiple 8 Byte (Giant) chunks

To see the top 4 values on the stack (64-bit machine):

(gdb) x/4xg $sp
0x7fffffffe100:    0x00000000004005d6    0x00007fffffffe238
0x7fffffffe110:    0x0000000000000001    0x00007ffff7de59a0

Alternative: Using print with Casting

If you prefer C-style casting over raw memory inspection, you can use the print (or p) command. This is often useful if you want GDB to handle the types for you.

  • 2 Bytes: p *(short *) 0x400500
  • 4 Bytes: p *(int *) 0x400500
  • 8 Bytes: p *(long long *) 0x400500

Print the assembly at the same time executing

You can achieve this in three ways. The first is a simple command, the second is a setting, and the third uses GDB’s visual mode.

Option 1: The display Command (Classic)

This tells GDB to automatically print an expression every time the program stops (e.g., after every si).

  1. Run this command once: display/i $pc
    • display: Show every time execution stops.
    • /i: Format as instruction (assembly).
    • $pc: The Program Counter register (current instruction pointer).
  2. Now, when you type si, GDB will automatically print the next instruction.
    text (gdb) si 1: x/i $pc => 0x40052d <main+4>: sub $0x10,%rsp

To stop this behavior later, type undisplay.


Option 2: The disassemble-next-line Setting (Cleaner)

Newer versions of GDB have a specific setting for this. It is often cleaner than display because it integrates the assembly into the standard stop message.

  1. Run this command: set disassemble-next-line on
  2. Now, when you si (or ni), it shows the instruction automatically:
    text (gdb) si 0x0000000000401126 4 printf("Hello\n"); 0x0000000000401126 <+4>: 48 83 ec 10 sub $0x10,%rsp

This typically shows both the source line (if available) and the assembly instruction.


Option 3: TUI Mode (Visual Split Screen)

This is usually the most helpful method. It splits your terminal window: the top half shows the scrolling assembly code with a highlighter on the current line, and the bottom half is your command prompt.

  1. Enable it by typing: layout asm (Or layout split to see both C source code and Assembly together).
  2. Now when you type si, the highlighter in the top window simply moves down one line.
  • Tip: If the screen gets messed up (garbled text), press Ctrl+L to refresh it.
  • Tip: Press Ctrl+X then A to exit this mode.

Leave a Reply

Your email address will not be published. Required fields are marked *