如何从一个C程序中或内联汇编得到一个C函数的大小? [英] How to get the size of a C function from inside a C program or with inline assembly?

查看:194
本文介绍了如何从一个C程序中或内联汇编得到一个C函数的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类似的功能如下:

 #猫003.cINT美孚(INT A,INT B)
{
    返回A + B;
}

并编译如下:

  GCC -S 003.c

将得到以下结果集:

  .file003.c
     。文本
 .globl富
     .TYPE富,@function
 富:
 .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%
     离开
     RET
 .LFE2:
     .size富。 - 富/ *函数foo的大小,怎么弄呢?* /

上面的最后一行做得到的函数的大小。哪里编译器存储的大小?我可以用得到某种方式的作用大小在我出身的C程序 C或内联汇编


解决方案

有关功能大小的信息存储在 ELF

属性的为相应的符号(名)。 C例程code如何以编程方式解析,这是在Solaris联机帮助页的 gelf_getsym(3ELF) (不libelf的Linux中存在,* BSD和MacOS,以及,你需要寻找的 st_size GElf_Sym 结构域),但你也可以使用objdump的用于/ elfdump(Solaris)上/ readelf(Linux)的任务:

 $ objdump的-h -d --section =的.text foo3.ofoo3.o:文件格式ELF64,X86-64部分:
IDX名称大小VMA LMA文件ALGN关闭
  0的.text 00000012 0000000000000000 0000000000000000 00000040 2 ** 2
                  内容ALLOC,LOAD,只读,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%)
   答:8B 45 F8 MOV 0xfffffffffffffff8(RBP%),%EAX
   D:03 45 FC加入0xfffffffffffffffc(RBP%),%EAX
  10:C9 leaveq
  11:C3 retq

这是你的code的未经优化的编译,而优化的版本是:

 $ objdump的-h -d --section =的.text foo3.ofoo3.o:文件格式ELF64,X86-64部分:
IDX名称大小VMA LMA文件ALGN关闭
  0的.text 00000004 0000000000000000 0000000000000000 00000040 2 ** 4
                  内容ALLOC,LOAD,只读,code
[...]
.text段拆卸:0000000000000000<富计算值:
   0:8D 04 37 LEA(%RDI,%RSI,1),%eax中
   3:C3 retq

请注意从 0×12 4 大小的变化?这是从 .size 汇编指令会发生什么。

在试图使用内联汇编,给你发挥作用的大小/ code位置的绝招是不是占编译器生成的胶水code(函数入口序言/出口尾声,直列code代,...),也不是编译器重新排序内联汇编(GCC是臭名昭著这样做),因此它不是一般相信这是一个好主意。最终,这取决于你想要做什么......

编辑:一些更多的引用,外部以及对计算器:


  1. 从gcc的邮件列表,上线的sizeof(功能)

  2. 什么的sizeof(函数名)返回?

  3. 查找用C
  4. 函数的大小
  5. 通过libelf的的例子SourceForge项目(这是文档/教程)

Suppose I have a function like below:

# cat 003.c

int foo(int a, int b)
{
    return a+b;
}

And compile it like this:

gcc -S 003.c

The gets the following assembly result:

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

The last line above do get the size of the function. Where does the compiler store the size? Can I get the function's size in some way in my origin C program using C or inline asm?

解决方案

The information about a function size is stored in the ELF Attributes for the corresponding symbol (name). C example code how to parse this programmatically is at the bottom of the Solaris manpage forgelf_getsym(3ELF) (libelf does exist in Linux, *BSD and MacOS as well, you need to look for the st_size field of the GElf_Sym structure), but you also can use objdump / elfdump (Solaris) / readelf (Linux) for the task:

$ 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

This is for an unoptimized compile of your code, while the optimized version is:

$ 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

Note the "Size" change from 0x12 to 4 ? That's what comes from the .size assembler directive.

The "trick" of trying to use inline assembly to give you function sizes / code locations isn't accounting for compiler-generated glue code (function entry prologues / exit epilogues, inline code generation, ...), nor for the compiler re-ordering inline assembly (gcc is notorious to do so), hence it's not generally a great idea to trust this. In the end, it depends on what exactly you're trying to do ...

Edit: A few more references, external as well as on stackoverflow:

  1. From the gcc mailing list, thread on sizeof(function)
  2. what does sizeof (function name) return?
  3. Find size of a function in C
  4. LibELF by example sourceforge project (this is documentation / a tutorial)

这篇关于如何从一个C程序中或内联汇编得到一个C函数的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆