很容易在C中获取函数的起始地址,但不是它的大小。所以我正在对目标文件做一个“nm”以找到我的函数,然后找到下一个函数的起始地址。我需要做“nm”,因为编译器可以(实际上,在我的情况下)重新排序函数,因此源顺序可以是对象顺序的不同。
我想知道是否有其他方法可以做到这一点。例如,指示编译器保留目标文件中的源代码顺序等。也许有些ELF魔术?
我的编译器是GCC,CLANG和Sun Studio。平台:Solaris和衍生产品,MacOSX,FreeBSD。为了在未来扩展。
答案 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 存根。)