寄存器说明:

rdi 存第1个参数(值或地址)

rsi 存第2个参数

rdx 存第3个参数

rcx 存第4个参数

r8 存第5个参数

r9 存第6个参数

rax 第1个返回值

rdx 第2个返回值

rbx、rbp、r12、r13、r14、r15 用作数据存储,遵循被调用者使用规则,调用子函数之前需要先保存

r10、r11 用作数据存储,遵循调用者使用规则,使用之前需要先保存

rsp 指向栈顶

观察参数传递,被调试的源代码如下:

/* 01 */ #include <string.h>

/* 02 */ #include <unistd.h>

/* 03 */ void f(int a, const char* b) {

/* 04 */     write(1234, b, strlen(b));

/* 05 */ }

/* 06 */ int main() {

/* 07 */     f(2018, "hello\n");

/* 08 */     return 0;

/* 09 */ }

优化方式编译程序:

g++ -g -O2 -o x x.cpp

实践目标:

在gdb中让write改写到标准输出。

设置两个观察点,一是main函数,二是write函数:

(gdb) b main

(gdb) b write

运行程序:

reakpoint 1, main () at x.cpp:6

6       /* 06 */ int main() {

Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.tl2.3.x86_64 libgcc-4.8.5-4.el7.x86_64 libstdc++-4.8.5-4.el7.x86_64

(gdb) n

7       /* 07 */     f(2018, "hello\n");

(gdb) disassemble

Dump of assembler code for function main():

0x0000000000400550 <+0>:     sub    $0x8,%rsp

=> 0x0000000000400554 <+4>:     mov    $0x400710,%esi // 0x400710为第二个参数的地址

0x0000000000400559 <+9>:     mov    $0x7e2,%edi // 0x7e2为第一个参数的值

0x000000000040055e <+14>:    callq  0x400660 <f(int, char const*)>

0x0000000000400563 <+19>:    xor    %eax,%eax

0x0000000000400565 <+21>:    add    $0x8,%rsp

0x0000000000400569 <+25>:    retq

End of assembler dump.

(gdb) p (char*)0x400710

$1 = 0x400710 "hello"

(gdb) p 0x7e2

$2 = 2018

(gdb) s

f (a=2018, b=0x400710 "hello") at x.cpp:3

3       /* 03 */ void f(int a, const char* b) {

(gdb) info reg

rax            0x400550 4195664

rbx            0x0      0

rcx            0x40     64

rdx            0x7fffffffe1a8   140737488347560

rsi            0x400710 4196112 // 第二个参数地址(4196112的十六进制为0x400710)

rdi            0x7e2    2018 // 第一个参数的值2018(2018的十六进制为0x7e2)

rbp            0x0      0x0

rsp            0x7fffffffe0a8   0x7fffffffe0a8

r8             0x7ffff75b5e80   140737343348352

r9             0x0      0

r10            0x7fffffffdd40   140737488346432

r11            0x7ffff7218b10   140737339558672

r12            0x40056c 4195692

r13            0x7fffffffe190   140737488347536

r14            0x0      0

r15            0x0      0

rip            0x400660 0x400660 <f(int, char const*)>

eflags         0x202    [ IF ]

cs             0x33     51

ss             0x2b     43

ds             0x0      0

es             0x0      0

fs             0x0      0

gs             0x0      0

(gdb) c

Continuing.

Breakpoint 2, 0x00007ffff72e0840 in write () from /lib64/libc.so.6

(gdb) info reg

rax            0x5      5

rbx            0x0      0

rcx            0x10     16

rdx            0x5      5 // write的第三个参数值

rsi            0x400710 4196112 // write的第二个参数值

rdi            0x1234   4660 // write的第一个参数值

rbp            0x0      0x0

rsp            0x7fffffffe0a8   0x7fffffffe0a8

r8             0x7ffff75b5e80   140737343348352

r9             0x0      0

r10            0x7fffffffdc70   140737488346224

r11            0x7ffff72e0840   140737340377152

r12            0x40056c 4195692

r13            0x7fffffffe190   140737488347536

r14            0x0      0

r15            0x0      0

rip            0x7ffff72e0840   0x7ffff72e0840 <write>

eflags         0x202    [ IF ]

cs             0x33     51

ss             0x2b     43

ds             0x0      0

es             0x0      0

fs             0x0      0

gs             0x0      0

(gdb) p $rdi

$4 = 4660

(gdb) set $rdi=7777 // 修改寄存器rdi的值

(gdb) p $rdi

$6 = 7777

(gdb) set $rdi=1

(gdb) c

Continuing.

hello // 正常输出到了标准输出,如果不修改rdi的值,将看不到输出“hello”

[Inferior 1 (process 6722) exited normally]

掌握此基础,就可以用来修改无源代码的程序等,比如希望jstatd在指定的端口上监听,而不是一个值为0的随机端口号,请参见《防火墙内JVisualVM连接jstatd解决方案》。

x86_64汇编调试程序初步的更多相关文章

  1. 【原创】X86_64汇编、寄存器、内嵌汇编

    整理的X86_64/X86汇编.寄存器.C内嵌汇编笔记,主要用于查阅使用. 目录 一.汇编语言 二.指令 数据传输指令 栈操作指令 push pop 运算指令 位操作 比较操作指令 标志寄存器 流控制 ...

  2. 【转载】汇编调试程序Debug使用

    https://blog.csdn.net/Notzuonotdied/article/details/70888205

  3. 【转】怎样创建一个Xcode插件(Part 1)

      原文:How To Create an Xcode Plugin: Part 1/3 原作者:Derek Selander 译者:@yohunl 译者注:原文使用的是xcode6.3.2,我翻译的 ...

  4. ObjC如何通过runtime修改Ivar的内存管理方式

    ObjC如何通过runtime修改Ivar的内存管理方式 为什么要这么做? 在iOS 9之前,UITableView(或者更确切的说是 UIScrollView)有一个众所周知的问题: propert ...

  5. centos7 docker 安装 mysql5.7.24 导入12G的sql

    先在CentOS7里面安装docker Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker .通过 uname - ...

  6. x64架构下Linux系统函数调用

    原文链接:https://blog.fanscore.cn/p/27/ 一. 函数调用相关指令 关于栈可以看下我之前的这篇文章x86 CPU与IA-32架构 在开始函数调用约定之前我们需要先了解一下几 ...

  7. 《30天自制操作系统》笔记2 --- 初步了解汇编产生的二进制(Day1)

    nask.exe应该就是nas kit(nas开发工具的意思),由于这个编译器是作者自己写的,所以这种汇编语言应该是作者改造出来的,所以我叫它nas汇编语言. 作者说nask是模仿nasm语法的,关于 ...

  8. ICS2019汇编实验在Linux下使用GDB调试程序

  9. iOS程序破解——ARM汇编基础

    原文在此:http://www.cnblogs.com/mddblog/p/4951650.html 一.Thumb指令与ARM指令 Thumb指令为16位,因此存储代码的密度高,节省存储空间.但是功 ...

随机推荐

  1. ORACLE数据库的关闭与重启

    一.关闭数据库 1.SHUTDOWN IMMEDIATE 这是我们常用的一种关闭数据库的方式,想很快地关闭数据库,但又想让数据库干净的关闭,常采用这种方式. 当前正在被Oracle处理的SQL语句立即 ...

  2. python 三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    http://www.cnblogs.com/linhaifeng/articles/7580830.html 三元表达式.列表推导式.生成器表达式.递归.匿名函数.内置函数

  3. Vs2015 c# 诊断工具查看程序的占用情况

    windbg用着还不熟悉,dottrace  还要版权,着急查看程序的cpu 的使用情况,因为程序开启之后占用处理器资源较大,问题在哪里呢,于是点开了vs2015自带的诊断工具,以前偶尔打开过,没发现 ...

  4. hdu 1558 (线段相交+并查集) Segment set

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐 ...

  5. Go语言之讲解GOROOT、GOPATH、GOBIN

    Go是一门全新的静态类型开发语言,具有自动垃圾回收,丰富的内置类型,函数多返回值,错误处理,匿名函数,并发编程,反射等特性. go命令依赖一个重要的环境变量:$GOPATH GOPATH允许多个目录, ...

  6. php中static静态关键字的使用方法和应用场景

    php中除了常规类和方法的使用,访问控制之外,还有静态关键字static,静态变量可以是局部变量也可以是全局变量,当一个程序段执行完毕时,静态变量并没有消失,它依然存在于内存中,下次在定义时还是以前的 ...

  7. BZOJ 1969 航线规划 - LCT 维护边双联通分量

    Solution 实际上就是查询 $u$ 到 $v$ 路径上 边双的个数 $ -1$. 并且题目仅有删边, 那么就离线倒序添边. 维护 边双 略有不同: 首先需要一个并查集, 记录 边双内的点. 在 ...

  8. MySQL 快速复数据库的方法

    为了方便快速复制一个数据库,可以用以下命令将db1数据库的数据以及表结构复制到newdb数据库 创建新的数据库 #mysql -u root -p123456 mysql>CREATE DATA ...

  9. [ES]elasticsearch章3 ES写入过程解析

    Elasticsearch的写 Elasticsearch采用多Shard方式,通过配置routing规则将数据分成多个数据子集,每个数据子集提供独立的索引和搜索功能.当写入文档的时候,根据routi ...

  10. python 字典遍历

    dic1={"name":"kxb","age":28}for k,v in dic1.items(): print(k+",,, ...