nm命令实战1: 分析ELF符号表&汇编输出

一.准备工作

1. main.c代码如下

extern int u_n1;
extern void u_func1();

long t_n3;
long d_n4 = 3;

int d_func2(){
	u_func1(u_n1, t_n3, d_n4);
}

2. 生成ELF文件命令

cc -o main.o -c main.c

二. 理论知识

1. nm命令的学习

nm命令

2. ELF的格式

  • ELF文件就是我们使用上述命令生成的文件(main.o),它以.o结尾,就是我们常说的可重定位目标文件。
    在这里插入图片描述

  • .text 存放代码节

  • .rodata 存放只读代码段

  • .rodata存放只读数据

  • .data存放已初始化数据

  • .bss存放未初始化数据

  • .symtab 就是我们博客的重点,符号表

3. .symtab

  • 经过预处理,编译,汇编之后,我们得到了ELF文件,但是并不是源文件中的每一个符号都会被我们所解析,所认知。
  • 正如我们提供的main.c一样,C++里有三类全局符号:
  • 引用的外部符号,以extern关键字标识
  • 全局定义但为初始化的符号,形如 int xxx;
  • 全局定义且初始化的符号,如int a = 3;
  • 现在我们要使用nm命令查看这三类符号

三. 使用nm命令分析ELF符号表

1. 打印.symtab

nm -f sysv -n main.o

其中-f指定了按照System5格式输出,-n指定了按照地址顺序排序

2. 分析符号表输出

输出

  • 注意看Class字段,U表示未定义,该符号的定义在别的文件中,t_func1和t_n1 是由extern关键字声明的,都是未定义的,这是符号我们预期的
  • T表示该符号位于.text区中,d_func2是我们定义的函数,符合预期,
  • D表示位于初始化数据段中,我们对于d_n4是给他初始化的,也符合预期
  • C表示未初始化的数据段,在链接的过程中才对其分配,value为其预估的字节长度,这里t_n3需要8个字节,未初始化,均符合预期。

3. 反汇编

首先反汇编:objdump -d main.o
得到输出如下:
在这里插入图片描述

4. 汇编输出逐行解释

  • 第一行:
    在这里插入图片描述
    我们的main.o还没有链接,所以此时的地址仍然是一个相对地址,所以d_func2的地址是从0x000…00开始,作为对比,稍后我会展示生成可执行文件后的地址

  • 第二,三行
    在这里插入图片描述
    函数调用是要压栈的,所以我们要保存%rsp栈指针的旧值,以便随后恢复上下文,我们将%rsp放入%rbp, 会破坏rbp,所以我们先让rbp的值入栈。

  • 中间对程序计数器的操作

  • 然后是参数入栈

  • 注意寄存器的顺序,第一个参数是%rsi,第二个是%rdi,依次类推…

  • eax是返回值

  • 最后是调用和现场恢复
    在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值