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:
sizeof(function)