GCC fails to reserve space for local variables
Posted: Mon Dec 31, 2012 6:18 pm
I'm really puzzled as why GCC obviously generates incorrect code. It uses references to rbp that are below stack buttom, and thus would be overwritten by stack operations. Comparing to something that works, GCC should have included "sub rsp,xx" or called some stack-validator.
Disassembled code:
Actually code:
Disassembled code:
Code: Select all
00000180e00000b0 <main>:
180e00000b0: 55 push %rbp
180e00000b1: 48 89 e5 mov %rsp,%rbp
180e00000b4: 53 push %rbx
180e00000b5: 48 8d 05 6c 02 00 00 lea 0x26c(%rip),%rax # ffffffffe0000328 <_end+0xfffffe7ebffff970>
180e00000bc: 48 89 45 e8 mov %rax,-0x18(%rbp)
180e00000c0: c6 45 e7 00 movb $0x0,-0x19(%rbp)
180e00000c4: b8 08 00 00 00 mov $0x8,%eax
180e00000c9: 48 83 c0 01 add $0x1,%rax
180e00000cd: 48 89 45 d8 mov %rax,-0x28(%rbp)
180e00000d1: 48 8b 45 e8 mov -0x18(%rbp),%rax
180e00000d5: 0f b6 4d e7 movzbl -0x19(%rbp),%ecx
180e00000d9: 4c 8b 55 d8 mov -0x28(%rbp),%r10
180e00000dd: 48 89 c7 mov %rax,%rdi
180e00000e0: 51 push %rcx
180e00000e1: 57 push %rdi
180e00000e2: 41 54 push %r12
180e00000e4: 41 57 push %r15
180e00000e6: 4d 89 d4 mov %r10,%r12
180e00000e9: 49 c7 c7 7b 00 00 00 mov $0x7b,%r15
180e00000f0: 0f 05 syscall
180e00000f2: 72 06 jb 180e00000fa <main+0x4a>
180e00000f4: 48 0f b7 c3 movzwq %bx,%rax
180e00000f8: eb 03 jmp 180e00000fd <main+0x4d>
180e00000fa: 48 31 c0 xor %rax,%rax
180e00000fd: 41 5f pop %r15
180e00000ff: 41 5c pop %r12
180e0000101: 5f pop %rdi
180e0000102: 59 pop %rcx
180e0000103: 48 89 45 d0 mov %rax,-0x30(%rbp)
180e0000107: 48 8b 45 d0 mov -0x30(%rbp),%rax
180e000010b: 89 45 f4 mov %eax,-0xc(%rbp)
180e000010e: 83 7d f4 00 cmpl $0x0,-0xc(%rbp)
180e0000112: 74 69 je 180e000017d <main+0xcd>
180e0000114: 8b 45 f4 mov -0xc(%rbp),%eax
180e0000117: 89 45 cc mov %eax,-0x34(%rbp)
180e000011a: 48 8b 05 e7 fe ff 3f mov 0x3ffffee7(%rip),%rax # 20000008 <usergate_entries+0x1ffffeb4>
180e0000121: 48 89 45 c0 mov %rax,-0x40(%rbp)
180e0000125: c7 45 bc f4 01 00 00 movl $0x1f4,-0x44(%rbp)
180e000012c: 8b 45 cc mov -0x34(%rbp),%eax
180e000012f: 8b 4d bc mov -0x44(%rbp),%ecx
180e0000132: 48 8b 7d c0 mov -0x40(%rbp),%rdi
180e0000136: 89 c3 mov %eax,%ebx
180e0000138: 51 push %rcx
180e0000139: 57 push %rdi
180e000013a: 41 54 push %r12
180e000013c: 41 57 push %r15
180e000013e: 49 89 cc mov %rcx,%r12
180e0000141: 49 89 c8 mov %rcx,%r8
180e0000144: 49 c7 c7 86 00 00 00 mov $0x86,%r15
180e000014b: 0f 05 syscall
180e000014d: 73 03 jae 180e0000152 <main+0xa2>
180e000014f: 48 31 c0 xor %rax,%rax
180e0000152: 41 5f pop %r15
180e0000154: 41 5c pop %r12
180e0000156: 5f pop %rdi
180e0000157: 59 pop %rcx
180e0000158: 48 89 45 b0 mov %rax,-0x50(%rbp)
180e000015c: 48 8b 45 b0 mov -0x50(%rbp),%rax
180e0000160: 89 45 f0 mov %eax,-0x10(%rbp)
180e0000163: 8b 45 f4 mov -0xc(%rbp),%eax
180e0000166: 89 45 ac mov %eax,-0x54(%rbp)
180e0000169: 44 8b 55 ac mov -0x54(%rbp),%r10d
180e000016d: 44 89 d3 mov %r10d,%ebx
180e0000170: 41 57 push %r15
180e0000172: 49 c7 c7 7d 00 00 00 mov $0x7d,%r15
180e0000179: 0f 05 syscall
180e000017b: 41 5f pop %r15
180e000017d: b8 00 00 00 00 mov $0x0,%eax
180e0000182: 5b pop %rbx
180e0000183: 5d pop %rbp
180e0000184: c3 retq
Code: Select all
#include "string.h"
#undef RDOSAPI
#define RDOSAPI static inline volatile __attribute__ ((always_inline))
#define UserGateRetEax(nr, ret) \
asm ( \
"pushq %%r15\n\t" \
"movq %1, %%r15\n\t" \
"syscall\n\t" \
"popq %%r15\n\t" \
: "=a" (ret) : "i" (nr) : "rbx", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r11"\
);
#define UserGateEdiEcxRetEbx(nr, rdi, rcx, len, ret) \
asm ( \
"pushq %%rcx\n\t" \
"pushq %%rdi\n\t" \
"pushq %%r12\n\t" \
"pushq %%r15\n\t" \
"movq %4,%%r12\n\t" \
"movq %1, %%r15\n\t" \
"syscall\n\t" \
"jc 1f\n\t" \
"movzx %%bx,%%rax\n\t" \
"jmp 2f\n\t" \
"1: \n\t" \
"xorq %%rax,%%rax\n\t" \
"2: \n\t" \
"popq %%r15\n\t" \
"popq %%r12\n\t" \
"popq %%rdi\n\t" \
"popq %%rcx\n\t" \
: "=a" (ret) : "i" (nr), "D" (rdi), "c" (rcx), "r" (len) : "rbx", "rdx", "rsi", "r8", "r9", "r11", "cc" \
);
#define UserGateEbxEcxEdiRetEax(nr, rbx, rcx, rdi, ret) \
asm ( \
"pushq %%rcx\n\t" \
"pushq %%rdi\n\t" \
"pushq %%r12\n\t" \
"pushq %%r15\n\t" \
"movq %%rcx,%%r12\n\t" \
"movq %%rcx,%%r8\n\t" \
"movq %1, %%r15\n\t" \
"syscall\n\t" \
"jnc 1f\n\t" \
"xorq %%rax,%%rax\n\t" \
"1: \n\t" \
"popq %%r15\n\t" \
"popq %%r12\n\t" \
"popq %%rdi\n\t" \
"popq %%rcx\n\t" \
: "=a" (ret) : "i" (nr), "b" (rbx), "c" (rcx), "D" (rdi) : "rdx", "rsi", "r8", "r9", "r11", "cc" \
);
#define UserGateEbx(nr, rbx) \
asm ( \
"pushq %%r15\n\t" \
"movq %0, %%r15\n\t" \
"syscall\n\t" \
"popq %%r15\n\t" \
: : "i" (nr), "b" (rbx) : "rax", "rcx", "rdx", "rsi", "rdi", "r8", "r9", "r11" \
);
RDOSAPI long RdosOpenFile(const char *FileName, char Access)
{
long res;
long size = strlen(FileName) + 1;
UserGateEdiEcxRetEbx(usergate_open_file, FileName, Access, size, res);
return res;
}
RDOSAPI long RdosReadFile(int Handle, void *Buf, int Size)
{
long res;
UserGateEbxEcxEdiRetEax(usergate_read_file, Handle, Size, Buf, res);
return res;
}
RDOSAPI RdosCloseFile(int Handle)
{
UserGateEbx(usergate_close_file, Handle);
}
char buf[500];
int main()
{
int handle;
int count;
handle = RdosOpenFile("test.exe", 0);
if (handle)
{
count = RdosReadFile(handle, buf, 500);
RdosCloseFile(handle);
}
return 0;
}