This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch x86/darwin] fix PR51784 'PIC register not correctly preserved...'
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: Iain Sandoe <iain at codesourcery dot com>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Mike Stump <mikestump at comcast dot net>, Richard Henderson <rth at redhat dot com>
- Date: Thu, 18 Jul 2013 09:26:30 +0200
- Subject: Re: [Patch x86/darwin] fix PR51784 'PIC register not correctly preserved...'
Hello!
> The PR is logged against Darwin, and (as Jakub points out in the PR
> thread) indeed Darwin is missing a nonlocal_goto_receiver to restore
> the PIC reg in code that uses it (most of the patch).
>
> However, there is a second issue, and (if I've understood things
> correctly) this affects GOT targets too - thus there is a single
> non-darwin-specific hunk for which I need approval for X86 as a whole.
>
> consider (x86 -fPIC -m32)
>
> ==
>
> int g42 = 42;
>
> int foo (void) <=== doesn't use EBX, so doesn't save it.
> {
> __label__ x;
> int z;
> int bar (int *zz) <== does use EBX, and saves it
> {
> *zz = g42;
> goto x; <== however, EBX is not restored here.
> }
>
> bar(&z);
>
> x:
> return z;
> }
>
> ==
>
> ... this all works OK when the caller of foo and foo are in one object
> (and thus share the same GOT)
>
> .. however, suppose we build the code above as a shared lib and call
> it from a pie executable (or another so).
>
> Now, when the caller (with a different GOT value from the lib) calls
> foo() - EBX gets trashed (probably *boom*).
>
> The solution proposed here (for this aspect) is that, if a function
> contains a nonlocal label, then the PICbase register should be
> preserved. This is the only non-darwin-specific hunk in the patch.
I don't think this is the correct solution. Function bar() should
restore %ebx before jumping to the label.
The problem can be seen if you change "return z" to "return z + g42"
at the end of your testcase. The test will be compiled to:
bar.1372:
pushl %ebp
movl %esp, %ebp
pushl %ebx
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
movl g42@GOT(%ebx), %edx
movl (%edx), %edx
movl %edx, (%eax)
leal .L2@GOTOFF(%ebx), %eax
movl (%ecx), %ebp
movl 4(%ecx), %esp
jmp *%eax
and
foo:
pushl %ebp
pushl %edi
pushl %esi
pushl %ebx
call __x86.get_pc_thunk.bx
addl $_GLOBAL_OFFSET_TABLE_, %ebx
subl $16, %esp
leal 16(%esp), %eax
movl %eax, 4(%esp)
leal 4(%esp), %ecx
movl %esp, %eax
movl %esp, 8(%esp)
call bar.1372
.L2:
movl g42@GOT(%ebx), %edx
movl (%esp), %eax
addl (%edx), %eax
addl $16, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
ret
Under assumpiton that foo and bar doesn't share the same GOT, you will
see that g42 after the label is accessed with "clobbered" %ebx.
Uros.