GDB Wikipedia
GNU调试器(英语:GNU Debugger,缩写:GDB),是GNU软件系统中的标准调试器,此外GDB也是个具有移携性的调试器,经过移携需求的调修与重新编译,如今许多的类UNIX操作系统上都可以使用GDB,而现有GDB所能支持调试的编程语言有C、C++、Pascal以及FORTRAN。
相关链接: GDB: The GNU Project Debugger
本文参考资料
GDB 的基本使用 接下来只涉及一小部分常用的命令,更多的常用命令查阅上面提到的参考资料
💡 样例程序 这里以 CSAPP 的 BombLab 的 phase_1 阶段为例:
实验简介:只有在输入正确的字符串后才可避免💣爆炸,目标是正确拆除所有💣
实验说明书
下载链接
实验环境
Ubuntu 20.04 LTS
GDB Version: GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
不安装 gef、peda、pwndbg 等
启动程序 使用 GDB 调试目标程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ❯ gdb bomb GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from bomb... (gdb)
此时目标程序尚未运行,不过可以使用 info functions
查看函数符号表:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 (gdb) info functions All defined functions: File bomb.c: 36 : int main (int , char **) ;Non-debugging symbols: 0x0000000000400ac0 _init0x0000000000400ae0 getenv@plt0x0000000000400af0 __errno_location@plt0x0000000000400b00 strcpy @plt... 0x0000000000400ee0 phase_10x0000000000400efc phase_20x0000000000400f43 phase_30x0000000000400fce func40x000000000040100c phase_40x0000000000401062 phase_50x00000000004010f4 phase_60x0000000000401204 fun7...
使用 disassemble
命令(简写 disass)反编译指定的函数:
1 2 3 4 5 6 7 8 9 10 11 (gdb) disass phase_1 Dump of assembler code for function phase_1: 0x0000000000400ee0 <+0 >: sub $0x8 ,%rsp 0x0000000000400ee4 <+4 >: mov $0x402400 ,%esi 0x0000000000400ee9 <+9 >: callq 0x401338 <strings_not_equal> 0x0000000000400eee <+14 >: test %eax,%eax 0x0000000000400ef0 <+16 >: je 0x400ef7 <phase_1+23 > 0x0000000000400ef2 <+18 >: callq 0x40143a <explode_bomb> 0x0000000000400ef7 <+23 >: add $0x8 ,%rsp 0x0000000000400efb <+27 >: retq End of assembler dump.
此时的汇编语法是 AT&T 风格的,可以使用 set disassembly-flavor intel
切换至 intel 风格:
1 2 3 4 5 6 7 8 9 10 11 12 (gdb) set disassembly-flavor intel (gdb) disass phase_1Dump of assembler code for function phase_1: 0x0000000000400ee0 <+0>: sub rsp,0x8 0x0000000000400ee4 <+4>: mov esi,0x402400 0x0000000000400ee9 <+9>: call 0x401338 <strings_not_equal> 0x0000000000400eee <+14>: test eax,eax 0x0000000000400ef0 <+16>: je 0x400ef7 <phase_1+23> 0x0000000000400ef2 <+18>: call 0x40143a <explode_bomb> 0x0000000000400ef7 <+23>: add rsp,0x8 0x0000000000400efb <+27>: ret End of assembler dump.
📌 AT&T 与 intel 语法有何区别?
AT&T 和 Intel 汇编语法的主要区别
后续内容默认使用 intel 汇编语法
使用 break 命令添加断点:
1 2 3 (gdb) b phase_1 Breakpoint 1 at 0x400ee0 (gdb)
break 命令
可以直接在指定地址处下断点: break *0x400ee0
也可以在已知的函数符号后加一定的偏移处下断点: break *main+10
断点相关
查看已经存在的断点信息: info breakpoints
删除指定断点:del 1
使用 run
或 start
命令启动程序:
1 2 3 4 5 6 7 8 (gdb) run Starting program: /home/ubuntu/Datas/study/bomb/bomb Welcome to my fiendish little bomb. You have 6 phases with which to blow yourself up. Have a nice day! ABCD Breakpoint 1 , 0x0000000000400ee0 in phase_1 () (gdb)
📌 run
与 start
命令的区别是什么?
run
会一直执行程序,直到执行到设置的断点处停下;
start
会执行程序到 main()
函数起始处停下,等同于先执行了 break main
后执行 run
分析 phase_1 执行 disass,会反汇编得到当前断点处所在的函数(phase_1
)的汇编代码:
1 2 3 4 5 6 7 8 9 10 11 (gdb) disass Dump of assembler code for function phase_1: => 0x0000000000400ee0 <+0 >: sub rsp,0x8 0x0000000000400ee4 <+4 >: mov esi,0x402400 0x0000000000400ee9 <+9 >: call 0x401338 <strings_not_equal> 0x0000000000400eee <+14 >: test eax,eax 0x0000000000400ef0 <+16 >: je 0x400ef7 <phase_1+23 > 0x0000000000400ef2 <+18 >: call 0x40143a <explode_bomb> 0x0000000000400ef7 <+23 >: add rsp,0x8 0x0000000000400efb <+27 >: ret End of assembler dump.
第一个参数则是会通过 rdi 寄存器进行传参,接下来查看 rdi 的值:
使用 info reg
可以查看当前的所有寄存器信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 (gdb) info reg rax 0x603780 6305664 rbx 0x402210 4203024 rcx 0x4 4 rdx 0x1 1 rsi 0x603780 6305664 rdi 0x603780 6305664 rbp 0x0 0x0 rsp 0x7fffffffe348 0x7fffffffe348 r8 0x603780 6305664 r9 0x7c 124 r10 0xfffffffffffffe34 -460 r11 0x7ffff7e004a0 140737352041632 r12 0x400c90 4197520 r13 0x7fffffffe440 140737488348224 r14 0x0 0 r15 0x0 0 rip 0x400ee0 0x400ee0 <phase_1> eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb)
或者使用 print
来输出当前的 rdi 寄存器值:
1 2 3 (gdb) print /x $rdi $1 = 0x603780 (gdb)
使用 x 命令打印出其中的字符串内容:
1 2 3 4 5 (gdb) x/s 0x603780 0x603780 <input_strings>: "ABCD" (gdb) x/s 0x402400 0x402400 : "Border relations with Canada have never been better."
print 与 x 命令的更多帮助信息
可以直接使用 help 命令查询:
查询GDB手册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (gdb) help x Examine memory: x/FMT ADDRESS. ADDRESS is an expression for the memory address to examine. FMT is a repeat count followed by a format letter and a size letter. Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes). The specified number of objects of the specified size are printed according to the format. If a negative number is specified, memory is examined backward from the address. Defaults for format and size letters are those previously used. Default count is 1. Default address is following last thing printed with this command or "print".
1 2 3 4 5 x/nfu addr n: 输出单元的个数 f: 输出单元的格式 o/x/d/u/t/f/a/i/c/s/z u: 每个输出单元的长度 b/h/w/g
打印栈上的数据 我们也可以使用 x 命令来打印栈的数据:
1 2 3 4 5 6 (gdb) x/10 gx $rsp 0x7fffffffe348 : 0x0000000000400e3f 0x0000000000402210 0x7fffffffe358 : 0x00007ffff7df0083 0x0000000000000000 0x7fffffffe368 : 0x00007fffffffe448 0x0000000100000000 0x7fffffffe378 : 0x0000000000400da0 0x0000000000402210 0x7fffffffe388 : 0x4f838435c81d5e78 0x0000000000400c90
比较明显的可以得知,接下来程序会对比这两个字符串是否一致,一致时💣可以被解除
重新执行 run,输入刚刚发现的目标字符串
为了方便调试,可以执行 layout regs
来切换到下面的布局:
进行单步执行:stepi
/ nexti
函数返回值存储在 rax 中,值为 0 表示两个字符串相等,然后会跳过 explode_bomb
函数,继续执行程序
📌 stepi
与 nexti
的区别是什么?
stepi(si):执行一条指令,遇到函数调用时进入函数内部
nexti(ni):类似于stepi,但是遇到函数调用时不会进入,直接跳过
继续执行程序 continue
,可以发现💣解除了一个:
1 2 3 (gdb) c Continuing. Phase 1 defused. How about the next one?
GDB + Pwndbg 常用命令 整理一下 gdb + pwndbg 的一些常用命令
运行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $ gdb program # 运行程序,简写r (gdb) run # 带参数运行程序(method 1) (gdb) run arg1 arg2 # 带参数运行程序(method 2) (gdb) set args arg1 arg2 (gdb) run # 指定标准输入 (gdb) run <file (gdb) run < <(python3 -c 'print(b"A"*10)') (gdb) run <<<$(python3 -c 'print(b"A"*10)') # 链接到正在运行的进程,并进行调试 (gdb) attach {process-id} # 断开链接 (gdb) detach # 查看历史命令 (gdb) show commands # 执行上一条命令 (gdb) <enter> # 从文件中加载gdb命令 (gdb) source {filepath} # 退出gdb (简写q) (gdb) quit # 帮助 (gdb) help
1 2 # 查看 pwndbg 命令帮助 pwndbg> pwndbg
断点 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # 添加断点(指定函数名) (gdb) break main # 添加断点(指定内存地址) (gdb) break *0x00400123 # 列出所有断点信息(简写info b) (gdb) info breakpoints # 删除编号为1的断点 (gdb) delete 1 # 删除所有断点(简写del) (gdb) delete # 删除内存地址的断点 (gdb) clear *0x00400123 # 禁用指定编号断点 (gdb) disable 2 # 启用指定编号断点 (gdb) enable 2 # 条件断点 (gdb) condition {id} {expr} 2 i == 10 # 只有在 i==10 成立时2号断点生效 # 继续执行(简写c) (gdb) continue # 单步进入(遇到函数会进入) (gdb) stepi # 单步跳过(遇到函数不会进入) (gdb) nexti # 结束当前函数 (gdb) finish
源代码及反汇编 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # 查看指定函数附近的代码 (gdb) list main # 查看指定地址的代码 (gdb) list *0x00400800 # 添加源代码搜索路径 (gdb) dir {dirpath} # 复原源代码搜索路径 (gdb) dir # 查看源代码搜索路径 (gdb) show directories # 打印当前执行函数的汇编代码 (gdb) disas # 打印指定函数的反汇编代码 (gdb) disas main # 对指定地址进行反汇编 (gdb) disas {address} # 打印程序中的函数 (gdb) info functions # 更改显示风格 (gdb) set disassembly-flavor att (gdb) set disassembly-flavor intel
1 2 3 4 # 设置默认只显示源代码段 pwndbg> set context-sections code # 显示源代码段 pwndbg> ctx code
栈 1 2 3 4 5 6 7 8 # 打印backtrace(简写bt) (gdb) backtrace # 打印当前运行的栈帧 (gdb) frame # 切换到指定编号的栈帧 (gdb) frame {id} # 显示当前函数参数 (gdb) info args
数据查看 1 2 3 4 5 6 7 8 9 10 11 12 # 打印出表达式结果 (gdb) print {expression} # 十六进制输出结果 (gdb) print /x {expr} /x 十六进制 /o 八进制 /d 十进制 /t 二进制 # 打印历史记录条目 (gdb) print $1 # 打印指定寄存器数据 (gdb) print /x $rax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 从指定地址处读取数据 (gdb) x/[数量][长度单位][显示格式] where 长度单位: /b 以1字节为单位读取数据 /w 以4字节为单位读取数据 /g 以8字节为单位读取数据 /i 尝试解析成汇编 例如: (gdb) x/8gx $rsp+8 0x7fffffffe478: 0x00007fffffffe6ef 0x0000000000000000 0x7fffffffe488: 0x00007fffffffe70e 0x00007fffffffe729 0x7fffffffe498: 0x00007fffffffe739 0x00007fffffffe74c 0x7fffffffe4a8: 0x00007fffffffe758 0x00007fffffffe767 (gdb) x/4wd $rsp+8 0x7fffffffe478: -6417 32767 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # pwndbg 中加入的 db(dump byte) dw(dump word) dq(dump qword) # db address [count] , 命令后可以指定打印的数量, 不指定则使用默认值 pwndbg> db $rsp 00007fffffffe470 01 00 00 00 00 00 00 00 ef e6 ff ff ff 7f 00 00 00007fffffffe480 00 00 00 00 00 00 00 00 0e e7 ff ff ff 7f 00 00 00007fffffffe490 29 e7 ff ff ff 7f 00 00 39 e7 ff ff ff 7f 00 00 00007fffffffe4a0 4c e7 ff ff ff 7f 00 00 58 e7 ff ff ff 7f 00 00 pwndbg> dw $rsp 00007fffffffe470 0001 0000 0000 0000 e6ef ffff 7fff 0000 00007fffffffe480 0000 0000 0000 0000 e70e ffff 7fff 0000 00007fffffffe490 e729 ffff 7fff 0000 e739 ffff 7fff 0000 00007fffffffe4a0 e74c ffff 7fff 0000 e758 ffff 7fff 0000 pwndbg> dq $rsp 00007fffffffe470 0000000000000001 00007fffffffe6ef 00007fffffffe480 0000000000000000 00007fffffffe70e 00007fffffffe490 00007fffffffe729 00007fffffffe739 00007fffffffe4a0 00007fffffffe74c 00007fffffffe758
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 查看寄存器数据 (gdb) info registers # 打印本地局部变量 (gdb) info locals # 打印全局变量名称 (gdb) info variables # 查看类型定义 (gdb) ptype {typename} (gdb) ptype main_arena type = struct malloc_state { __libc_lock_t mutex; int flags; int have_fastchunks; mfastbinptr fastbinsY[10]; mchunkptr top; mchunkptr last_remainder; mchunkptr bins[254]; unsigned int binmap[4]; struct malloc_state *next; struct malloc_state *next_free; size_t attached_threads; size_t system_mem; size_t max_system_mem; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 # pwndbg 中加入 dt (Dump out information on a type (e.g. ucontext_t).) # 打印指定类型的信息(可选指定address) dt typename [address] pwndbg> dt FILE FILE +0x0000 _flags : int +0x0008 _IO_read_ptr : char * +0x0010 _IO_read_end : char * +0x0018 _IO_read_base : char * +0x0020 _IO_write_base : char * +0x0028 _IO_write_ptr : char * +0x0030 _IO_write_end : char * +0x0038 _IO_buf_base : char * +0x0040 _IO_buf_end : char * +0x0048 _IO_save_base : char * +0x0050 _IO_backup_base : char * +0x0058 _IO_save_end : char * +0x0060 _markers : struct _IO_marker * +0x0068 _chain : struct _IO_FILE * +0x0070 _fileno : int +0x0074 _flags2 : int +0x0078 _old_offset : __off_t +0x0080 _cur_column : short unsigned int +0x0082 _vtable_offset : signed char +0x0083 _shortbuf : char [1] +0x0088 _lock : _IO_lock_t * +0x0090 _offset : __off64_t +0x0098 _codecvt : struct _IO_codecvt * +0x00a0 _wide_data : struct _IO_wide_data * +0x00a8 _freeres_list : struct _IO_FILE * +0x00b0 _freeres_buf : void * +0x00b8 __pad5 : size_t +0x00c0 _mode : int +0x00c4 _unused2 : char [20] # 显示malloc_state结构体信息(有各个字段的偏移 pwndbg> dt "struct malloc_state" struct malloc_state +0x0000 mutex : __libc_lock_t +0x0004 flags : int +0x0008 have_fastchunks : int +0x0010 fastbinsY : mfastbinptr [10] +0x0060 top : mchunkptr +0x0068 last_remainder : mchunkptr +0x0070 bins : mchunkptr [254] +0x0860 binmap : unsigned int [4] +0x0870 next : struct malloc_state * +0x0878 next_free : struct malloc_state * +0x0880 attached_threads : size_t +0x0888 system_mem : size_t +0x0890 max_system_mem : size_t
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # pwndbg 中加入 xinfo(Shows offsets of the specified address to useful other locations) # 显示指定地址到有用位置的偏移 pwndbg> xinfo [address] pwndbg> xinfo Extended information for virtual address 0x5555555548d0: Containing mapping: 0x555555554000 0x55555555a000 r-xp 6000 0 /home/ubuntu/Documents/pwn/pwn Offset information: Mapped Area 0x5555555548d0 = 0x555555554000 + 0x8d0 File (Base) 0x5555555548d0 = 0x555555554000 + 0x8d0 File (Segment) 0x5555555548d0 = 0x555555554000 + 0x8d0 File (Disk) 0x5555555548d0 = /home/ubuntu/Documents/pwn/pwn + 0x8d0 Containing ELF sections: .text 0x5555555548d0 = 0x5555555548d0 + 0x0
堆 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # vis_heap_chunks(Visualize chunks on a heap, default to the current arena's active heap.) # 可视化显示当前堆分配情况 pwndbg> vis_heap_chunks pwndbg> heap pwndbg> bins pwndbg> fastbins pwndbg> smallbins pwndbg> largebins pwndbg> tcache pwndbg> tcachebins # malloc_chunk(Print a chunk.) # 打印出指定地址的 malloc_chunk pwndbg> malloc_chunk [addr]
进程调试 1 2 # 设置当进程调用fork时是否进入子进程 (gdb) set follow-fork-mode parent/child
其他 GDB 调试 16位程序
set arch i8086
命令并不能生效,下面的解决办法来自 这里
1 2 3 4 echo '<?xml version="1.0"?><!DOCTYPE target SYSTEM "gdb-target.dtd"><target><architecture>i8086</architecture><xi:include href="i386-32bit.xml"/></target>' > target.xml wget https://raw.githubusercontent.com/qemu/qemu/master/gdb-xml/i386-32bit.xml (gdb) set tdesc filename ./target.xml
1 2 3 4 5 <?xml version="1.0" ?> <!DOCTYPE target SYSTEM "gdb-target.dtd" > <target > <architecture > i8086</architecture > <xi:include href ="i386-32bit.xml" /> </target >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 <?xml version="1.0" ?> <!DOCTYPE target SYSTEM "gdb-target.dtd" > <feature name ="org.gnu.gdb.i386.core" > <flags id ="i386_eflags" size ="4" > <field name ="" start ="22" end ="31" /> <field name ="ID" start ="21" end ="21" /> <field name ="VIP" start ="20" end ="20" /> <field name ="VIF" start ="19" end ="19" /> <field name ="AC" start ="18" end ="18" /> <field name ="VM" start ="17" end ="17" /> <field name ="RF" start ="16" end ="16" /> <field name ="" start ="15" end ="15" /> <field name ="NT" start ="14" end ="14" /> <field name ="IOPL" start ="12" end ="13" /> <field name ="OF" start ="11" end ="11" /> <field name ="DF" start ="10" end ="10" /> <field name ="IF" start ="9" end ="9" /> <field name ="TF" start ="8" end ="8" /> <field name ="SF" start ="7" end ="7" /> <field name ="ZF" start ="6" end ="6" /> <field name ="" start ="5" end ="5" /> <field name ="AF" start ="4" end ="4" /> <field name ="" start ="3" end ="3" /> <field name ="PF" start ="2" end ="2" /> <field name ="" start ="1" end ="1" /> <field name ="CF" start ="0" end ="0" /> </flags > <reg name ="eax" bitsize ="32" type ="int32" regnum ="0" /> <reg name ="ecx" bitsize ="32" type ="int32" /> <reg name ="edx" bitsize ="32" type ="int32" /> <reg name ="ebx" bitsize ="32" type ="int32" /> <reg name ="esp" bitsize ="32" type ="data_ptr" /> <reg name ="ebp" bitsize ="32" type ="data_ptr" /> <reg name ="esi" bitsize ="32" type ="int32" /> <reg name ="edi" bitsize ="32" type ="int32" /> <reg name ="eip" bitsize ="32" type ="code_ptr" /> <reg name ="eflags" bitsize ="32" type ="i386_eflags" /> <reg name ="cs" bitsize ="32" type ="int32" /> <reg name ="ss" bitsize ="32" type ="int32" /> <reg name ="ds" bitsize ="32" type ="int32" /> <reg name ="es" bitsize ="32" type ="int32" /> <reg name ="fs" bitsize ="32" type ="int32" /> <reg name ="gs" bitsize ="32" type ="int32" /> <reg name ="fs_base" bitsize ="32" type ="int32" /> <reg name ="gs_base" bitsize ="32" type ="int32" /> <reg name ="k_gs_base" bitsize ="32" type ="int32" /> <flags id ="i386_cr0" size ="4" > <field name ="PG" start ="31" end ="31" /> <field name ="CD" start ="30" end ="30" /> <field name ="NW" start ="29" end ="29" /> <field name ="AM" start ="18" end ="18" /> <field name ="WP" start ="16" end ="16" /> <field name ="NE" start ="5" end ="5" /> <field name ="ET" start ="4" end ="4" /> <field name ="TS" start ="3" end ="3" /> <field name ="EM" start ="2" end ="2" /> <field name ="MP" start ="1" end ="1" /> <field name ="PE" start ="0" end ="0" /> </flags > <flags id ="i386_cr3" size ="4" > <field name ="PDBR" start ="12" end ="31" /> <field name ="PCID" start ="0" end ="11" /> </flags > <flags id ="i386_cr4" size ="4" > <field name ="VME" start ="0" end ="0" /> <field name ="PVI" start ="1" end ="1" /> <field name ="TSD" start ="2" end ="2" /> <field name ="DE" start ="3" end ="3" /> <field name ="PSE" start ="4" end ="4" /> <field name ="PAE" start ="5" end ="5" /> <field name ="MCE" start ="6" end ="6" /> <field name ="PGE" start ="7" end ="7" /> <field name ="PCE" start ="8" end ="8" /> <field name ="OSFXSR" start ="9" end ="9" /> <field name ="OSXMMEXCPT" start ="10" end ="10" /> <field name ="UMIP" start ="11" end ="11" /> <field name ="LA57" start ="12" end ="12" /> <field name ="VMXE" start ="13" end ="13" /> <field name ="SMXE" start ="14" end ="14" /> <field name ="FSGSBASE" start ="16" end ="16" /> <field name ="PCIDE" start ="17" end ="17" /> <field name ="OSXSAVE" start ="18" end ="18" /> <field name ="SMEP" start ="20" end ="20" /> <field name ="SMAP" start ="21" end ="21" /> <field name ="PKE" start ="22" end ="22" /> </flags > <flags id ="i386_efer" size ="8" > <field name ="TCE" start ="15" end ="15" /> <field name ="FFXSR" start ="14" end ="14" /> <field name ="LMSLE" start ="13" end ="13" /> <field name ="SVME" start ="12" end ="12" /> <field name ="NXE" start ="11" end ="11" /> <field name ="LMA" start ="10" end ="10" /> <field name ="LME" start ="8" end ="8" /> <field name ="SCE" start ="0" end ="0" /> </flags > <reg name ="cr0" bitsize ="32" type ="i386_cr0" /> <reg name ="cr2" bitsize ="32" type ="int32" /> <reg name ="cr3" bitsize ="32" type ="i386_cr3" /> <reg name ="cr4" bitsize ="32" type ="i386_cr4" /> <reg name ="cr8" bitsize ="32" type ="int32" /> <reg name ="efer" bitsize ="32" type ="i386_efer" /> <reg name ="st0" bitsize ="80" type ="i387_ext" /> <reg name ="st1" bitsize ="80" type ="i387_ext" /> <reg name ="st2" bitsize ="80" type ="i387_ext" /> <reg name ="st3" bitsize ="80" type ="i387_ext" /> <reg name ="st4" bitsize ="80" type ="i387_ext" /> <reg name ="st5" bitsize ="80" type ="i387_ext" /> <reg name ="st6" bitsize ="80" type ="i387_ext" /> <reg name ="st7" bitsize ="80" type ="i387_ext" /> <reg name ="fctrl" bitsize ="32" type ="int" group ="float" /> <reg name ="fstat" bitsize ="32" type ="int" group ="float" /> <reg name ="ftag" bitsize ="32" type ="int" group ="float" /> <reg name ="fiseg" bitsize ="32" type ="int" group ="float" /> <reg name ="fioff" bitsize ="32" type ="int" group ="float" /> <reg name ="foseg" bitsize ="32" type ="int" group ="float" /> <reg name ="fooff" bitsize ="32" type ="int" group ="float" /> <reg name ="fop" bitsize ="32" type ="int" group ="float" /> <vector id ="v4f" type ="ieee_single" count ="4" /> <vector id ="v2d" type ="ieee_double" count ="2" /> <vector id ="v16i8" type ="int8" count ="16" /> <vector id ="v8i16" type ="int16" count ="8" /> <vector id ="v4i32" type ="int32" count ="4" /> <vector id ="v2i64" type ="int64" count ="2" /> <union id ="vec128" > <field name ="v4_float" type ="v4f" /> <field name ="v2_double" type ="v2d" /> <field name ="v16_int8" type ="v16i8" /> <field name ="v8_int16" type ="v8i16" /> <field name ="v4_int32" type ="v4i32" /> <field name ="v2_int64" type ="v2i64" /> <field name ="uint128" type ="uint128" /> </union > <flags id ="i386_mxcsr" size ="4" > <field name ="IE" start ="0" end ="0" /> <field name ="DE" start ="1" end ="1" /> <field name ="ZE" start ="2" end ="2" /> <field name ="OE" start ="3" end ="3" /> <field name ="UE" start ="4" end ="4" /> <field name ="PE" start ="5" end ="5" /> <field name ="DAZ" start ="6" end ="6" /> <field name ="IM" start ="7" end ="7" /> <field name ="DM" start ="8" end ="8" /> <field name ="ZM" start ="9" end ="9" /> <field name ="OM" start ="10" end ="10" /> <field name ="UM" start ="11" end ="11" /> <field name ="PM" start ="12" end ="12" /> <field name ="FZ" start ="15" end ="15" /> </flags > <reg name ="xmm0" bitsize ="128" type ="vec128" /> <reg name ="xmm1" bitsize ="128" type ="vec128" /> <reg name ="xmm2" bitsize ="128" type ="vec128" /> <reg name ="xmm3" bitsize ="128" type ="vec128" /> <reg name ="xmm4" bitsize ="128" type ="vec128" /> <reg name ="xmm5" bitsize ="128" type ="vec128" /> <reg name ="xmm6" bitsize ="128" type ="vec128" /> <reg name ="xmm7" bitsize ="128" type ="vec128" /> <reg name ="mxcsr" bitsize ="32" type ="i386_mxcsr" group ="vector" /> </feature >