diff options
author | Sergei Trofimovich <slyfox@gentoo.org> | 2014-08-27 22:19:52 +0300 |
---|---|---|
committer | Sergei Trofimovich <slyfox@gentoo.org> | 2014-08-27 22:19:52 +0300 |
commit | a93ab43ab5f40cadbedea2f6342b93c245e91434 (patch) | |
tree | 66a5987e2a4b33a145d74c662666e5a6c9ed91eb /compiler/main/DriverPipeline.hs | |
parent | 43f1b2ecd1960fa7377cf55a2b97c66059a701ef (diff) | |
download | haskell-a93ab43ab5f40cadbedea2f6342b93c245e91434.tar.gz |
driver: pass '-fPIC' option to assembler as well
Summary:
Before the patch '-fPIC' was passed only to C compiler,
but not to assembler itself.
It led to runtime crash in GHC_DYNAMIC_PROGRAMS=YES mode
on sparc32.
Technical details are in 'Note [-fPIC for assembler]'.
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Test Plan: validate on sparc
Reviewers: simonmar, austin, kgardas
Reviewed By: austin
Subscribers: simonmar, ezyang, carter
Differential Revision: https://phabricator.haskell.org/D177
Diffstat (limited to 'compiler/main/DriverPipeline.hs')
-rw-r--r-- | compiler/main/DriverPipeline.hs | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs index 183f435296..5a18e6e7bf 100644 --- a/compiler/main/DriverPipeline.hs +++ b/compiler/main/DriverPipeline.hs @@ -1199,6 +1199,7 @@ runPhase (RealPhase (As with_cpp)) input_fn dflags as_prog <- whichAsProg let cmdline_include_paths = includePaths dflags + let pic_c_flags = picCCOpts dflags next_phase <- maybeMergeStub output_fn <- phaseOutputFilename next_phase @@ -1212,6 +1213,9 @@ runPhase (RealPhase (As with_cpp)) input_fn dflags = liftIO $ as_prog dflags ([ SysTools.Option ("-I" ++ p) | p <- cmdline_include_paths ] + -- See Note [-fPIC for assembler] + ++ map SysTools.Option pic_c_flags + -- We only support SparcV9 and better because V8 lacks an atomic CAS -- instruction so we have to make sure that the assembler accepts the -- instruction set. Note that the user can still override this @@ -1253,6 +1257,8 @@ runPhase (RealPhase SplitAs) _input_fn dflags osuf = objectSuf dflags split_odir = base_o ++ "_" ++ osuf ++ "_split" + let pic_c_flags = picCCOpts dflags + -- this also creates the hierarchy liftIO $ createDirectoryIfMissing True split_odir @@ -1286,6 +1292,9 @@ runPhase (RealPhase SplitAs) _input_fn dflags then [SysTools.Option "-mcpu=v9"] else []) ++ + -- See Note [-fPIC for assembler] + map SysTools.Option pic_c_flags ++ + [ SysTools.Option "-c" , SysTools.Option "-o" , SysTools.FileOption "" (split_obj n) @@ -2203,3 +2212,38 @@ haveRtsOptsFlags dflags = isJust (rtsOpts dflags) || case rtsOptsEnabled dflags of RtsOptsSafeOnly -> False _ -> True + +-- Note [-fPIC for assembler] +-- When compiling .c source file GHC's driver pipeline basically +-- does the following two things: +-- 1. ${CC} -S 'PIC_CFLAGS' source.c +-- 2. ${CC} -x assembler -c 'PIC_CFLAGS' source.S +-- +-- Why do we need to pass 'PIC_CFLAGS' both to C compiler and assembler? +-- Because on some architectures (at least sparc32) assembler also choses +-- relocation type! +-- Consider the following C module: +-- +-- /* pic-sample.c */ +-- int v; +-- void set_v (int n) { v = n; } +-- int get_v (void) { return v; } +-- +-- $ gcc -S -fPIC pic-sample.c +-- $ gcc -c pic-sample.s -o pic-sample.no-pic.o # incorrect binary +-- $ gcc -c -fPIC pic-sample.s -o pic-sample.pic.o # correct binary +-- +-- $ objdump -r -d pic-sample.pic.o > pic-sample.pic.o.od +-- $ objdump -r -d pic-sample.no-pic.o > pic-sample.no-pic.o.od +-- $ diff -u pic-sample.pic.o.od pic-sample.no-pic.o.od +-- +-- Most of architectures won't show any difference in this test, but on sparc32 +-- the following assembly snippet: +-- +-- sethi %hi(_GLOBAL_OFFSET_TABLE_-8), %l7 +-- +-- generates two kinds or relocations, only 'R_SPARC_PC22' is correct: +-- +-- 3c: 2f 00 00 00 sethi %hi(0), %l7 +-- - 3c: R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_-0x8 +-- + 3c: R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_-0x8 |