我有一个简单的调试器(使用ptrace:http : //pastebin.com/D0um3bUi)来计算为给定输入可执行程序执行的指令数。它使用ptrace单步执行模式来计数指令。
为此,当将程序1)的可执行文件(来自gcc main.c的a.out)作为输入提供给我的测试调试器时,它将作为执行的指令打印约100k。当我使用-static选项时,它会给出10681条指令。
-static
现在在2)中,我创建一个汇编程序,并使用NASM进行编译和链接,然后当此可执行文件作为测试调试器的输入提供时,它显示8条指令作为计数,这是适当的。
由于在运行时将程序与系统库的链接起来,因此程序1)中执行的指令数量很高。使用了- static,将计数减少了1/10。我如何确保指令计数仅是程序1)中主要功能的计数,而程序2)是如何为调试器报告的?
1)
#include <stdio.h> int main() { printf("Hello, world!\n"); return 0; }
我使用gcc创建可执行文件。
2)
; 64-bit "Hello World!" in Linux NASM global _start ; global entry point export for ld section .text _start: ; sys_write(stdout, message, length) mov rax, 1 ; sys_write mov rdi, 1 ; stdout mov rsi, message ; message address mov rdx, length ; message string length syscall ; sys_exit(return_code) mov rax, 60 ; sys_exit mov rdi, 0 ; return 0 (success) syscall section .data message: db 'Hello, world!',0x0A ; message and newline length: equ $-message ; NASM definition pseudo-
我用:
nasm -f elf64 -o main.o -s main.asm ld -o main main.o
由于在运行时将程序与系统库链接在一起,因此程序1)中执行的指令数量很高?
是的,动态链接以及CRT(C运行时)启动文件。
使用-static,并将计数减少1/10。
这样就剩下了CRT启动文件,这些文件在调用之前main和之后进行处理。
main
如何确保指令计数仅是程序1)中主要功能的计数?
测量一个空的main,然后从将来的测量中减去该数字。
除非您的指令计数器更聪明,并且在可执行文件中查看其跟踪过程的符号,否则它将无法分辨出哪个代码来自何处。
以及程序2)向调试器报告的方式。
这是因为有 是 在该程序中没有其他的代码。并不是说您以某种方式帮助调试器忽略了某些指令,而是您在编写程序时没有自己未放入的任何指令。
如果你想看看 真正 发生在你运行GCC的输出gdb a.out,b _start,r,和单步执行。一旦深入了解通话树,您就很有可能了。fin因为您不想单步执行一百万条指令甚至一万条指令,所以将要使用它来完成当前功能的执行。
gdb a.out
b _start
r
fin