我故意在我的代码中生成了 SIGSEGV,以学习在各种实用程序下调试它,例如catchsegv、gdb、valgrind和pmap。我故意在mmap'ed文件上使用了memcpy(),该文件具有由mprotect()设置的PROT_READ标志。现在,当我在 gdb 下调试它时,我无法从汇编输出中得出任何结论。我是组装的新手。
细节 -
记忆的东西:
(gdb) x/35i 0x00002aaaaad55500
0x2aaaaad55500 <memccpy+32>: jne 0x2aaaaad554e8 <memccpy+8>
0x2aaaaad55502 <memccpy+34>: mov %rdi,%rax
0x2aaaaad55505 <memccpy+37>: retq
0x2aaaaad55506 <memccpy+38>: nopw %cs:0x0(%rax,%rax,1)
0x2aaaaad55510 <memccpy+48>: xor %eax,%eax
0x2aaaaad55512 <memccpy+50>: retq
0x2aaaaad55513: nop
0x2aaaaad55514: nop
0x2aaaaad55515: nop
0x2aaaaad55516: nop
0x2aaaaad55517: nop
0x2aaaaad55518: nop
0x2aaaaad55519: nop
0x2aaaaad5551a: nop
0x2aaaaad5551b: nop
0x2aaaaad5551c: nop
0x2aaaaad5551d: nop
0x2aaaaad5551e: nop
0x2aaaaad5551f: nop
0x2aaaaad55520 <__memcpy_chk>: cmp %rdx,%rcx
0x2aaaaad55523 <__memcpy_chk+3>: jb 0x2aaaaadcb590 <__chk_fail>
0x2aaaaad55529: nopl 0x0(%rax)
0x2aaaaad55530 <memcpy>: cmp $0x20,%rdx
0x2aaaaad55534 <memcpy+4>: mov %rdi,%rax
0x2aaaaad55537 <memcpy+7>: jae 0x2aaaaad555b0 <memcpy+128>
0x2aaaaad55539 <memcpy+9>: test $0x1,%dl
0x2aaaaad5553c <memcpy+12>: je 0x2aaaaad55549 <memcpy+25>
0x2aaaaad5553e <memcpy+14>: movzbl (%rsi),%ecx
=> 0x2aaaaad55541 <memcpy+17>: mov %cl,(%rdi)
0x2aaaaad55543 <memcpy+19>: inc %rsi
0x2aaaaad55546 <memcpy+22>: inc %rdi
0x2aaaaad55549 <memcpy+25>: test $0x2,%dl
0x2aaaaad5554c <memcpy+28>: je 0x2aaaaad55560 <memcpy+48>
0x2aaaaad5554e <memcpy+30>: movzwl (%rsi),%ecx
0x2aaaaad55551 <memcpy+33>: mov %cx,(%rdi)
如您所见,SEGFAULT 发生在指令 0x2aaaaad55541 处,这也在 64 位指令指针寄存器 RIP 中指示。
寄存器:
(gdb) info registers
rax 0x2aaaaaacf002 46912496267266
rbx 0x40146a 4199530
rcx 0x69 105
rdx 0x1 1
rsi 0x40146a 4199530
rdi 0x2aaaaaacf002 46912496267266
rbp 0x7 0x7
rsp 0x7fffffffe468 0x7fffffffe468
r8 0x40146a 4199530
r9 0x53202c444145525f 5989836176067220063
r10 0x7fffffffe1f0 140737488347632
r11 0x2aaaaad55530 46912498914608
r12 0x2aaaab05eac8 46912502098632
r13 0x7fffffffe5a0 140737488348576
r14 0x7fffffffe590 140737488348560
r15 0x2aaaaaacf000 46912496267264
rip 0x2aaaaad55541 0x2aaaaad55541 <memcpy+17>
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
过程映射:
下面是 gdb 中“info proc mappings”命令的输出。
[excerpt]
0x2aaaaaacf000 0x2aaaaaad0000 0x1000 0 /tmp/dst_file
[/excerpt]
/tmp/dst_file 使用 mmap() 映射到内存中,并在 memcpy() 调用和 memcpy() 尝试在其上写入内容并因此出现 SEGFAULT 之前使用 PROT_READ 将其设为只读。
使用的 Memcpy() 调用:
memcpy (mmap_start + myfilestat1.st_size, str1, strlen(str1))
mmap_start 是起始地址,myfilestat1.st_size 是新的截断文件大小。str1 是要附加到文件的字符串。
这是我的源代码的一点流程-
1. Fstat original size of file
2. Set Offset of file to grow depending upon strlen() of string to append
3. Ftruncate() to grow file size
4. Fstat new file size.
5. Mmap the newly truncated file
6. If segmentation fault need to be generated, call mprotect() to convert to PROT_READ.
7. Memcpy() with Orignal fstat size to append contents to text file.
问题 -
现在我无法理解的是
0x2aaaaad55541 <memcpy+17>: mov %cl,(%rdi)
这条指令到底是做什么的?RDI寄存器包含映射到开始写入的文件的结束地址,为什么RDI地址的值被写入CX寄存器?
任何帮助表示赞赏。如果需要更多信息,请告诉我。