compiler: Write .o files atomically. See #14533
[ghc.git] / compiler / main / SysTools.hs
1 {-
2 -----------------------------------------------------------------------------
3 --
4 -- (c) The University of Glasgow 2001-2003
5 --
6 -- Access to system tools: gcc, cp, rm etc
7 --
8 -----------------------------------------------------------------------------
9 -}
10
11 {-# LANGUAGE CPP, MultiWayIf, ScopedTypeVariables #-}
12
13 module SysTools (
14 -- * Initialisation
15 initSysTools,
16 initLlvmConfig,
17
18 -- * Interface to system tools
19 module SysTools.Tasks,
20 module SysTools.Info,
21
22 linkDynLib,
23
24 copy,
25 copyWithHeader,
26
27 -- * General utilities
28 Option(..),
29 expandTopDir,
30
31 -- * Platform-specifics
32 libmLinkOpts,
33
34 -- * Mac OS X frameworks
35 getPkgFrameworkOpts,
36 getFrameworkOpts
37 ) where
38
39 #include "HsVersions.h"
40
41 import GhcPrelude
42
43 import Module
44 import Packages
45 import Config
46 import Outputable
47 import ErrUtils
48 import Platform
49 import Util
50 import DynFlags
51 import Fingerprint
52
53 import System.FilePath
54 import System.IO
55 import System.Directory
56 import SysTools.ExtraObj
57 import SysTools.Info
58 import SysTools.Tasks
59 import SysTools.BaseDir
60
61 {-
62 Note [How GHC finds toolchain utilities]
63 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
64
65 SysTools.initSysProgs figures out exactly where all the auxiliary programs
66 are, and initialises mutable variables to make it easy to call them.
67 To do this, it makes use of definitions in Config.hs, which is a Haskell
68 file containing variables whose value is figured out by the build system.
69
70 Config.hs contains two sorts of things
71
72 cGCC, The *names* of the programs
73 cCPP e.g. cGCC = gcc
74 cUNLIT cCPP = gcc -E
75 etc They do *not* include paths
76
77
78 cUNLIT_DIR The *path* to the directory containing unlit, split etc
79 cSPLIT_DIR *relative* to the root of the build tree,
80 for use when running *in-place* in a build tree (only)
81
82
83 ---------------------------------------------
84 NOTES for an ALTERNATIVE scheme (i.e *not* what is currently implemented):
85
86 Another hair-brained scheme for simplifying the current tool location
87 nightmare in GHC: Simon originally suggested using another
88 configuration file along the lines of GCC's specs file - which is fine
89 except that it means adding code to read yet another configuration
90 file. What I didn't notice is that the current package.conf is
91 general enough to do this:
92
93 Package
94 {name = "tools", import_dirs = [], source_dirs = [],
95 library_dirs = [], hs_libraries = [], extra_libraries = [],
96 include_dirs = [], c_includes = [], package_deps = [],
97 extra_ghc_opts = ["-pgmc/usr/bin/gcc","-pgml${topdir}/bin/unlit", ... etc.],
98 extra_cc_opts = [], extra_ld_opts = []}
99
100 Which would have the advantage that we get to collect together in one
101 place the path-specific package stuff with the path-specific tool
102 stuff.
103 End of NOTES
104 ---------------------------------------------
105
106 ************************************************************************
107 * *
108 \subsection{Initialisation}
109 * *
110 ************************************************************************
111 -}
112
113 initLlvmConfig :: String
114 -> IO LlvmConfig
115 initLlvmConfig top_dir
116 = do
117 targets <- readAndParse "llvm-targets" mkLlvmTarget
118 passes <- readAndParse "llvm-passes" id
119 return (targets, passes)
120 where
121 readAndParse name builder =
122 do let llvmConfigFile = top_dir </> name
123 llvmConfigStr <- readFile llvmConfigFile
124 case maybeReadFuzzy llvmConfigStr of
125 Just s -> return (fmap builder <$> s)
126 Nothing -> pgmError ("Can't parse " ++ show llvmConfigFile)
127
128 mkLlvmTarget :: (String, String, String) -> LlvmTarget
129 mkLlvmTarget (dl, cpu, attrs) = LlvmTarget dl cpu (words attrs)
130
131
132 initSysTools :: String -- TopDir path
133 -> IO Settings -- Set all the mutable variables above, holding
134 -- (a) the system programs
135 -- (b) the package-config file
136 -- (c) the GHC usage message
137 initSysTools top_dir
138 = do -- see Note [topdir: How GHC finds its files]
139 -- NB: top_dir is assumed to be in standard Unix
140 -- format, '/' separated
141 mtool_dir <- findToolDir top_dir
142 -- see Note [tooldir: How GHC finds mingw and perl on Windows]
143
144 let installed :: FilePath -> FilePath
145 installed file = top_dir </> file
146 libexec :: FilePath -> FilePath
147 libexec file = top_dir </> "bin" </> file
148 settingsFile = installed "settings"
149 platformConstantsFile = installed "platformConstants"
150
151 settingsStr <- readFile settingsFile
152 platformConstantsStr <- readFile platformConstantsFile
153 mySettings <- case maybeReadFuzzy settingsStr of
154 Just s ->
155 return s
156 Nothing ->
157 pgmError ("Can't parse " ++ show settingsFile)
158 platformConstants <- case maybeReadFuzzy platformConstantsStr of
159 Just s ->
160 return s
161 Nothing ->
162 pgmError ("Can't parse " ++
163 show platformConstantsFile)
164 let getSetting key = case lookup key mySettings of
165 Just xs -> return $ expandTopDir top_dir xs
166 Nothing -> pgmError ("No entry for " ++ show key ++ " in " ++ show settingsFile)
167 getToolSetting key = expandToolDir mtool_dir <$> getSetting key
168 getBooleanSetting key = case lookup key mySettings of
169 Just "YES" -> return True
170 Just "NO" -> return False
171 Just xs -> pgmError ("Bad value for " ++ show key ++ ": " ++ show xs)
172 Nothing -> pgmError ("No entry for " ++ show key ++ " in " ++ show settingsFile)
173 readSetting key = case lookup key mySettings of
174 Just xs ->
175 case maybeRead xs of
176 Just v -> return v
177 Nothing -> pgmError ("Failed to read " ++ show key ++ " value " ++ show xs)
178 Nothing -> pgmError ("No entry for " ++ show key ++ " in " ++ show settingsFile)
179 crossCompiling <- getBooleanSetting "cross compiling"
180 targetArch <- readSetting "target arch"
181 targetOS <- readSetting "target os"
182 targetWordSize <- readSetting "target word size"
183 targetUnregisterised <- getBooleanSetting "Unregisterised"
184 targetHasGnuNonexecStack <- readSetting "target has GNU nonexec stack"
185 targetHasIdentDirective <- readSetting "target has .ident directive"
186 targetHasSubsectionsViaSymbols <- readSetting "target has subsections via symbols"
187 myExtraGccViaCFlags <- getSetting "GCC extra via C opts"
188 -- On Windows, mingw is distributed with GHC,
189 -- so we look in TopDir/../mingw/bin,
190 -- as well as TopDir/../../mingw/bin for hadrian.
191 -- It would perhaps be nice to be able to override this
192 -- with the settings file, but it would be a little fiddly
193 -- to make that possible, so for now you can't.
194 gcc_prog <- getToolSetting "C compiler command"
195 gcc_args_str <- getSetting "C compiler flags"
196 gccSupportsNoPie <- getBooleanSetting "C compiler supports -no-pie"
197 cpp_prog <- getToolSetting "Haskell CPP command"
198 cpp_args_str <- getSetting "Haskell CPP flags"
199 let unreg_gcc_args = if targetUnregisterised
200 then ["-DNO_REGS", "-DUSE_MINIINTERPRETER"]
201 else []
202 -- TABLES_NEXT_TO_CODE affects the info table layout.
203 tntc_gcc_args
204 | mkTablesNextToCode targetUnregisterised
205 = ["-DTABLES_NEXT_TO_CODE"]
206 | otherwise = []
207 cpp_args= map Option (words cpp_args_str)
208 gcc_args = map Option (words gcc_args_str
209 ++ unreg_gcc_args
210 ++ tntc_gcc_args)
211 ldSupportsCompactUnwind <- getBooleanSetting "ld supports compact unwind"
212 ldSupportsBuildId <- getBooleanSetting "ld supports build-id"
213 ldSupportsFilelist <- getBooleanSetting "ld supports filelist"
214 ldIsGnuLd <- getBooleanSetting "ld is GNU ld"
215 perl_path <- getToolSetting "perl command"
216
217 let pkgconfig_path = installed "package.conf.d"
218 ghc_usage_msg_path = installed "ghc-usage.txt"
219 ghci_usage_msg_path = installed "ghci-usage.txt"
220
221 -- For all systems, unlit, split, mangle are GHC utilities
222 -- architecture-specific stuff is done when building Config.hs
223 unlit_path = libexec cGHC_UNLIT_PGM
224
225 -- split is a Perl script
226 split_script = libexec cGHC_SPLIT_PGM
227
228 windres_path <- getToolSetting "windres command"
229 libtool_path <- getToolSetting "libtool command"
230 ar_path <- getToolSetting "ar command"
231 ranlib_path <- getToolSetting "ranlib command"
232
233 tmpdir <- getTemporaryDirectory
234
235 touch_path <- getToolSetting "touch command"
236
237 let -- On Win32 we don't want to rely on #!/bin/perl, so we prepend
238 -- a call to Perl to get the invocation of split.
239 -- On Unix, scripts are invoked using the '#!' method. Binary
240 -- installations of GHC on Unix place the correct line on the
241 -- front of the script at installation time, so we don't want
242 -- to wire-in our knowledge of $(PERL) on the host system here.
243 (split_prog, split_args)
244 | isWindowsHost = (perl_path, [Option split_script])
245 | otherwise = (split_script, [])
246 mkdll_prog <- getToolSetting "dllwrap command"
247 let mkdll_args = []
248
249 -- cpp is derived from gcc on all platforms
250 -- HACK, see setPgmP below. We keep 'words' here to remember to fix
251 -- Config.hs one day.
252
253
254 -- Other things being equal, as and ld are simply gcc
255 gcc_link_args_str <- getSetting "C compiler link flags"
256 let as_prog = gcc_prog
257 as_args = gcc_args
258 ld_prog = gcc_prog
259 ld_args = gcc_args ++ map Option (words gcc_link_args_str)
260
261 -- We just assume on command line
262 lc_prog <- getSetting "LLVM llc command"
263 lo_prog <- getSetting "LLVM opt command"
264 lcc_prog <- getSetting "LLVM clang command"
265
266 let iserv_prog = libexec "ghc-iserv"
267
268 let platform = Platform {
269 platformArch = targetArch,
270 platformOS = targetOS,
271 platformWordSize = targetWordSize,
272 platformUnregisterised = targetUnregisterised,
273 platformHasGnuNonexecStack = targetHasGnuNonexecStack,
274 platformHasIdentDirective = targetHasIdentDirective,
275 platformHasSubsectionsViaSymbols = targetHasSubsectionsViaSymbols,
276 platformIsCrossCompiling = crossCompiling
277 }
278
279 return $ Settings {
280 sTargetPlatform = platform,
281 sTmpDir = normalise tmpdir,
282 sGhcUsagePath = ghc_usage_msg_path,
283 sGhciUsagePath = ghci_usage_msg_path,
284 sToolDir = mtool_dir,
285 sTopDir = top_dir,
286 sRawSettings = mySettings,
287 sExtraGccViaCFlags = words myExtraGccViaCFlags,
288 sSystemPackageConfig = pkgconfig_path,
289 sLdSupportsCompactUnwind = ldSupportsCompactUnwind,
290 sLdSupportsBuildId = ldSupportsBuildId,
291 sLdSupportsFilelist = ldSupportsFilelist,
292 sLdIsGnuLd = ldIsGnuLd,
293 sGccSupportsNoPie = gccSupportsNoPie,
294 sProgramName = "ghc",
295 sProjectVersion = cProjectVersion,
296 sPgm_L = unlit_path,
297 sPgm_P = (cpp_prog, cpp_args),
298 sPgm_F = "",
299 sPgm_c = (gcc_prog, gcc_args),
300 sPgm_s = (split_prog,split_args),
301 sPgm_a = (as_prog, as_args),
302 sPgm_l = (ld_prog, ld_args),
303 sPgm_dll = (mkdll_prog,mkdll_args),
304 sPgm_T = touch_path,
305 sPgm_windres = windres_path,
306 sPgm_libtool = libtool_path,
307 sPgm_ar = ar_path,
308 sPgm_ranlib = ranlib_path,
309 sPgm_lo = (lo_prog,[]),
310 sPgm_lc = (lc_prog,[]),
311 sPgm_lcc = (lcc_prog,[]),
312 sPgm_i = iserv_prog,
313 sOpt_L = [],
314 sOpt_P = [],
315 sOpt_P_fingerprint = fingerprint0,
316 sOpt_F = [],
317 sOpt_c = [],
318 sOpt_a = [],
319 sOpt_l = [],
320 sOpt_windres = [],
321 sOpt_lcc = [],
322 sOpt_lo = [],
323 sOpt_lc = [],
324 sOpt_i = [],
325 sPlatformConstants = platformConstants
326 }
327
328
329 {- Note [Windows stack usage]
330
331 See: Trac #8870 (and #8834 for related info) and #12186
332
333 On Windows, occasionally we need to grow the stack. In order to do
334 this, we would normally just bump the stack pointer - but there's a
335 catch on Windows.
336
337 If the stack pointer is bumped by more than a single page, then the
338 pages between the initial pointer and the resulting location must be
339 properly committed by the Windows virtual memory subsystem. This is
340 only needed in the event we bump by more than one page (i.e 4097 bytes
341 or more).
342
343 Windows compilers solve this by emitting a call to a special function
344 called _chkstk, which does this committing of the pages for you.
345
346 The reason this was causing a segfault was because due to the fact the
347 new code generator tends to generate larger functions, we needed more
348 stack space in GHC itself. In the x86 codegen, we needed approximately
349 ~12kb of stack space in one go, which caused the process to segfault,
350 as the intervening pages were not committed.
351
352 GCC can emit such a check for us automatically but only when the flag
353 -fstack-check is used.
354
355 See https://gcc.gnu.org/onlinedocs/gnat_ugn/Stack-Overflow-Checking.html
356 for more information.
357
358 -}
359
360 copy :: DynFlags -> String -> FilePath -> FilePath -> IO ()
361 copy dflags purpose from to = copyWithHeader dflags purpose Nothing from to
362
363 copyWithHeader :: DynFlags -> String -> Maybe String -> FilePath -> FilePath
364 -> IO ()
365 copyWithHeader dflags purpose maybe_header from to = do
366 showPass dflags purpose
367
368 hout <- openBinaryFile to WriteMode
369 hin <- openBinaryFile from ReadMode
370 ls <- hGetContents hin -- inefficient, but it'll do for now. ToDo: speed up
371 maybe (return ()) (header hout) maybe_header
372 hPutStr hout ls
373 hClose hout
374 hClose hin
375 where
376 -- write the header string in UTF-8. The header is something like
377 -- {-# LINE "foo.hs" #-}
378 -- and we want to make sure a Unicode filename isn't mangled.
379 header h str = do
380 hSetEncoding h utf8
381 hPutStr h str
382 hSetBinaryMode h True
383
384 {-
385 ************************************************************************
386 * *
387 \subsection{Support code}
388 * *
389 ************************************************************************
390 -}
391
392 linkDynLib :: DynFlags -> [String] -> [InstalledUnitId] -> IO ()
393 linkDynLib dflags0 o_files dep_packages
394 = do
395 let -- This is a rather ugly hack to fix dynamically linked
396 -- GHC on Windows. If GHC is linked with -threaded, then
397 -- it links against libHSrts_thr. But if base is linked
398 -- against libHSrts, then both end up getting loaded,
399 -- and things go wrong. We therefore link the libraries
400 -- with the same RTS flags that we link GHC with.
401 dflags1 = if cGhcThreaded then addWay' WayThreaded dflags0
402 else dflags0
403 dflags2 = if cGhcDebugged then addWay' WayDebug dflags1
404 else dflags1
405 dflags = updateWays dflags2
406
407 verbFlags = getVerbFlags dflags
408 o_file = outputFile dflags
409
410 pkgs <- getPreloadPackagesAnd dflags dep_packages
411
412 let pkg_lib_paths = collectLibraryPaths dflags pkgs
413 let pkg_lib_path_opts = concatMap get_pkg_lib_path_opts pkg_lib_paths
414 get_pkg_lib_path_opts l
415 | ( osElfTarget (platformOS (targetPlatform dflags)) ||
416 osMachOTarget (platformOS (targetPlatform dflags)) ) &&
417 dynLibLoader dflags == SystemDependent &&
418 WayDyn `elem` ways dflags
419 = ["-L" ++ l, "-Xlinker", "-rpath", "-Xlinker", l]
420 -- See Note [-Xlinker -rpath vs -Wl,-rpath]
421 | otherwise = ["-L" ++ l]
422
423 let lib_paths = libraryPaths dflags
424 let lib_path_opts = map ("-L"++) lib_paths
425
426 -- We don't want to link our dynamic libs against the RTS package,
427 -- because the RTS lib comes in several flavours and we want to be
428 -- able to pick the flavour when a binary is linked.
429 -- On Windows we need to link the RTS import lib as Windows does
430 -- not allow undefined symbols.
431 -- The RTS library path is still added to the library search path
432 -- above in case the RTS is being explicitly linked in (see #3807).
433 let platform = targetPlatform dflags
434 os = platformOS platform
435 pkgs_no_rts = case os of
436 OSMinGW32 ->
437 pkgs
438 _ ->
439 filter ((/= rtsUnitId) . packageConfigId) pkgs
440 let pkg_link_opts = let (package_hs_libs, extra_libs, other_flags) = collectLinkOpts dflags pkgs_no_rts
441 in package_hs_libs ++ extra_libs ++ other_flags
442
443 -- probably _stub.o files
444 -- and last temporary shared object file
445 let extra_ld_inputs = ldInputs dflags
446
447 -- frameworks
448 pkg_framework_opts <- getPkgFrameworkOpts dflags platform
449 (map unitId pkgs)
450 let framework_opts = getFrameworkOpts dflags platform
451
452 case os of
453 OSMinGW32 -> do
454 -------------------------------------------------------------
455 -- Making a DLL
456 -------------------------------------------------------------
457 let output_fn = case o_file of
458 Just s -> s
459 Nothing -> "HSdll.dll"
460
461 runLink dflags (
462 map Option verbFlags
463 ++ [ Option "-o"
464 , FileOption "" output_fn
465 , Option "-shared"
466 ] ++
467 [ FileOption "-Wl,--out-implib=" (output_fn ++ ".a")
468 | gopt Opt_SharedImplib dflags
469 ]
470 ++ map (FileOption "") o_files
471
472 -- Permit the linker to auto link _symbol to _imp_symbol
473 -- This lets us link against DLLs without needing an "import library"
474 ++ [Option "-Wl,--enable-auto-import"]
475
476 ++ extra_ld_inputs
477 ++ map Option (
478 lib_path_opts
479 ++ pkg_lib_path_opts
480 ++ pkg_link_opts
481 ))
482 _ | os == OSDarwin -> do
483 -------------------------------------------------------------------
484 -- Making a darwin dylib
485 -------------------------------------------------------------------
486 -- About the options used for Darwin:
487 -- -dynamiclib
488 -- Apple's way of saying -shared
489 -- -undefined dynamic_lookup:
490 -- Without these options, we'd have to specify the correct
491 -- dependencies for each of the dylibs. Note that we could
492 -- (and should) do without this for all libraries except
493 -- the RTS; all we need to do is to pass the correct
494 -- HSfoo_dyn.dylib files to the link command.
495 -- This feature requires Mac OS X 10.3 or later; there is
496 -- a similar feature, -flat_namespace -undefined suppress,
497 -- which works on earlier versions, but it has other
498 -- disadvantages.
499 -- -single_module
500 -- Build the dynamic library as a single "module", i.e. no
501 -- dynamic binding nonsense when referring to symbols from
502 -- within the library. The NCG assumes that this option is
503 -- specified (on i386, at least).
504 -- -install_name
505 -- Mac OS/X stores the path where a dynamic library is (to
506 -- be) installed in the library itself. It's called the
507 -- "install name" of the library. Then any library or
508 -- executable that links against it before it's installed
509 -- will search for it in its ultimate install location.
510 -- By default we set the install name to the absolute path
511 -- at build time, but it can be overridden by the
512 -- -dylib-install-name option passed to ghc. Cabal does
513 -- this.
514 -------------------------------------------------------------------
515
516 let output_fn = case o_file of { Just s -> s; Nothing -> "a.out"; }
517
518 instName <- case dylibInstallName dflags of
519 Just n -> return n
520 Nothing -> return $ "@rpath" `combine` (takeFileName output_fn)
521 runLink dflags (
522 map Option verbFlags
523 ++ [ Option "-dynamiclib"
524 , Option "-o"
525 , FileOption "" output_fn
526 ]
527 ++ map Option o_files
528 ++ [ Option "-undefined",
529 Option "dynamic_lookup",
530 Option "-single_module" ]
531 ++ (if platformArch platform == ArchX86_64
532 then [ ]
533 else [ Option "-Wl,-read_only_relocs,suppress" ])
534 ++ [ Option "-install_name", Option instName ]
535 ++ map Option lib_path_opts
536 ++ extra_ld_inputs
537 ++ map Option framework_opts
538 ++ map Option pkg_lib_path_opts
539 ++ map Option pkg_link_opts
540 ++ map Option pkg_framework_opts
541 ++ [ Option "-Wl,-dead_strip_dylibs" ]
542 )
543 _ -> do
544 -------------------------------------------------------------------
545 -- Making a DSO
546 -------------------------------------------------------------------
547
548 let output_fn = case o_file of { Just s -> s; Nothing -> "a.out"; }
549 unregisterised = platformUnregisterised (targetPlatform dflags)
550 let bsymbolicFlag = -- we need symbolic linking to resolve
551 -- non-PIC intra-package-relocations for
552 -- performance (where symbolic linking works)
553 -- See Note [-Bsymbolic assumptions by GHC]
554 ["-Wl,-Bsymbolic" | not unregisterised]
555
556 runLink dflags (
557 map Option verbFlags
558 ++ libmLinkOpts
559 ++ [ Option "-o"
560 , FileOption "" output_fn
561 ]
562 ++ map Option o_files
563 ++ [ Option "-shared" ]
564 ++ map Option bsymbolicFlag
565 -- Set the library soname. We use -h rather than -soname as
566 -- Solaris 10 doesn't support the latter:
567 ++ [ Option ("-Wl,-h," ++ takeFileName output_fn) ]
568 ++ extra_ld_inputs
569 ++ map Option lib_path_opts
570 ++ map Option pkg_lib_path_opts
571 ++ map Option pkg_link_opts
572 )
573
574 -- | Some platforms require that we explicitly link against @libm@ if any
575 -- math-y things are used (which we assume to include all programs). See #14022.
576 libmLinkOpts :: [Option]
577 libmLinkOpts =
578 #if defined(HAVE_LIBM)
579 [Option "-lm"]
580 #else
581 []
582 #endif
583
584 getPkgFrameworkOpts :: DynFlags -> Platform -> [InstalledUnitId] -> IO [String]
585 getPkgFrameworkOpts dflags platform dep_packages
586 | platformUsesFrameworks platform = do
587 pkg_framework_path_opts <- do
588 pkg_framework_paths <- getPackageFrameworkPath dflags dep_packages
589 return $ map ("-F" ++) pkg_framework_paths
590
591 pkg_framework_opts <- do
592 pkg_frameworks <- getPackageFrameworks dflags dep_packages
593 return $ concat [ ["-framework", fw] | fw <- pkg_frameworks ]
594
595 return (pkg_framework_path_opts ++ pkg_framework_opts)
596
597 | otherwise = return []
598
599 getFrameworkOpts :: DynFlags -> Platform -> [String]
600 getFrameworkOpts dflags platform
601 | platformUsesFrameworks platform = framework_path_opts ++ framework_opts
602 | otherwise = []
603 where
604 framework_paths = frameworkPaths dflags
605 framework_path_opts = map ("-F" ++) framework_paths
606
607 frameworks = cmdlineFrameworks dflags
608 -- reverse because they're added in reverse order from the cmd line:
609 framework_opts = concat [ ["-framework", fw]
610 | fw <- reverse frameworks ]
611
612 {-
613 Note [-Bsymbolic assumptions by GHC]
614 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
615
616 GHC has a few assumptions about interaction of relocations in NCG and linker:
617
618 1. -Bsymbolic resolves internal references when the shared library is linked,
619 which is important for performance.
620 2. When there is a reference to data in a shared library from the main program,
621 the runtime linker relocates the data object into the main program using an
622 R_*_COPY relocation.
623 3. If we used -Bsymbolic, then this results in multiple copies of the data
624 object, because some references have already been resolved to point to the
625 original instance. This is bad!
626
627 We work around [3.] for native compiled code by avoiding the generation of
628 R_*_COPY relocations.
629
630 Unregisterised compiler can't evade R_*_COPY relocations easily thus we disable
631 -Bsymbolic linking there.
632
633 See related Trac tickets: #4210, #15338
634 -}