This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]