https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80759

--- Comment #52 from ro at CeBiTec dot Uni-Bielefeld.DE <ro at CeBiTec dot 
Uni-Bielefeld.DE> ---
> The attached patch (on top of v6) *might* solve the problem on Darwin, but I
> don't understand exactly how GOTPCREL works, other than it's using a global
> offset table for linking.  Hopefully, the linker can translate this directly
> into a constant rip-rel offset.  What I'm doing here is that instead of 
> feeding
> addresses to the asm template, I'm giving in the offsets and schlepping
> together an address operand from that, e.g.:
>
>         lea %p0 + test_data@GOTPCREL(%%rip), %%rax
>
> Now if this fix *does* work, then I might need to investigate if this is a
> performance problem for Darwin -- why use an extra instruction to copy the
> address to a register before modifying it?  If it doesn't work then it's
> probably because it really *needs* two instructions.  I'm curious what the
> disassembly of the linked program looks like.

Unfortunately, the patch doesn't work, apart from the

+# define PCREL "@GETPCREL"

-> @GOTPCREL typo ;-)

At -O0 -g3, it SEGVs at

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
1: x/i $pc
=> 0x0: <error: Cannot access memory at address 0x0>
(gdb) where
#0  0x0000000000000000 in ?? ()
#1  0x0000000100031c58 in do_test_body0 ()
    at
/vol/gcc/src/hg/trunk/solaris/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms-sysv.c:178
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

where %rip is 0x0.  This happens because most of the addresses are off
by 0x680 bytes.  Here's the disassembly:

(gdb) x/12i 0x0000000100031c58-42
   0x100031c2e <do_test_body0>: push   %rbp
   0x100031c2f <do_test_body0+1>:       mov    %rsp,%rbp
   0x100031c32 <do_test_body0>: lea    0x1b407(%rip),%rax        # 0x10004d040
   0x100031c39 <do_test_body0+7>:       callq  0x10003247c <regs_to_mem>
   0x100031c3e <do_test_body0+12>:
    lea    0x1b4db(%rip),%rax        # 0x10004d120 <do_tests_0004_noinfo>
   0x100031c45 <do_test_body0+19>:      callq  0x1000324ea <mem_to_regs>
   0x100031c4a <do_test_body0+24>:      pop    %rax
   0x100031c4b <do_test_body0+25>:
    mov    %rax,0x1b696(%rip)        # 0x10004d2e8 <buffer.5456+104>
   0x100031c52 <do_test_body0+32>:
    callq  *0x1b688(%rip)        # 0x10004d2e0 <buffer.5456+96>
   0x100031c58 <do_test_body0+38>:
    mov    0x1bd09(%rip),%rcx        # 0x10004d968 <test_data+680>

Here are the addresses that are supposed to be used:

%p0

(gdb) p/x &test_data.regdata[0]
$11 = 0x10004d6c0

%p1

(gdb) p/x &test_data.regdata[1]
$12 = 0x10004d7a0

%p4

(gdb) p/x &test_data.retaddr
$13 = 0x10004d968

%p3

(gdb) p/x &test_data.fn
$14 = 0x10004d960

Only the second use of %p4 is right.

        Rainer

Reply via email to