知道编译的目标文件中C函数的大小

时间:2014-03-20 01:45:24

标签: c compiler-construction compiler-optimization elf object-files

很容易在C中获取函数的起始地址,但不是它的大小。所以我正在对目标文件做一个“nm”以找到我的函数,然后找到下一个函数的起始地址。我需要做“nm”,因为编译器可以(实际上,在我的情况下)重新排序函数,因此源顺序可以是对象顺序的不同。

我想知道是否有其他方法可以做到这一点。例如,指示编译器保留目标文件中的源代码顺序等。也许有些ELF魔术?

我的编译器是GCC,CLANG和Sun Studio。平台:Solaris和衍生产品,MacOSX,FreeBSD。为了在未来扩展。

1 个答案:

答案 0 :(得分:1)

我发现objdump -t xxx的输出将为程序和目标文件(.o)提供确定的函数大小/长度值。

例如:(来自我的一个项目)

objdump -t emma | grep " F .text"

0000000000401674 l F .text 0000000000000376 parse_program_header
00000000004027ce l F .text 0000000000000157 create_segment
00000000004019ea l F .text 000000000000050c parse_section_header
0000000000402660 l F .text 000000000000016e create_section
0000000000401ef6 l F .text 000000000000000a parse_symbol_section
000000000040252c l F .text 0000000000000134 create_symbol
00000000004032e0 g F .text 0000000000000002 __libc_csu_fini
0000000000402240 g F .text 000000000000002e emma_segment_count
00000000004022f1 g F .text 0000000000000055 emma_get_symbol
00000000004021bd g F .text 000000000000002e emma_section_count
0000000000402346 g F .text 00000000000001e6 emma_close
0000000000401f00 g F .text 000000000000002f emma_init
0000000000403270 g F .text 0000000000000065 __libc_csu_init
0000000000400c20 g F .text 0000000000000060 estr
00000000004022c3 g F .text 000000000000002e emma_symbol_count
0000000000400b10 g F .text 0000000000000000 _start
0000000000402925 g F .text 000000000000074f main
0000000000401f2f g F .text 000000000000028e emma_open

我已经修了一下这个名单,这很冗长。您可以看到第5列(第二个宽列,包含许多零....)为每个函数提供了一个长度值。 main长度为0x74f字节,emma_close为0x1e6,parse_symbol_section是一个微不足道的0x0a字节... 10个字节! (等等......是存根吗?)

此外,我只关注'F'unctions部分中的.text,从而进一步限制了列表。 -t的{​​{1}}选项仅显示符号表,因此省略了相当多的其他信息,这对于函数长度收集不是特别有用。

我想你可以像这样使用它:

objdump

一个例子:

objdump -t MYPROG | grep "MYFUNCTION$" | awk '{print "0x" $(NF-1)}' | xargs -I{} -- python -c 'print {}'

签出,因为0x50c == 1292。

我使用00000000004019ea l F .text 000000000000050c parse_section_header $ objdump -t emma | grep "parse_section_header$" | awk '{print "0x" $(NF-1)}' | xargs -I{} -- python -c 'print {}' 1292 来获取awk中的列,因为第二个字段的内容和空格可能会有所不同,具体取决于与所涉及符号相关的标识符。另外,请注意grep 中的结尾$(NF-1),导致$找到函数,而不是main作为main.c的条目它的名字。

xargs -I{} -- python -c 'print {}'位是将值从十六进制转换为十进制。如果有人能想到一个更简单的方法,请加入。(你可以看到awk隐藏0x前缀的位置。

啊,我记得我有objdump的别名,它为objdump预设了demangle选项。如果将--demangle添加到objdump调用中,它会使事情更容易匹配。 (我也使用--wide,更容易阅读,但不会影响这个特定的输出。)

这适用于任何 ELF对象,库,程序,目标文件,只要它 NOT 被剥离。 (我使用和不使用调试符号进行了测试)

希望这有帮助。

(我看,parse_symbol_section IS 存根。)