基于dynamorio自制反汇编小工具 instr_trace安装

概述

该工具可以对程序进行反汇编,然后打印出运行每个汇编时各个寄存器的值(类似于gdb单步调试,然后每一步都打印寄存器的值)。同时可以实时地打印各个分支跳转指令实际跳转的方向。

一、下载源码

这个不是dynamorio的官方仓库,是我自己fork出来的,加了自己的代码

git clone https://gitee.com/xiaolicangdao/instr_trace.git dynamorio

二、安装dynamorio

为了方便,我在WSL进行的环境配置

1、安装依赖

sudo apt-get install cmake g++ g++-multilib doxygen git zlib1g-dev

cmake版本有一定要求,如果apt安装的版本不够新,可以自己从源码安装

2、编译

$ cd dynamorio
$ mkdir build
$ cd build

# 以防有人对cmake不熟悉,提示一下注意命令后面有两个点
$ cmake ..

$ make -j

3、测试安装是否成功

$ ./bin64/drrun echo hello world

参考截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、安装instr_trace工具

1、文件说明

mytool文件下为instr_trace工具的所有内容,run.sh为参考运行脚本

2、编译

$ cd mytool/build
$ bash compile.sh

3、运行

前提:切换当前目录到dynamorio的主目录
参数解释:bash run.sh 程序 trace文件

$ bash run.sh ~/test/test ./test.asm
$ head ./test.asm # 查看文件的前10行

参考截图:
在这里插入图片描述
在这里插入图片描述

四、生成的文件格式说明

我利用dynamorio工具打印出了每条指令的源操作数、源操作数的值和目标操作数(注意没有打印目标操作数的值,因为脚本的功能不够完善),且注释的格式是我自己根据实际需要写的,并不是说非要使用这个格式。
下面挑几个例子介绍一下

(1)mov指令(寄存器->寄存器)

mov    rbp, rsp
; dst: reg: rbp(8 byte) 
; src: rsp 0x00007ffff85e7280
; 0.000000
  1. mov rbp, rsp:反汇编的指令
  2. ; dst: reg: rbp(8 byte) dst表示它是目标操作数,reg表示目标操作数是寄存器类型,rbp为具体的寄存器名称,(8byte)表示这个指令操作的数据宽度为8byte,即64bit
  3. ; src: rsp 0x00007ffff85e7280src表示它是源操作数,rsp为具体的寄存器名称,0x00007ffff85e7280为该寄存器的值(这个值显然是一个地址)
  4. ; 0.000000:是源操作数的浮点数格式,即将源操作数的值用浮点数来解释,在此处是没有意义的,因为rsp寄存器里放的并不是浮点数。

(2)mov指令(内存->寄存器)

mov    rax, qword ptr [0x00491eb0]
; dst: reg: rax(8 byte) 
; src: mem: 0x491eb0, read_sz=0x8, val=0x00000002 0x00000001
; 0.000000
  1. mov rax, qword ptr [0x00491eb0]:反汇编的指令
  2. dst: reg: rax(8 byte) :略
  3. ; src: mem: 0x491eb0, read_sz=0x8, val=0x00000002 0x00000001src表示它是源操作数,mem表示源操作数是内存类型的,0x491eb0为内存地址(单位为byte),read_sz=0x8表示该操作的数据宽度为8byte,val=0x00000002 0x00000001为该内存指向的内存的值,val宽度与前面对应,为8byte。
    注意:val的值我是按高地址到地址打印的,即0x00000002为高地址(0x491eb0+0x4),0x00000001为低地址(0x491eb0),这个可以使用gdb验证。
  4. ; 0.000000:在此处没有意义的,因为源操作数不是浮点数。

(3)mov指令(寄存器->内存)

mov    qword ptr [rbp-0x28], rax
; dst: mem: 0x7ffff85e7258(8 byte) 
; src: rax 0x0000000400000003
; 0.000000
  1. mov qword ptr [rbp-0x28], rax:反汇编的指令
  2. ; dst: mem: 0x7ffff85e7258(8 byte) dst表示它是目标操作数,mem表示目标操作数是内存类型,0x7ffff85e7258为具体的内存地址,(8byte)表示数据宽度为8byte
  3. ; src: rax 0x0000000400000003src表示它是源操作数,rax 表示源操作数的寄存器为rax,0x0000000400000003为该寄存器的值,val宽度与前面对应,为8byte。
    注意:rax 的值我也是按高地址到地址打印的,即0x00000004为rax寄存器的高地址部分,0x00000003为rax寄存器的低地址部分(即eax寄存器),这个也可以使用gdb验证。
  4. ; 0.000000:在此处没有意义的,因为源操作数不是浮点数。

(4)lea指令

lea    rdi, [rbp-0x30]
; dst: reg: rdi(8 byte) 
; src: mem: 0x7ffff85e7250, read_sz=0x0, val=0x00
; 0 double:
; 0 float:
  1. lea rdi, [rbp-0x30]:反汇编的指令,lea指令相当于c语言中的&(取地址操作)
  2. ; dst: reg: rdi(8 byte) :目标寄存器
  3. ; src: mem: 0x7ffff85e7250, read_sz=0x0, val=0x00src表示它是源操作数,mem表示源操作数为地址,然后注意read_sz=0,即它没有从内存中取数据,它只是在计算地址,即rdi=[rbp-0x30]的地址,而不是[rbp-0x30]的数据。
  4. 0 double:和; 0 float::在此处没有意义的,因为源操作数不是浮点数。

(5)jmp指令

jmp    <INVALID>
; src: 

无条件跳转指令,没有源操作数和目标操作数
关于跳转指令,可以参考跳转指令手册

(6) cmp指令

cmp 0x7ffff85e71ec(mem) 0x8 
; src: mem: 0x7ffff85e71ec, read_sz=0x4, val=0x00000004
; 0.000000
; src: (int)0x8
  1. cmp 0x7ffff85e71ec(mem) 0x8 ]:反汇编的指令,cmp指令是比较两个操作数,然后设置标志位寄存器,此处是比较内存0x7ffff85e71ec处的数据与立即数0x8
  2. ; src: mem: 0x7ffff85e71ec, read_sz=0x4, val=0x00000004:打印了地址0x7ffff85e71ec处的值
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
class cpu_model; bit [31:0] r0, r1, r2, r3; bit [31:0] sram [256]; enum { ADD, LOAD, STORE } instruct_type; typedef struct packed { instruct_type type; bit [31:0] data; bit [7:0] addr; bit [1:0] reg1, reg2, dest_reg; } instruct; bit clk, reset; bit instr_valid, [31:0] instr_data; interface clk_rst_if; modport clk_rst ( input wire clk, reset, input wire instr_valid, input wire [31:0] instr_data ); endinterface interface bus_if; modport cpu_bus ( output reg [31:0] r0, r1, r2, r3, output reg [31:0] sram [256], input wire [31:0] instr_data, input wire reg1, reg2, dest_reg, input wire [7:0] addr, input wire instr_valid ); endinterface task drive_cpu (); input clk, reset, instr_valid; input [31:0] instr_data; clk_rst_if clk_rst(); bus_if cpu_bus(); begin r0 = r1 = r2 = r3 = 0; instr_valid = 0; instr_data = 0; forever begin @(posedge clk); if (reset) begin r0 = r1 = r2 = r3 = 0; end else if (instr_valid) begin instruct inst; inst = get_instr(instr_data); case (inst.type) ADD: r[inst.dest_reg] = r[inst.reg1] + r[inst.reg2]; LOAD: r[inst.dest_reg] = sram[inst.addr]; STORE: sram[inst.addr] = r[inst.reg1]; endcase end end end endtask task monitor (); input clk; clk_rst_if clk_rst(); bus_if cpu_bus(); begin @(posedge clk); $display("r0 = %d, r1 = %d, r2 = %d, r3 = %d", r0, r1, r2, r3); @(posedge clk); for (int i = 0; i < 256; i++) begin $display("sram[%0d] = %d", i, sram[i]); end end endtask function automatic instruct get_instr (input [31:0] instr_data); instruct inst; if (instr_data[31:30] == 2'b00) begin inst.type = ADD; inst.reg1 = instr_data[29:28]; inst.reg2 = instr_data[27:26]; inst.dest_reg = instr_data[25:24]; end else if (instr_data[31:30] == 2'b01) begin if (instr_data[26]) begin inst.type = LOAD; inst.data = instr_data[23:16]; inst.dest_reg = instr_data[11:8]; end else begin inst.type = LOAD; inst.addr = instr_data[7:0]; inst.dest_reg = instr_data[11:8]; end end else if (instr_data[31:30] == 2'b10) begin if (instr_data[26]) begin inst.type = STORE; inst.data = instr_data[23:16]; inst.reg1 = instr_data[11:8]; end else begin inst.type = STORE; inst.addr = instr_data[7:0]; inst.reg1 = instr_data[11:8]; end end return inst; endfunction endclass
05-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值