Skip to content

Instantly share code, notes, and snippets.

@mrexodia
Created November 23, 2025 12:55
Show Gist options
  • Select an option

  • Save mrexodia/897fdd4ec9ffe15cdc76591cc7220603 to your computer and use it in GitHub Desktop.

Select an option

Save mrexodia/897fdd4ec9ffe15cdc76591cc7220603 to your computer and use it in GitHub Desktop.
When a breakpoint is triggered, how should I use a script function to print each member of a std::vector pointed to by the `rcx` register?

DeepWiki Q&A with Code Context for Repository: x64dbg/x64dbg

Q1

When a breakpoint is triggered, how should I use a script function to print each member of a std::vector pointed to by the rcx register?

Answer

To print each member of a std::vector pointed to by the rcx register when a breakpoint is triggered, you need to understand the memory layout of std::vector and use x64dbg's scripting capabilities with breakpoint commands.

Solution Approach

1. Set up a breakpoint command

You can execute a script when a breakpoint is hit by using the "command text" field. x64dbg:22-26

The command can call a script function using scriptcmd: x64dbg:21-31

2. Understand std::vector memory layout

A std::vector object typically contains three pointers:

  • Offset 0x0: pointer to the first element (begin)
  • Offset 0x8: pointer to one past the last element (end)
  • Offset 0x10: pointer to end of allocated storage (capacity)

3. Access the vector data

Use the ptr() or pointer() function to read pointer values from memory: x64dbg:104-104

4. Use loops to iterate

x64dbg scripts use label-based loops with conditional jumps, similar to assembly language: x64dbg:23-31

5. Format output with log command

Use the log command with string formatting to print values: x64dbg:5-5

The {mem;size@address} format can print memory at specific addresses: x64dbg:23-23

Example Script Structure

print_vector:
    vec_begin = ptr(rcx)
    vec_end = ptr(rcx+8)
    element_size = 4  // adjust based on your vector's element type
    count = (vec_end - vec_begin) / element_size
    i = 0
loop_start:
    cmp i, count
    je loop_end
    addr = vec_begin + (i * element_size)
    log "Element {d:i}: {mem;4@addr}"  // adjust size as needed
    i++
    jmp loop_start
loop_end:
    ret

Then set your breakpoint command to:

bp <address>
SetBreakpointCommand <address>, "scriptcmd call print_vector"

Notes

  • Replace element_size and the memory format size based on your vector's element type (4 for int, 8 for int64_t or pointers, etc.)
  • Use {d:value} for signed decimal, {p:value} for pointer format, or {x:value} for hex
  • You can use {utf8@addr} or {utf16@addr} if the vector contains string pointers
  • The log command output should be quoted if it contains semicolons: log "{mem;8@addr}" x64dbg:48-50
  • Set break condition to 0 if you only want to log without pausing: x64dbg:52-52

Citations

File: docs/introduction/ConditionalBreakpoint.md (L22-26)

- If *command text* is set and *command condition* evaluated to `1`:
  - Set the system variable `$breakpointcondition` to the *break condition*;
  - Set the system variable `$breakpointlogcondition` to the *log condition*;
  - Execute the command in *command text*;
  - The *break condition* will be set to the value of `$breakpointcondition`. So if you modify this system variable in the script, you will be able to control whether the debuggee would break.

File: docs/introduction/ConditionalBreakpoint.md (L52-52)

*break condition*: `0` (Useful if you only want to execute command or log data, but not pause the debuggee)

File: docs/commands/script/scriptcmd.md (L21-31)

This command can be used in combination with [SetBreakpointCommand](../conditional-breakpoint-control/SetBreakpointCommand.md) to execute scripts on breakpoint callbacks:

fn_addr = module.dll:$0x1234 // module.dll RVA 0x1234 bp fn_addr SetBreakpointCommand fn_addr, "scriptcmd call mycallback"

// TODO: make sure the script is not unloaded (using run)

mycallback: log "fn({arg.get(0)}, {arg.get(1)})"

**File:** docs/introduction/Expression-functions.md (L104-104)
```markdown
* `ReadPtr(addr)`,`ReadPointer(addr)`,`ptr(addr)`,`Pointer(addr)`,`pointer(addr)`: Read a pointer (4/8 bytes) from `addr` and return the value.

File: docs/introduction/Formatting.md (L5-5)

The basic syntax is `{?:expression}` where `?` is the optional type of the [expression](./Expressions.md). To output `{` or `}` in the result, escape them as `{{` or `}}`.

File: docs/introduction/Formatting.md (L23-23)

- `{mem;size@address}` will print the `size` bytes starting at `address` in hex.

File: docs/introduction/Formatting.md (L48-50)

## Logging

When using the `log` command you should put quotes around the format string (`log "{mem;8@rax}"`) to avoid ambiguity with the `;` (which separates two commands). See [issue #1931](https://github.com/x64dbg/x64dbg/issues/1931) for more details.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment