I have the following code:
void cp(void *a, const void *b, int n) { for (int i = 0; i < n; ++i) { ((char *) a)[i] = ((const char *) b)[i]; }}void _start(void) { char buf[20]; const char m[] = "123456789012345"; cp(buf, m, 15); register int rax __asm__ ("rax") = 60; // exit register int rdi __asm__ ("rdi") = 0; // status __asm__ volatile ("syscall" :: "r" (rax), "r" (rdi) : "cc", "rcx", "r11" ); __builtin_unreachable();}
If I compile it with gcc -nostdlib -O1 "./a.c" -o "./a"
, I get a functioning program, but if I compile it with -O2
, I get a program that generates a segmentation fault.
This is the generated code with -O1
:
0000000000001000 <cp>: 1000: b8 00 00 00 00 mov $0x0,%eax 1005: 0f b6 14 06 movzbl (%rsi,%rax,1),%edx 1009: 88 14 07 mov %dl,(%rdi,%rax,1) 100c: 48 83 c0 01 add $0x1,%rax 1010: 48 83 f8 0f cmp $0xf,%rax 1014: 75 ef jne 1005 <cp+0x5> 1016: c3 retq 0000000000001017 <_start>: 1017: 48 83 ec 30 sub $0x30,%rsp 101b: 48 b8 31 32 33 34 35 movabs $0x3837363534333231,%rax 1022: 36 37 38 1025: 48 ba 39 30 31 32 33 movabs $0x35343332313039,%rdx 102c: 34 35 00 102f: 48 89 04 24 mov %rax,(%rsp) 1033: 48 89 54 24 08 mov %rdx,0x8(%rsp) 1038: 48 89 e6 mov %rsp,%rsi 103b: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi 1040: ba 0f 00 00 00 mov $0xf,%edx 1045: e8 b6 ff ff ff callq 1000 <cp> 104a: b8 3c 00 00 00 mov $0x3c,%eax 104f: bf 00 00 00 00 mov $0x0,%edi 1054: 0f 05 syscall
And this is the generated code with -O2
:
0000000000001000 <cp>: 1000: 31 c0 xor %eax,%eax 1002: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 1008: 0f b6 14 06 movzbl (%rsi,%rax,1),%edx 100c: 88 14 07 mov %dl,(%rdi,%rax,1) 100f: 48 83 c0 01 add $0x1,%rax 1013: 48 83 f8 0f cmp $0xf,%rax 1017: 75 ef jne 1008 <cp+0x8> 1019: c3 retq 101a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)0000000000001020 <_start>: 1020: 48 8d 44 24 d8 lea -0x28(%rsp),%rax 1025: 48 8d 54 24 c9 lea -0x37(%rsp),%rdx 102a: b9 31 00 00 00 mov $0x31,%ecx 102f: 66 0f 6f 05 c9 0f 00 movdqa 0xfc9(%rip),%xmm0 # 2000 <_start+0xfe0> 1036: 00 1037: 48 8d 70 0f lea 0xf(%rax),%rsi 103b: 0f 29 44 24 c8 movaps %xmm0,-0x38(%rsp) 1040: eb 0d jmp 104f <_start+0x2f> 1042: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 1048: 0f b6 0a movzbl (%rdx),%ecx 104b: 48 83 c2 01 add $0x1,%rdx 104f: 88 08 mov %cl,(%rax) 1051: 48 83 c0 01 add $0x1,%rax 1055: 48 39 f0 cmp %rsi,%rax 1058: 75 ee jne 1048 <_start+0x28> 105a: b8 3c 00 00 00 mov $0x3c,%eax 105f: 31 ff xor %edi,%edi 1061: 0f 05 syscall
The crash happens at 103b
, instruction movaps %xmm0,-0x38(%rsp)
.
I noticed that if m
contains less than 15 characters, then the generated code is different and the crash does not happen.
What am I doing wrong?