Closed llvmbot closed 8 years ago
This is a known issue with our stack realignment that happens with rbx on x64.
I ran into and tried to make us fatal error in these situations: http://reviews.llvm.org/D1317
I'm going to dupe this against llvm/llvm-project#17204 , since it's older and basically the same problem. The core issue is that aligned stack space with a moving SP requires three pointers to the stack:
Keeping ebp where it is also keeps a reference to the return address, which is good for frame pointer based unwinders.
This bug has been marked as a duplicate of bug llvm/llvm-project#17204
Extended Description
I'm trying to compile a Native Client tool (nacl_helper_bootstrap[1]) w/ Clang that make direct syscalls using inline assembly (using the linux-syscall-support[2] library).
The x86_64 version of the tool works, but the i686 version segfaults. I tracked it down to this function, which I've expanded using clang -m32 -E (also attached):
static int my_errno;
void sys_mmap2(void s, size_t l, int p, int f, int d, off_t o) { long res; struct { long a1; long a6; } s = {(long)s, (long)o}; asm volatile( "push %%ebp\n" "push %%ebx\n" "movl 4(%2),%%ebp\n" "movl 0(%2), %%ebx\n" "movl %1,%%eax\n" "int $0x80\n" "pop %%ebx\n" "pop %%ebp" : "=a"(res) : "i"(192), "0"((long)(&s)), "c"((long)(l)), "d"((long)(p)), "S"((long)(f)), "D"((long)(d)) : "esp", "memory"); do { if ((unsigned long)(__res) >= (unsigned long)(-4095)) { my_errno = -(res); res = -1; } return (void*)(__res); } while (0); }
I compile this using clang version 3.6.0 (trunk 223108) and the following commandline:
clang -m32 -mstackrealign -O0 -c test.c -o test.o
And get the following output:
00000000:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 53 push %ebx
4: 57 push %edi
5: 56 push %esi
6: 83 e4 f8 and $0xfffffff8,%esp
9: 83 ec 40 sub $0x40,%esp
c: 89 e6 mov %esp,%esi
e: 8b 45 1c mov 0x1c(%ebp),%eax
11: 8b 4d 18 mov 0x18(%ebp),%ecx
14: 8b 55 14 mov 0x14(%ebp),%edx
17: 8b 7d 10 mov 0x10(%ebp),%edi
1a: 8b 5d 0c mov 0xc(%ebp),%ebx
1d: 89 46 14 mov %eax,0x14(%esi)
20: 8b 45 08 mov 0x8(%ebp),%eax
23: 89 46 10 mov %eax,0x10(%esi)
26: 8d 46 18 lea 0x18(%esi),%eax
29: 89 46 0c mov %eax,0xc(%esi)
2c: 8b 46 10 mov 0x10(%esi),%eax
2f: 89 46 38 mov %eax,0x38(%esi)
32: 89 5e 34 mov %ebx,0x34(%esi)
35: 89 7e 30 mov %edi,0x30(%esi)
38: 89 56 2c mov %edx,0x2c(%esi)
3b: 89 4e 28 mov %ecx,0x28(%esi)
3e: 8b 4e 14 mov 0x14(%esi),%ecx
41: 89 4e 24 mov %ecx,0x24(%esi)
44: 8b 56 38 mov 0x38(%esi),%edx
47: 89 56 18 mov %edx,0x18(%esi)
4a: 8b 56 24 mov 0x24(%esi),%edx
4d: 89 56 1c mov %edx,0x1c(%esi)
50: 8b 4e 34 mov 0x34(%esi),%ecx
53: 8b 56 30 mov 0x30(%esi),%edx
56: 8b 7e 2c mov 0x2c(%esi),%edi
59: 8b 5e 28 mov 0x28(%esi),%ebx
5c: 8b 46 0c mov 0xc(%esi),%eax
5f: 89 fe mov %edi,%esi
61: 89 df mov %ebx,%edi
63: 55 push %ebp
64: 53 push %ebx
65: 8b 68 04 mov 0x4(%eax),%ebp
68: 8b 18 mov (%eax),%ebx
6a: b8 c0 00 00 00 mov $0xc0,%eax
6f: cd 80 int $0x80
71: 5b pop %ebx
72: 5d pop %ebp
73: 89 46 20 mov %eax,0x20(%esi)
76: 81 7e 20 01 f0 ff ff cmpl $0xfffff001,0x20(%esi)
7d: 0f 82 11 00 00 00 jb 94 <sys_mmap2+0x94>
83: 31 c0 xor %eax,%eax
85: 2b 46 20 sub 0x20(%esi),%eax
88: a3 00 00 00 00 mov %eax,0x0
8d: c7 46 20 ff ff ff ff movl $0xffffffff,0x20(%esi)
94: 8b 46 20 mov 0x20(%esi),%eax
97: 89 46 08 mov %eax,0x8(%esi)
9a: 8b 46 08 mov 0x8(%esi),%eax
9d: 8d 65 f4 lea -0xc(%ebp),%esp
a0: 5e pop %esi
a1: 5f pop %edi
a2: 5b pop %ebx
a3: 5d pop %ebp
a4: c3 ret
The program crashes at instruction 0x73. This is because %esi is not an address, but actually the flags for the mmap2 syscall. The code generated assumes that %esi is still set to %esp (done at instruction 0xc).
This bug does not occur if I remove -mstackrealign:
... 48: 8b 75 e4 mov -0x1c(%ebp),%esi 4b: 8b 7d e0 mov -0x20(%ebp),%edi 4e: 55 push %ebp 4f: 53 push %ebx 50: 8b 68 04 mov 0x4(%eax),%ebp 53: 8b 18 mov (%eax),%ebx 55: b8 c0 00 00 00 mov $0xc0,%eax 5a: cd 80 int $0x80 5c: 5b pop %ebx 5d: 5d pop %ebp 5e: 89 45 d8 mov %eax,-0x28(%ebp) ...
Nor does it occur when using the default clang on Ubuntu Trusty (Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final)):
... 5d: 8b 74 24 1c mov 0x1c(%esp),%esi 61: 8b 7c 24 18 mov 0x18(%esp),%edi 65: 55 push %ebp 66: 53 push %ebx 67: 8b 68 04 mov 0x4(%eax),%ebp 6a: 8b 18 mov (%eax),%ebx 6c: b8 c0 00 00 00 mov $0xc0,%eax 71: cd 80 int $0x80 73: 5b pop %ebx 74: 5d pop %ebp 75: 89 44 24 10 mov %eax,0x10(%esp) ...
This bug still occurs with optimization turned on (I tried -O2), but not in this simple example.
[1]https://code.google.com/p/chromium/codesearch#chromium/src/native_client/src/trusted/service_runtime/linux/nacl_bootstrap.c [2]https://code.google.com/p/linux-syscall-support/