I’d really like some tool (ideally,g++ based) that shows me what parts of compiled/linked code are generated from what parts of C++ source code. For instance,to see whether a particular template is being instantiated for hundreds of different types (fixable via a template specialization) or whether code is being inlined excessively,or whether particular functions are larger than expected.
解决方法
首先你可能已经知道的一些东西:
addr2line命令接收一个地址,并可以告诉您机器代码所在的源代码在哪里.可执行文件需要使用调试符号构建,您可能不希望对其进行优化(-O0,-O1或-Os可能与您最初想要的一样高). addr2line有几个标志,您将需要阅读其手册页面,但如果要查看输出中有意义的C函数名称,那么肯定需要使用-C或–demangle.
objdump命令可以打印出许多类型的对象文件中有关这些东西的各种有趣的东西.它可以做的一件事就是打印出一个表,表示一个目标文件(包括可执行文件)中的符号或由其引用的表.
现在,你想要做的是:
你想要的是objdump告诉你的.text部分的地址和大小.这就是实际的可执行机器码所在的地方.有几种方法可以做到这一点,但最简单(对于这一点,无论如何)可能是为了你做:
objdump -h my_exe | grep text
这应该会导致如下:
12 .text 0000049 000000f000 0000000f000 00000400 2**4
如果你没有grep它会给你一个标题,如:
Idx Name Size VMA LMA File off Algn
我认为对于可执行文件,VMA和LMA应该是一样的,所以不用你使用什么,但我认为LMA是最好的.你也想要大小.
使用LMA和大小,您可以重复地调用addr2line来询问机器代码的源代码.如果您通过一个教学内的地址,我不知道这将如何工作,但我认为它应该有效.
addr2line -e my_exe <address>
此输出将是路径/文件名,冒号和行号.
如果您计算每个唯一路径/文件的发生次数:num,您应该能够查看具有最高计数的那些.
Perl使用路径/文件:num作为键和一个计数器的哈希值作为一个简单的方法实现这一点,虽然有更快的方法,如果你发现运行太慢.
您还可以筛选出您可以确定的事项,不需要提前包括.
为了显示输出,您可能需要从相同的功能中过滤不同的行,但是您可能会注意到,一个函数中的不同行有不同的计数,这可能很有趣.无论如何,这可以通过使addr2line在第一步中告诉您函数名称或使用objdump -t来完成,并一次使用一个函数.
如果您看到一些模板代码或其他代码行在您的可执行文件中比您认为的更频繁地出现,那么您可以轻松找到它们并仔细观察.宏和内联函数可能会显示出与您预期不同的表现形式.
如果你不知道,objdump和addr2line是从GNU binutils包,其中包括其他几个有用的工具.