Why no corresponding subroutine call in machine code dump when calling strcpy()?
我正在研究乔恩·埃里克森(Jon Erickson)的《黑客:剥削的艺术》一书。
在本书的一部分中,他给出了C代码,然后使用gdb遍历了相应的程序集,解释了指令和内存活动。
我正在Mac OS X上工作,所以事情与他在书中介绍的有所不同(他正在使用Linux)。
无论如何,我有这个C程序:
1 2 3 4 5 6 7 8 9 10 11 |
这是对应的otool对象转储(我刚刚包含main):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | _main: 0000000100000ea0 pushq %rbp 0000000100000ea1 movq %rsp,%rbp 0000000100000ea4 subq $0x30,%rsp 0000000100000ea8 movq 0x00000189(%rip),%rax 0000000100000eaf movq (%rax),%rax 0000000100000eb2 movq %rax,0xf8(%rbp) 0000000100000eb6 leaq 0xd4(%rbp),%rax 0000000100000eba movq %rax,%rcx 0000000100000ebd movq $0x77202c6f6c6c6548,%rdx 0000000100000ec7 movq %rdx,(%rcx) 0000000100000eca movb $0x00,0x0e(%rcx) 0000000100000ece movw $0x0a21,0x0c(%rcx) 0000000100000ed4 movl $0x646c726f,0x08(%rcx) 0000000100000edb movq %rcx,0xe8(%rbp) 0000000100000edf xorb %cl,%cl 0000000100000ee1 movq %rax,%rdi 0000000100000ee4 movb %cl,%al 0000000100000ee6 callq 0x100000f1e ; symbol stub for: _printf 0000000100000eeb movl 0xf4(%rbp),%eax 0000000100000eee movq 0x00000143(%rip),%rcx 0000000100000ef5 movq (%rcx),%rcx 0000000100000ef8 movq 0xf8(%rbp),%rdx 0000000100000efc cmpq %rdx,%rcx 0000000100000eff movl %eax,0xd0(%rbp) 0000000100000f02 jne 0x100000f0d 0000000100000f04 movl 0xd0(%rbp),%eax 0000000100000f07 addq $0x30,%rsp 0000000100000f0b popq %rbp 0000000100000f0c ret 0000000100000f0d callq 0x100000f12 ; symbol stub for: ___stack_chk_fail |
好。您会注意到对printf()的子例程调用:
1 | 0000000100000ee6 callq 0x100000f1e ; symbol stub for: _printf |
但是对strcpy()的调用在哪里?
还有另外两个异常。首先,如果我在gdp中为strcpy()设置了一个断点:
1 | break strcpy |
该程序将在不停止的情况下进行压缩。似乎strcpy()实际上没有被调用。
其次,当我编译代码时:
1 | gcc -g -o char_array2 char_array2.c |
我收到警告:
1 2 3 | char_array2.c: In function ‘main’: char_array2.c:9: warning: format not a string literal and no format arguments char_array2.c:9: warning: format not a string literal and no format arguments |
我不确定这是否与缺少的子例程调用有关,但是我认为无论如何我都会将其包含为数据点。
在我看来,似乎编译器已决定不需要strcpy()并优化了代码以使其不使用它。该程序按预期运行,显示" Hello,world!"。到标准输出,但是缺少对strcpy()的调用让我想知道到底发生了什么。
在书中Erickson的示例中,有一个对strcpy()的调用,因此也许他的编译器和我的编译器的工作方式有所不同。我在使用LLVM:
i686-apple-darwin11-llvm-gcc-4.2
任何想法将不胜感激!
在此先感谢您,我希望您觉得这一点很有趣。
汤姆
就在这里:
1 2 3 4 5 | 0000000100000ebd movq $0x77202c6f6c6c6548,%rdx 0000000100000ec7 movq %rdx,(%rcx) 0000000100000eca movb $0x00,0x0e(%rcx) 0000000100000ece movw $0x0a21,0x0c(%rcx) 0000000100000ed4 movl $0x646c726f,0x08(%rcx) |