x命令基本写法为x/nfu addr,其中n为单元个数、f为格式(x表示十六进制)、u为单元大小(如b/h/w/g),addr为内存地址;缺省u时默认w(4字节),但未指定addr或u不匹配易导致显示异常。

gdb中x命令输出十六进制的基本写法
直接用 x/x 就能以十六进制格式查看内存,但这个“x”不是固定字符,而是由三部分拼出来的:x/[n][f][u]。其中 f 控制格式,x 就是十六进制;u 控制单位大小(比如字节、字),n 是要显示多少个单位。
常见错误是只敲 x/x 然后报错或输出看不懂的地址——那是因为没指定地址,或者单位大小缺失导致 gdb 默认用 b(1 字节),结果一堆零散字节堆在一起难读。
-
x/4xw 0x7fffffffe000:从地址0x7fffffffe000开始,以 4 字为单位(每字 4 字节)、十六进制显示 → 适合看 int 数组或结构体字段 -
x/8xb 0x7fffffffe000:以 8 字节为单位、按单字节十六进制显示 → 适合分析字符串原始字节或填充模式 -
x/10xg 0x7fffffffe000:按 8 字节(g= giant word)显示 10 个单元 → 常用于 x86_64 下看指针或 long 类型
为什么用x/x却看到十进制或乱码?
本质是单位大小(u)和格式(f)没配对好。比如 x/x 缺少 u,gdb 会回退到默认单位 b(byte),但一个字节用 x 格式显示时,高位补零不明显,容易误判为十进制;而 x/c 显示的是 ASCII 字符,不是数值,看着像乱码其实是正常行为。
- 想看“干净”的 32 位十六进制整数 → 用
w(word)+x:如x/5xw &my_int_array - 想确认某处是否为
0x90909090(NOP 指令)→ 用x/4xb拆开看每个字节,避免x/1xw把四个字节当一个整数反序显示 - 在 x86_64 下查指针值 → 必须用
g(giant,8 字节),否则w只读低 4 字节,高位被截断
十六进制输出和实际内存布局的关系
gdb 的 x 命令按“从低地址到高地址”顺序读,但每个单元内部字节序取决于当前架构。x86_64 是小端(little-endian),所以 x/1xw 0x7fffffffe000 显示的 0x00000001,真实内存里这 4 字节在地址上是 01 00 00 00(低字节在前)。
- 调试栈溢出或格式化字符串漏洞时,常需对照
x/8xw $rsp和x/32xb $rsp两组输出,前者看指针/整数逻辑值,后者看原始字节排列 - 用
x/10xs查字符串时,gdb 会自动停在第一个\0,但若该地址附近有非打印字符或嵌入\0,就可能提前截断 —— 此时换x/20xb更可靠 -
x/10xw和x/40xb看同一段内存,数据总量一样,但解释方式不同:前者把每 4 字节当一个 int,后者把每个字节单独列出
容易忽略的细节:地址对齐与符号扩展
如果你用 x/5xh(半字,2 字节)去看一个未对齐地址(比如 0x7fffffffe001),某些系统会触发总线错误(SIGBUS),尤其在 ARM 或严格对齐平台;x86_64 通常容忍,但值可能因字节序和符号位处理异常。
- 查看 char* 指向的内容,别直接
x/x $rdi—— 这是在看寄存器值本身(即指针地址),应先解引用:x/10xb *$rdi或x/10xs *$rdi - 用
x/d看有符号数时,高位是 1 会被扩展成负数;而x/u强制无符号解释 —— 同一段内存,x/1dw和x/1uw输出可能完全不同 - 调试时发现十六进制值“突然变小”,检查是否误用了
b单位(比如本该用w却用了b),导致只读了低字节











