有没有办法单独输出单个函数的汇编?

问题描述 投票:0回答:2

我正在学习如何将 C 文件编译为机器代码。我知道我可以使用

gcc
标志从
-S
生成程序集,但是它也会生成很多与
main()
printf()
相关的代码,我目前对此不感兴趣。

有没有办法让

gcc
clang
独立地“编译”函数并输出程序集?

单独获取以下 c 的程序集:

int add( int a, int b ) {
    return a + b;
}
assembly gcc clang
2个回答
16
投票

对于特定的目标文件有两种方法可以执行此操作:

  1. -ffunction-sections
    gcc
    选项指示它为正在编译的源文件中的每个函数创建一个单独的ELF部分
  2. 符号表包含给定函数的段名、起始地址和大小;可以通过
    objdump
    /
    --start-address
    参数输入
    --stop-address

第一个例子:

$ readelf -S t.o | grep '.text.'
  [1] .text PROGBITS 0000000000000000 00000040
  [4] .text.foo PROGBITS 0000000000000000 00000040
  [6] .text.bar PROGBITS 0000000000000000 00000060
  [9] .text.foo2 PROGBITS 0000000000000000 000000c0
  [11] .text.munch PROGBITS 0000000000000000 00000110
  [14].text.startup.mai PROGBITS 0000000000000000 00000180

这是用

-ffunction-sections
编译的,在我的目标文件中有四个函数,
foo()
bar()
foo2()
munch()
。我可以像这样单独拆卸它们:

$ objdump -w -d --section=.text.foo to.o

to.o:文件格式 elf64-x86-64

.text.foo 部分的反汇编:

0000000000000000 :
   0: 48 83 ec 08 子 $0x8,%rsp
   4: 8b 3d 00 00 00 00 mov 0(%rip),%edi # a 
   a: 31 f6 异或 %esi,%esi
   c: 31 c0 异或 %eax,%eax
   e: e8 00 00 00 00 呼叫 13 
  13: 85 c0 测试 %eax,%eax
  15: 75 01 jne 18 
  17:90 没有
  18: 48 83 c4 08 添加 $0x8,%rsp
  1c: c3 retq

另一个选项可以像这样使用(

nm
转储符号表条目):

$ nm -f sysv t.o | $ nm -f sysv t.o | grep 栏
酒吧|0000000000000020|   T |    功能|0000000000000026|     |.文本
$ objdump -w -d --start-address=0x20 --stop-address=0x46 to--section=.text

to.o:文件格式 elf64-x86-64

.text 节的反汇编:

0000000000000020 :
  20: 48 83 ec 08 子 $0x8,%rsp
  24: 8b 3d 00 00 00 00 mov 0(%rip),%edi # 2a 
  2a: 31 f6 异或 %esi,%esi
  2c: 31 c0 异或 %eax,%eax
  2e: e8 00 00 00 00 呼叫 33 
  33: 85 c0 测试 %eax,%eax
  35:75 01 jne 38 
  37:90 没有
  38: bf 3f 00 00 00 移动 $0x3f,%edi
  3d: 48 83 c4 08 添加 $0x8,%rsp
  41:e9 00 00 00 00 jmpq 46 

在这种情况下,

-ffunction-sections
选项尚未使用,因此函数的起始偏移量不为零,并且它不在其单独的部分中(但在
.text
中)。

反汇编目标文件时要小心...

这不是完全你想要的,因为,对于目标文件,

call
目标(以及全局变量的地址)没有解析 - 你在这里看不到
foo
调用
printf 
,因为二进制级别的解析仅发生在链接时。不过,汇编源代码中会有
call printf
。这个
callq
实际上是
printf
的信息位于目标文件中,但与代码分开(它位于所谓的 relocation 部分,列出了目标文件中要由链接器“修补”的位置);反汇编程序无法解决这个问题。


2
投票

最好的方法是将函数复制到单个

temp.c
C 文件中,并使用
-c
标志进行编译,如下所示:
gcc -c -S temp.c -o temp.s

它应该生成更紧凑的汇编代码,没有其他干扰(页眉和页脚除外)。

© www.soinside.com 2019 - 2024. All rights reserved.