I have generated SIGSEGV in my code intentionally to learn to debug it under various utilities like catchsegv, gdb, valgrind & pmap. I intentionally used memcpy() on mmap'ed file which is having flag of PROT_READ set by mprotect(). Now when I am debugging it under gdb I am not able to make any conclusion from assembly output. I am quite a newbie to assembly.
Details -
Memory Stuff :
(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)
As you can see that SEGFAULT happened at instruction 0x2aaaaad55541, which is also indicated in 64bit Instruction Pointer register RIP.
Registers :
(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
Process mappings :
Below is the output of "info proc mappings" command inside gdb.
[excerpt]
0x2aaaaaacf000 0x2aaaaaad0000 0x1000 0 /tmp/dst_file
[/excerpt]
/tmp/dst_file is mapped into memory using mmap() and made READ ONLY using PROT_READ before memcpy() call & memcpy() tries to write content on it and thus SEGFAULT appears.
Memcpy() call used :
memcpy (mmap_start + myfilestat1.st_size, str1, strlen(str1))
mmap_start is the starting address and myfilestat1.st_size is new truncated file size. str1 is the string to append to the file.
Here is a little flow of my source code -
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.
Question -
Now what I am not able to understand is
0x2aaaaad55541 <memcpy+17>: mov %cl,(%rdi)
What does this instruction exactly do? RDI register contains end address of file mapped to start writing, why does the value at RDI address is being written at CX register?
Any help is appreciated. Let me know if more info is needed.
RDI
is the argument passed to memcpy
as destination. In your case that seems to be offset 2 in the mapped area. You didn't provide what memcpy
call you used.
CL
holds the first byte of the source memory region, it has been loaded by the instruction directly preceding the fault: movzbl (%rsi),%ecx
. I assume you know that CL
is the low 8 bits of ECX
(which in turn is the low 32 bits of RCX
).