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

假设我有如下函数:

# cat 003.c int foo(int a, int b) { return a+b; } 

并编译它像这样:

 gcc -S 003.c 

得到以下汇编结果:

  .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?*/ 

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

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

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

 foo3.o:文件格式为elf64-x86-64

部分:
 Idx名称大小VMA LMA文件关闭Algn
   0 .text 00000012 0000000000000000 0000000000000000 00000040 2 ** 2
                  内容,ALLOC,LOAD,READONLY,CODE
 [...]
反汇编.text:

 0000000000000000 :
    0:55推%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:文件格式为elf64-x86-64

部分:
 Idx名称大小VMA LMA文件关闭Algn
   0 .text 00000004 0000000000000000 0000000000000000 00000040 2 ** 4
                  内容,ALLOC,LOAD,READONLY,CODE
 [...]
反汇编.text:

 0000000000000000 :
    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项目(这是文档/教程)

为什么不在function结束时采用函数指针和当前地址的区别? 看看这个问题来恢复当前的IP地址: 获取x86当前指令的地址 ,可能是这段代码, 被盗forms的回复之一 :

 unsigned long get_PC() { unsigned long current_instruction; __asm__ __volatile__ ( "movq 8(%rbp), %rax\n\t" : "=a" (current_instruction) ); return current_instruction; } 

会做的伎俩,