专栏首页高性能服务器开发Linux GDB jump 命令介绍

Linux GDB jump 命令介绍

jump 命令基本用法是:

jump <location>

location 可以是程序的行号或者函数的地址,jump 会让程序执行流跳转到指定位置执行,当然其行为也是不可控制的,例如您跳过了某个对象的初始化代码,直接执行操作该对象的代码,那么可能会导致程序崩溃或其他意外行为。jump 命令可以简写成 j,但是不可以简写成 jmp,其使用有一个注意事项,即如果 jump 跳转到的位置后续没有断点,那么 GDB 会执行完跳转处的代码会继续执行。举个例子:

1 int somefunc()
2 {
3   //代码A
4   //代码B
5   //代码C
6   //代码D
7   //代码E
8   //代码F    
9 }

假设我们的断点初始位置在行号 3 处(代码 A),这个时候我们使用 jump 6,那么程序会跳过代码 B 和 C 的执行,执行完代码 D( 跳转点),程序并不会停在代码 6 处,而是继续执行后续代码,因此如果我们想查看执行跳转处的代码后的结果,需要在行号 678 处设置断点。

jump 命令除了跳过一些代码的执行外,还有一个妙用就是可以执行一些我们想要执行的代码,而这些代码在正常的逻辑下可能并不会执行(当然可能也因此会产生一些意外的结果,这需要读者自行斟酌使用)。举个例子,假设现在有如下代码:

1  #include <stdio.h>
2  int main()
3  {
4    int a = 0;
5    if (a != 0)
6    {
7      printf("if condition\n");
8    }
9    else
10   {
11     printf("else condition\n");
12   }
13
14   return 0;
15 }

我们在行号 414 处设置一个断点,当触发行号 4 处的断点后,正常情况下程序执行流会走 else 分支,我们可以使用 jump 7 强行让程序执行 if 分支,接着 GDB 会因触发行号 14 处的断点而停下来,此时我们接着执行 jump 11,程序会将 else 分支中的代码重新执行一遍。整个操作过程如下:

[root@localhost testcore]# gdb test
Reading symbols from /root/testcore/test...done.
(gdb) b main
Breakpoint 1 at 0x400545: file main.cpp, line 4.
(gdb) b 14
Breakpoint 2 at 0x400568: file main.cpp, line 14.
(gdb) r
Starting program: /root/testcore/test 

Breakpoint 1, main () at main.cpp:4
4       int a = 0;
Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libstdc++-4.8.5-36.el7.x86_64
(gdb) jump 7
Continuing at 0x400552.
if condition

Breakpoint 2, main () at main.cpp:14
14       return 0;
(gdb) jump 11
Continuing at 0x40055e.
else condition

Breakpoint 2, main () at main.cpp:14
14       return 0;
(gdb) c
Continuing.
[Inferior 1 (process 13349) exited normally]
(gdb)

redis-server 在入口函数 main 处调用 initServer() ,我们使用 “b initServer” 、“b 2025”、“b 2027”在这个函数入口处、2025 行、2027 行增加三个断点,然后使用 run 命令重新运行一下程序,触发第一个断点后,继续输入 c 命令继续运行,然后触发 2025 行处的断点,接着输入 jmp 2027

(gdb) b 2025
Breakpoint 5 at 0x42c8e7: file server.c, line 2025.
(gdb) b 2027
Breakpoint 6 at 0x42c8f8: file server.c, line 2027.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) n     
Program not restarted.
(gdb) b initServer
Note: breakpoint 3 also set at pc 0x42c8b0.
Breakpoint 7 at 0x42c8b0: file server.c, line 2013.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/redis-5.0.3/src/redis-server 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".

Breakpoint 1, main (argc=1, argv=0x7fffffffe4e8) at server.c:4003
4003    int main(int argc, char **argv) {
(gdb) c
Continuing.
13374:C 14 Jan 2019 15:12:16.571 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
13374:C 14 Jan 2019 15:12:16.571 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=13374, just started
13374:C 14 Jan 2019 15:12:16.571 # Warning: no config file specified, using the default config. In order to specify a config file use /root/redis-5.0.3/src/redis-server /path/to/redis.conf

Breakpoint 3, initServer () at server.c:2013
2013    void initServer(void) {
(gdb) c
Continuing.

Breakpoint 5, initServer () at server.c:2025
2025        server.hz = server.config_hz;
(gdb) jump 2027
Continuing at 0x42c8f8.

Breakpoint 6, initServer () at server.c:2027
2027        server.current_client = NULL;
(gdb) 

程序将 2026 行的代码跳过了,2026 行处的代码是获取当前进程 id:

2026 server.pid = getpid();

由于这一行被跳过了,所以 server.pid 的值应该是一个无效的值,我们可以使用 print 命令将这个值打印出来看一下:

(gdb) p server.pid
$3 = 0

结果确实是 0 这个我们初始化的无效值。

本质上,jump 命令的作用类似于在 Visual Studio 中调试时,拖鼠标将程序从一个执行处拖到另外一个执行处。

本文分享自微信公众号 - 高性能服务器开发(easyserverdev)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 直击架构本质:优秀架构师必须掌握的几种架构思维

    架构的本质是管理复杂性,抽象、分层、分治和演化思维是我们工程师/架构师应对和管理复杂性的四种最基本武器。

    范蠡
  • (三)服务器端的程序架构介绍1

    通过上一节的编译与部署,我们会得到TeamTalk服务器端以下部署程序: db_proxy_server file_server http_msg_server...

    范蠡
  • 用两张图告诉你,为什么你的App会卡顿?

    有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? 知道Android究竟是如何在屏幕上显示我们期望的画面的? 对A...

    范蠡
  • RSA 创新沙盒盘点| BluBracket:让安全的保障和代码迭代一样快

    2020年2月24日-28日,网络安全行业盛会RSA Conference将在旧金山拉开帷幕。在RSAC官方宣布入选今年创新沙盒十强初创公司中,已经为大家介绍过...

    绿盟科技研究通讯
  • 成为一名更好的程序员:如何阅读源代码

    成为一名更好的程序员:如何阅读源代码 阅读源代码有许多益处。你会发现新的架构(construct)和库,与其他的代码维护者产生共鸣,但最重要的是学会如何组织代码...

    用户1289394
  • 墨菲定律:一个参数Drop_caches导致集群数据库实例崩溃

    李真旭@killdb Oracle ACE,云和恩墨技术专家 个人博客:www.killdb.com 在墨菲定律里,我们知道,有可能发生的故障就一定会发生,哪怕...

    数据和云
  • 儿童编程“控制”部分学习总结

    在任何编程语言中,控制部分都是非常重要的,也是体现编程语言神奇之处。在Scratch中同样如此。初次学习肯定会感觉有些抽象,但是在实际应用之中,则会体现出其功能...

    一石匠人
  • 快速学习-Sentinel 熔断降级

    熔断降级是指当资源处于不稳定的情况下,在接下来的时间窗口之内,对该资源的调用都自动熔断。我们通常用两种方式来衡量资源是否处于稳定的状态:

    cwl_java
  • Python自动化运维之Keepalived

    海仔
  • 人类仍是最好的有损图片压缩器

    本文是来自Stanford Compression Workshop 2019的演讲,讲者是三位高中生:来自Palo Alto High School的Ashu...

    用户1324186

扫码关注云+社区

领取腾讯云代金券