Evaluate expressions

Zxdb can evaluate and print values from simple C, C++, and Rust expressions. The most common use case to evaluate an expression in zxdb is with the print verb. Expressions can also be used for commands that take a memory location as an argument such as stack or mem-read.

When you evaluate an expression you need a stack frame, which in turn requires a process with a paused thread. If the process is currently running, you can use the pause verb to pause the thread.

You can use the print command to show the current value of a variable in the current stack frame:

For example, to see the value of a variable i:

print i
34

You can also evaluate expressions in the context of another stack frame without switching to that frame.

For example, to see the value of argv[0] in stack frame 2:

frame 2 print argv[0]
"/bin/cowsay"

The print command accepts the following arguments:

  • --max-array=<number>: Specifies the maximum array size to print. By default this is 256. Specifying large values slows down expression evaluation.

  • --raw or -r: Bypass pretty-printers and show the raw type information.

  • --types or -t: Force type printing on. The type of every value printed is explicitly shown. Implies -v.

  • --verbose or -v: Don't omit type names. Show reference addresses and pointer types.

To write an expression beginning with a hyphen, use -- to mark the end of arguments. Hyphens after -- are treated as part of the expression:

print -- -i

Number formatting options

The print command accepts the following options to force numeric values to be of specific types:

  • -b: Binary
  • -c: Character
  • -d: Signed decimal
  • -u: Unsigned decimal
  • -x: Unsigned hexadecimal

Special variables

When you work with variables in zxdb you may have an identifier name that is not parseable in the current language. This is often the case for compiler-generated symbols. Make sure to enclose such strings in $(<symbols>). Parentheses inside the escaped contents can be literal as long as they are balanced, otherwise, escape them by preceding with a backslash. Include any literal backslash with two backslashes.

These are all valid examples:

  • $(something with spaces)
  • $({{impl}})
  • $(some_closure(data))
  • $(line\)noise\\)

Additionally, zxdb also supports:

CPU registers

You can refer to CPU registers with the $reg(register name) syntax. For example, to display the ARM register v3:

print $reg(v3)
0x573a420f128

CPU registers can also be used unescaped as long as no variable in the current scope has the same name. Registers can also be used like any other variable in more complex expressions:

print -x rax + rbx
0x2108aa0032a

Vector registers

Vector registers can be treated as arrays based on the setting of vector-format.

print ymm1
{3.141593, 1.0, 0, 0}

[zxdb] print ymm[0] * 2
6.28319

List vector registers

You can list the vector registers with regs.

For example, to list all of the vector registers:

regs --vector
    (Use "print $registername" to show a single one, or
     "print $registername = newvalue" to set.)

Vector Registers
  mxcsr 0x1fa0 = 8096

   Name [3] [2]           [1]           [0]
   ymm0   0   0 -3.72066e-103 -3.72066e-103
   ymm1   0   0  3.79837e-312  2.63127e-312
   ymm2   0   0             0 -3.72066e-103
   ymm3   0   0  1.26218e-311  1.26218e-311
   ymm4   0   0  1.26218e-311  1.26218e-311
   ymm5   0   0  1.26218e-311  1.26218e-311
   ymm6   0   0  5.96337e-321  5.87938e-321
   ymm7   0   0  2.56125e-311   2.4891e-311
   ymm8   0   0             0             0
   ymm9   0   0             0             0
  ymm10   0   0             0             0
  ymm11   0   0             0             0
  ymm12   0   0             0             0
  ymm13   0   0             0             0
  ymm14   0   0             0             0
  ymm15   0   0             0             0
    (Use "get/set vector-format" to control vector register interpretation.
     Currently showing vectors of "double".)

Use display

When stepping through a function, it can be useful to automatically print one or more expressions each time the program stops. The display command adds a given expression to this list:

display status
Added to display for every stop: status

[zxdb] next
🛑 main(…) • main.cc:48

    [code dump]

status = 5;

Use locals

The locals command shows all local variables in the current stack frame. It accepts the same arguments as print (see Print with expressions):

locals
argc = 1
argv = (const char* const*) 0x59999ec02dc0