每天学点GDB(三)

简介: 本文讨论强大的反汇编能力,以及helloworld最先是从main函数开始执行的么?

<一>强大的反汇编能力

GDB提供了强大的反汇编能力,本节就围绕于该主题而展开。

继续以Hello.c为例。

1
2
3
4
5
6
7
#include <stdlib.h>
#include <stdio.h>
 
int main( int argc, char ** argv) {
   printf ( "hello,world\n" );
   return 0;
}

编译生成可执行文件

gcc -o hello -g hello.c

用gdb载入进行调试

gdb hello

反汇编main函数

disassemble main

以下为输出内容:

Dump of assembler code for function main:
    0x080483fc <+ 0 >:     push   %ebp
    0x080483fd <+ 1 >:     mov    %esp,%ebp
    0x080483ff <+ 3 >:     and    $ 0xfffffff0 ,%esp
    0x08048402 <+ 6 >:     sub    $ 0x10 ,%esp
    0x08048405 <+ 9 >:     movl   $ 0x80484b0 ,(%esp)
    0x0804840c <+ 16 >:    call   0x80482d0 <puts @plt >
    0x08048411 <+ 21 >:    mov    $ 0x0 ,%eax
    0x08048416 <+ 26 >:    leave
    0x08048417 <+ 27 >:    ret
End of assembler dump.

如果留心的话,可能发现在main函数中调用的printf并没有在反汇编中出现。原因在于printf其实使用的是puts。

如果已经知道了地址,想反过来查看是否对应为某一个函数的话,可以使用info symbol指令

info symbol 0x80482d0

输出为:

puts @plt in section .plt

说明地址0x80482d0对应于函数puts

与info symbol相对的指令为info address,可以通过名称获得其地址。继续为Puts为例:

info addr puts

输出为:

Symbol "puts" is at 0x80482d0 in a file compiled without debugging.

反汇编的另外一种方法就是使用x,当程序执行后(注意一定是程序运行后,停在断点处时),可以使用如下指令

x/3i $pc

<二>helloworld最先是从main函数开始执行的么?

今天探讨的话题是“helloworld最先是从main函数开始执行的么”。

1 #include <stdio.h>
2 #include <stdlib.h>
3 
4 int main(int argc, char** argv) {
5     printf("hello,world\n");
6     return 0;
7 }

一个最简单的程序,简单到任何人都能信手写来。如果静下来仔细想想,这个程序是如何执行的时候,总会有一些小小的疑惑。
那么用之前的GDB知识来看看这个执行过程吧。

gdb)br 5
gdb)r
gdb)bt

显示调用堆栈

gdb)bt
#0  main (argc=1, argv=0x7fffffffe918) at hello.c:5

进一步显示frame的信息

gdb)info frame
Stack level 0, frame at 0x7fffffffe840:
 rip = 0x40050f in main (hello.c:5); saved rip 0x7ffff7a4fa15
 source language c.
 Arglist at 0x7fffffffe830, args: argc=1, argv=0x7fffffffe918
 Locals at 0x7fffffffe830, Previous frame's sp is 0x7fffffffe840
 Saved registers:
  rbp at 0x7fffffffe830, rip at 0x7fffffffe838

注意两个register的值,分别是保存的rbp和rip. saved rip表示main被调用前的代码。可以用x来看看具体的函数名称

(gdb) x 0x7ffff7a4fa15
0x7ffff7a4fa15 <__libc_start_main+245>:    0xb4e8c789

或者利用另一种方法

info symbol 0x7ffff7a4fa15
__libc_start_main + 245 in section .text of /usr/lib/libc.so.6

至此,可断定main函数被__libc_start_main调用。

如果到这还不尽兴的话,可以用如下指令来看看__libc_start_main中有哪些内容,或者直接去下载glibc源码。

gdb)disassemble  __libc_start_main

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
8月前
|
NoSQL
GDB调试学习(三):观察点
GDB调试学习(三):观察点
81 0
本地内核调试神器 —— livekd 使用总结
本地内核调试神器 —— livekd 使用总结
|
8月前
|
NoSQL IDE Linux
《Linux从练气到飞升》No.09 Linux调试器-gdb使用
《Linux从练气到飞升》No.09 Linux调试器-gdb使用
61 0
《Linux从练气到飞升》No.09 Linux调试器-gdb使用
|
NoSQL Linux 编译器
Linux工具学习之【gdb】
vim 可以编写代码,gcc/g++ 可以编译代码,此时只最后一件神器,就能进行完整的开发工作,那就是通过 gdb 调试代码,毕竟谁都不敢保证自己的代码没有问题,所以就有调试器这种东西帮助我们定位问题,进而解决问题
215 0
Linux工具学习之【gdb】
|
存储 NoSQL JavaScript
如何优♂雅地学习GDB调试(二)
本章我们将带着大家高雅的学一学令众多习惯图形化页面的朋友难受的 gdb 调试,这部分知识可以选择性学习学习,以后倘若遇到一些问题时能在 Linux 内简单调试,还是很香的。然后在讲讲 gcc 和 g++,系统讲解程序运行时的各个过程。
219 0
如何优♂雅地学习GDB调试(二)
|
NoSQL Linux C语言
如何优♂雅地学习GDB调试(一)
本章我们将带着大家高雅的学一学令众多习惯图形化页面的朋友难受的 gdb 调试,这部分知识可以选择性学习学习,以后倘若遇到一些问题时能在 Linux 内简单调试,还是很香的。然后在讲讲 gcc 和 g++,系统讲解程序运行时的各个过程。
250 0
如何优♂雅地学习GDB调试(一)
|
NoSQL C++ 容器
每天学点GDB(五)
本节分享使用GDB来进行STL容器的调试。
1819 0
|
编译器 数据处理 C语言
ARM汇编
ARM汇编
146 0
|
NoSQL Python Windows
开源代码分析技巧之二——gdb单步调试
在海量的源码面前,如何更好的切入到源码,锁定我们需要的那一行,有时显得格外重要。
281 0
|
安全 数据安全/隐私保护 Windows

热门文章

最新文章