如何从C程序内部或内联汇编中获取C函数的大小?

yan*_*wen 7 c assembly gcc gnu-assembler elf

假设我有如下函数:

# cat 003.c

int foo(int a, int b)
{
    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

并像这样编译它:

gcc -S 003.c
Run Code Online (Sandbox Code Playgroud)

得到以下汇编结果:

     .file   "003.c"
     .text
 .globl foo
     .type   foo, @function
 foo:
 .LFB2:
     pushq   %rbp
 .LCFI0:
     movq    %rsp, %rbp
 .LCFI1:
     movl    %edi, -4(%rbp)
     movl    %esi, -8(%rbp)
     movl    -8(%rbp), %edx
     movl    -4(%rbp), %eax
     addl    %edx, %eax
     leave
     ret
 .LFE2:
     .size   foo, .-foo /* size of the function foo, how to get it?*/
Run Code Online (Sandbox Code Playgroud)

上面的最后一行确实得到了函数的大小.编译器在哪里存储大小?我可以使用C或内联asm在我的原始C程序中以某种方式获取函数的大小吗?

Fra*_*kH. 13

有关函数大小的信息存储在相应符号(名称)的ELF属性中.C示例代码如何以编程方式解析它是在Solaris手册页的底部gelf_getsym(3ELF)(libelf确实存在于Linux,*BSD和MacOS中,你需要查找结构的st_size字段GElf_Sym),但你也可以使用objdump/elfdump(Solaris)/ readelf(Linux)的任务:

$ objdump -h -d --section=.text foo3.o

foo3.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000012  0000000000000000  0000000000000000  00000040  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
[ ... ]
Disassembly of section .text:

0000000000000000 <foo>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   89 7d fc                mov    %edi,0xfffffffffffffffc(%rbp)
   7:   89 75 f8                mov    %esi,0xfffffffffffffff8(%rbp)
   a:   8b 45 f8                mov    0xfffffffffffffff8(%rbp),%eax
   d:   03 45 fc                add    0xfffffffffffffffc(%rbp),%eax
  10:   c9                      leaveq
  11:   c3                      retq

这是对未经优化的代码编译,而优化版本是:

$ objdump -h -d --section=.text foo3.o

foo3.o:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000004  0000000000000000  0000000000000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
[ ... ]
Disassembly of section .text:

0000000000000000 <foo>:
   0:   8d 04 37                lea    (%rdi,%rsi,1),%eax
   3:   c3                      retq

注意"大小"从0x12变为4?这就是.size汇编程序指令的内容.

尝试使用内联汇编为您提供函数大小/代码位置的"技巧"不考虑编译器生成的粘合代码(函数入口序言/退出结尾,内联代码生成......),也不考虑编译器重新编写 - 内联汇编(gcc因此而臭名昭着)因此,相信这一点并不是一个好主意.最后,这取决于你究竟要做什么......

编辑:一些引用,外部以及stackoverflow:

  1. 从gcc邮件列表中,线程打开sizeof(function)
  2. sizeof(函数名)返回什么?
  3. 在C中查找函数的大小
  4. LibELF通过示例 sourceforge项目(这是文档/教程)