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

标签 c gcc assembly elf gnu-assembler

假设我有如下函数:

# 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 属性 中。如何以编程方式解析此 C 示例代码位于 gelf_getsym(3ELF) 的 Solaris 联机帮助页底部(libelf在Linux、*BSD和MacOS中也存在,你需要寻找GElf_Sym结构的st_size字段),但你也可以使用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 邮件列表,thread on sizeof(function)
  2. what does sizeof (function name) return?
  3. Find size of a function in C
  4. LibELF by example sourceforge 项目(这是文档/教程)

关于c - 如何从 C 程序内部或使用内联汇编获取 C 函数的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11410037/

相关文章:

c - memcpy 遇到问题

c - 我应该使用 strdup() 还是只分配一个地址?

c - 需要帮助了解 Linux 内核的 BIOS 中断调用

c++ - 在 C++ 中使用 __asm 将 short 类型的变量移动到 EAX(VS 2010)

c - 如何在 Cygwin 中获得有用的回溯?

c++ - 从 main 调用 C++ 源文件中的函数

c++ - 打印所有继承的类成员变量和方法

optimization - GCC热属性语义

c - Linux新手问题: GCC Compiler output

c - 在 C 中使用汇编全局变量