Opened 4 years ago

Closed 3 years ago

#8024 closed bug (fixed)

Dynamic linking not working on PowerPC Linux.

Reported by: erikd Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.7
Keywords: Cc: slyfox@…, ptrommler@…, pho@…
Operating System: Linux Architecture: powerpc
Type of failure: Building GHC failed Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): D560
Wiki Page:

Description (last modified by erikd)

With dynamic linking enabled, the first binary compiled by the stage1 compiler (dll-split) crashes with an illegal instruction exception.

(gdb) bt
#0  0x0f3f2e24 in cr_str () from /home/erikd/Git/ghc-upstream/rts/dist/build/libHSrts-ghc7.7.20130630.so
#1  0x0f3de490 in stg_catchzh () from /home/erikd/Git/ghc-upstream/rts/dist/build/libHSrts-ghc7.7.20130630.so
#2  0x0f3cc01c in scheduleWaitThread () from /home/erikd/Git/ghc-upstream/rts/dist/build/libHSrts-ghc7.7.20130630.so
#3  0x0f3c63dc in rts_evalLazyIO () from /home/erikd/Git/ghc-upstream/rts/dist/build/libHSrts-ghc7.7.20130630.so
#4  0x0f3c8300 in hs_main () from /home/erikd/Git/ghc-upstream/rts/dist/build/libHSrts-ghc7.7.20130630.so
#5  0x10006ae4 in main ()

Disassmbling the function gives:

Dump of assembler code for function cr_str:
   0x0f3f2dec:  rlwimi  r1,r2,10,0,16
   0x0f3f2df0:  xoris   r2,r27,27237
   0x0f3f2df4:  ori     r20,r27,8293
   0x0f3f2df8:  xoris   r20,r19,25970
   0x0f3f2dfc:  oris    r4,r11,8448
   0x0f3f2e00:  .long 0xfffeae2c
   0x0f3f2e04:  .long 0xfffeae2c
   0x0f3f2e08:  .long 0xfffeae2c
   0x0f3f2e0c:  .long 0xfffeae2c
   0x0f3f2e10:  .long 0xfffeae2c
   0x0f3f2e14:  .long 0xfffeae2c
   0x0f3f2e18:  .long 0xfffeae2c
   0x0f3f2e1c:  .long 0xfffeae2c
   0x0f3f2e20:  .long 0xfffeae2c
=> 0x0f3f2e24:  .long 0xfffeae20
   0x0f3f2e28:  .long 0xfffeae20
   0x0f3f2e2c:  .long 0xfffeae20
   0x0f3f2e30:  .long 0xfffeae20

However function stg_catchzh() in rts/Exception.cmm does not call cr_str().

If I disable dynamic lbraries by adding powerpc-unknow-linux to NoSharedLibsPlatformList in mk/config.mk.in then the compile builds.

Change History (12)

comment:1 Changed 4 years ago by erikd

Description: modified (diff)
Summary: Illegal instruction in cr_strDynamic linking not working on PowerPC Linux.

comment:2 Changed 4 years ago by erikd

difficulty: Unknown

Mentioned this to Duncan and he suggested this may might be fixed by changing -fpic to -fPIC.

From: http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

"""Use -fPIC or -fpic to generate code. Whether to use -fPIC or -fpic to generate code is target-dependent. The -fPIC choice always works, but may produce larger code than -fpic (mnenomic to remember this is that PIC is in a larger case, so it may produce larger amounts of code). Using -fpic option usually generates smaller and faster code, but will have platform-dependent limitations, such as the number of globally visible symbols or the size of the code. The linker will tell you whether it fits when you create the shared library. When in doubt, I choose -fPIC, because it always works."""

Last edited 4 years ago by erikd (previous) (diff)

comment:3 Changed 3 years ago by slyfox

Cc: slyfox@… added

comment:4 Changed 3 years ago by slyfox

I see odd things happening on sparc and ia64 as well.

On sparc it looks like a wrongly resolved current module (seems to be PIC mis-handling).

comment:5 Changed 3 years ago by erikd

In mk/config.mk.in tried changing

PIC = pic

to

PIC = PIC

ran the whole process from perl boot onwards and that didn't help. This was on ppc64.

Last edited 3 years ago by erikd (previous) (diff)

comment:6 Changed 3 years ago by trommler

Cc: ptrommler@… added

comment:7 Changed 3 years ago by PHO

Cc: pho@… added

comment:8 Changed 3 years ago by slyfox

The bug looks very much like SPARC's bug #8857 where compiler emitted one level more indirection, but assembler didn't generate proper relocations for it:

https://phabricator.haskell.org/D177

I wonder if it cures ppc32 for you.

comment:9 Changed 3 years ago by thomie

Status: newinfoneeded

comment:10 Changed 3 years ago by slyfox

Differential Rev(s): D560
Status: infoneededpatch

The problem happened to be in code emitting prologs for basic block entries (also got fixed by https://phabricator.haskell.org/D560).

Typically haskell function has single entry point (-fPIC -ddump-asm-native):

M.f_info:
_ci4:
; PIC prolog
        bcl     20,31,1f
1:      mflr    %vI_nic
        lwz     %vI_nij, _nii-(1b)(%vI_nic)
        add     %vI_nic, %vI_nic, %vI_nij
... <HERE GOES ACTUAL CODE> ...
; offset to LCTOC from nearest '1:'
.text
.align 2
_nii:
        .long   .LCTOC1-(1b)+0

But sometimes runtime needs to return back into a middle of haskell function (try/catch primitives?) and prolog gets emitted at each such point using the same LCTOC offset:

M.f_info:
_ci4:
; PIC prolog
        bcl     20,31,1f
1:      mflr    %vI_nic ; REF 1
        lwz     %vI_nij, _nii-(1b)(%vI_nic)
        add     %vI_nic, %vI_nic, %vI_nij
... <HERE GOES ACTUAL CODE> ...
returns_here_later:
; PIC prolog
        bcl     20,31,1f
1:      mflr    %vI_nic ; REF 2
        lwz     %vI_nij, _nii-(1b)(%vI_nic)
        add     %vI_nic, %vI_nic, %vI_nij
...
; offset to LCTOC from nearest '1:'
.text
.align 2
_nii:
        .long   .LCTOC1-(1b)+0

Here '_nii' contains offset to nearest '1:' label, not first one (as intended). It leads to miscomputation of LCTOC1 in function entry (around first '1:' which usually manifests in call to random location.

It is fixed by using simpler prolog (similar to what modern gcc emits nowadays):

        bcl     20,31,1f
1:      mflr    %vI_ny4
        addis   %vI_ny4, %vI_ny4, .LCTOC1-(1b)@ha
        addi    %vI_ny4, %vI_ny4, .LCTOC1-(1b)@l
        mr      30, %vI_ny4

And it is safe to duplicate.

comment:11 Changed 3 years ago by Sergei Trofimovich <siarheit@…>

In fa31e8f4a0f853848d96549a429083941877bf8d/ghc:

powerpc: fix and enable shared libraries by default on linux

Summary:
And fix things all the way down to it. Namely:
    - remove 'r30' from free registers, it's an .LCTOC1 register
      for gcc. generated .plt stubs expect it to be initialised.
    - fix PicBase computation, which originally forgot to use 'tmp'
      reg in 'initializePicBase_ppc.fetchPC'
    - mark 'ForeighTarget's as implicitly using 'PicBase' register
      (see comment for details)
    - add 64-bit MO_Sub and test on alloclimit3/4 regtests
    - fix dynamic label offsets to match with .LCTOC1 offset

Signed-off-by: Sergei Trofimovich <siarheit@google.com>

Test Plan: validate passes equal amount of vanilla/dyn tests

Reviewers: simonmar, erikd, austin

Reviewed By: erikd, austin

Subscribers: carter, thomie

Differential Revision: https://phabricator.haskell.org/D560

GHC Trac Issues: #8024, #9831

comment:12 Changed 3 years ago by slyfox

Resolution: fixed
Status: patchclosed
Note: See TracTickets for help on using tickets.