Save registers via local variables instead of simple "push", so that gcc become aware of this operation and avoid stack disorder. opengl calling (in call_opengl_qemu) includes 4 steps: 1. prepare opengl parameters on stack 2. save some "input" register by push 3. load "input" register with parameters on stack via same index as step 1 4. issue "int 0x99" to trap into qemu, who will get parameter in the registers New gcc uses "%esp" rather than "%ebp" to index local variable in stack, which leads wrong index in step 3, as push decrease "%esp" automatically. Saving registers via local variables to fix it. Upstream-Status: Pending Signed-off-by: Zhai Edwin Index: git/opengl_client.c =================================================================== --- git.orig/opengl_client.c 2012-02-28 15:26:28.000000000 +0800 +++ git/opengl_client.c 2012-02-28 15:29:18.000000000 +0800 @@ -1076,23 +1076,29 @@ { #if defined(__i386__) int ret; + int bx, cx, dx, si; #ifdef WIN32 __asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (win32_sigsegv_handler)); #endif - __asm__ ("push %ebx"); - __asm__ ("push %ecx"); - __asm__ ("push %edx"); - __asm__ ("push %esi"); + /* save registers before opengl call */ + __asm__ ("mov %%ebx, %0"::"m"(bx)); + __asm__ ("mov %%ecx, %0"::"m"(cx)); + __asm__ ("mov %%edx, %0"::"m"(dx)); + __asm__ ("mov %%esi, %0"::"m"(si)); + __asm__ ("mov %0, %%eax"::"m"(func_number)); __asm__ ("mov %0, %%ebx"::"m"(pid)); __asm__ ("mov %0, %%ecx"::"m"(ret_string)); __asm__ ("mov %0, %%edx"::"m"(args)); __asm__ ("mov %0, %%esi"::"m"(args_size)); __asm__ ("int $0x99"); - __asm__ ("pop %esi"); - __asm__ ("pop %edx"); - __asm__ ("pop %ecx"); - __asm__ ("pop %ebx"); + + /* restore registers */ + __asm__ ("mov %0, %%ebx"::"m"(bx)); + __asm__ ("mov %0, %%ecx"::"m"(cx)); + __asm__ ("mov %0, %%edx"::"m"(dx)); + __asm__ ("mov %0, %%esi"::"m"(si)); + __asm__ ("mov %%eax, %0"::"m"(ret)); #ifdef WIN32 __asm__ ("movl (%%esp),%%ecx;movl %%ecx,%%fs:0;addl $8,%%esp;" : : : "%ecx"); @@ -1100,20 +1106,27 @@ return ret; #elif defined(__x86_64__) int ret; - __asm__ ("push %rbx"); - __asm__ ("push %rcx"); - __asm__ ("push %rdx"); - __asm__ ("push %rsi"); + long bx, cx, dx, si; + + /* save registers before opengl call */ + __asm__ ("mov %%rbx, %0"::"m"(bx)); + __asm__ ("mov %%rcx, %0"::"m"(cx)); + __asm__ ("mov %%rdx, %0"::"m"(dx)); + __asm__ ("mov %%rsi, %0"::"m"(si)); + __asm__ ("mov %0, %%eax"::"m"(func_number)); __asm__ ("mov %0, %%ebx"::"m"(pid)); __asm__ ("mov %0, %%rcx"::"m"(ret_string)); __asm__ ("mov %0, %%rdx"::"m"(args)); __asm__ ("mov %0, %%rsi"::"m"(args_size)); __asm__ ("int $0x99"); - __asm__ ("pop %rsi"); - __asm__ ("pop %rdx"); - __asm__ ("pop %rcx"); - __asm__ ("pop %rbx"); + + /* restore registers */ + __asm__ ("mov %0, %%rbx"::"m"(bx)); + __asm__ ("mov %0, %%rcx"::"m"(cx)); + __asm__ ("mov %0, %%rdx"::"m"(dx)); + __asm__ ("mov %0, %%rsi"::"m"(si)); + __asm__ ("mov %%eax, %0"::"m"(ret)); return ret; #else