How to get the size of a C function from inside a C program or with inline assembly?

醉酒当歌 提交于 2019-11-27 14:29:42
FrankH.

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)
Felice Pollano

Why don't take the difference of the pointer of the function and the current address at the end of the function ? Have a look at this question to recover the current IP address: Get address of current instruction for x86, may be this code, stolen form one of the reply:

unsigned long get_PC()
{
    unsigned long current_instruction;

    __asm__ __volatile__
    (
        "movq 8(%rbp), %rax\n\t"
        : "=a" (current_instruction)
    );

    return current_instruction;
}

would do the trick,

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!