Revert "Fix obscure problem with using the system linker (#8935)"
authorAustin Seipp <austin@well-typed.com>
Mon, 30 Jun 2014 12:44:31 +0000 (07:44 -0500)
committerAustin Seipp <austin@well-typed.com>
Mon, 30 Jun 2014 12:44:31 +0000 (07:44 -0500)
This reverts commit 2f8b4c9330b455d4cb31c186c747a7db12a69251.

Signed-off-by: Austin Seipp <austin@well-typed.com>
compiler/ghci/Linker.lhs
rts/Linker.c

index 162c349..0b23985 100644 (file)
@@ -124,12 +124,8 @@ data PersistentLinkerState
         -- The currently-loaded packages; always object code
         -- Held, as usual, in dependency order; though I am not sure if
         -- that is really important
-        pkgs_loaded :: ![PackageId],
-
-        -- we need to remember the name of the last temporary DLL/.so
-        -- so we can link it
-        last_temp_so :: !(Maybe FilePath)
-         }
+        pkgs_loaded :: ![PackageId]
+     }
 
 emptyPLS :: DynFlags -> PersistentLinkerState
 emptyPLS _ = PersistentLinkerState {
@@ -137,8 +133,7 @@ emptyPLS _ = PersistentLinkerState {
                         itbl_env    = emptyNameEnv,
                         pkgs_loaded = init_pkgs,
                         bcos_loaded = [],
-                        objs_loaded = [],
-                        last_temp_so = Nothing }
+                        objs_loaded = [] }
 
   -- Packages that don't need loading, because the compiler
   -- shares them with the interpreted program.
@@ -320,14 +315,14 @@ reallyInitDynLinker dflags =
         ; if null cmdline_lib_specs then return pls
                                     else do
 
-        { pls1 <- foldM (preloadLib dflags lib_paths framework_paths) pls cmdline_lib_specs
+        { mapM_ (preloadLib dflags lib_paths framework_paths) cmdline_lib_specs
         ; maybePutStr dflags "final link ... "
         ; ok <- resolveObjs
 
         ; if succeeded ok then maybePutStrLn dflags "done"
           else throwGhcExceptionIO (ProgramError "linking extra libraries/objects failed")
 
-        ; return pls1
+        ; return pls
         }}
 
 
@@ -366,21 +361,19 @@ classifyLdInput dflags f
         return Nothing
     where platform = targetPlatform dflags
 
-preloadLib :: DynFlags -> [String] -> [String] -> PersistentLinkerState -> LibrarySpec -> IO (PersistentLinkerState)
-preloadLib dflags lib_paths framework_paths pls lib_spec
+preloadLib :: DynFlags -> [String] -> [String] -> LibrarySpec -> IO ()
+preloadLib dflags lib_paths framework_paths lib_spec
   = do maybePutStr dflags ("Loading object " ++ showLS lib_spec ++ " ... ")
        case lib_spec of
           Object static_ish
-             -> do (b, pls1) <- preload_static lib_paths static_ish
+             -> do b <- preload_static lib_paths static_ish
                    maybePutStrLn dflags (if b  then "done"
                                                 else "not found")
-                   return pls1
 
           Archive static_ish
              -> do b <- preload_static_archive lib_paths static_ish
                    maybePutStrLn dflags (if b  then "done"
                                                 else "not found")
-                   return pls
 
           DLL dll_unadorned
              -> do maybe_errstr <- loadDLL (mkSOName platform dll_unadorned)
@@ -396,14 +389,12 @@ preloadLib dflags lib_paths framework_paths pls lib_spec
                         case err2 of
                           Nothing -> maybePutStrLn dflags "done"
                           Just _  -> preloadFailed mm lib_paths lib_spec
-                   return pls
 
           DLLPath dll_path
              -> do maybe_errstr <- loadDLL dll_path
                    case maybe_errstr of
                       Nothing -> maybePutStrLn dflags "done"
                       Just mm -> preloadFailed mm lib_paths lib_spec
-                   return pls
 
           Framework framework ->
               if platformUsesFrameworks (targetPlatform dflags)
@@ -411,7 +402,6 @@ preloadLib dflags lib_paths framework_paths pls lib_spec
                       case maybe_errstr of
                          Nothing -> maybePutStrLn dflags "done"
                          Just mm -> preloadFailed mm framework_paths lib_spec
-                      return pls
               else panic "preloadLib Framework"
 
   where
@@ -431,13 +421,11 @@ preloadLib dflags lib_paths framework_paths pls lib_spec
     -- Not interested in the paths in the static case.
     preload_static _paths name
        = do b <- doesFileExist name
-            if not b then return (False, pls)
-                     else if dynamicGhc
-                             then  do pls1 <- dynLoadObjs dflags pls [name]
-                                      return (True, pls1)
-                             else  do loadObj name
-                                      return (True, pls)
-
+            if not b then return False
+                     else do if dynamicGhc
+                                 then dynLoadObjs dflags [name]
+                                 else loadObj name
+                             return True
     preload_static_archive _paths name
        = do b <- doesFileExist name
             if not b then return False
@@ -804,8 +792,8 @@ dynLinkObjs dflags pls objs = do
             wanted_objs              = map nameOfObject unlinkeds
 
         if dynamicGhc
-            then do pls2 <- dynLoadObjs dflags pls1 wanted_objs
-                    return (pls2, Succeeded)
+            then do dynLoadObjs dflags wanted_objs
+                    return (pls1, Succeeded)
             else do mapM_ loadObj wanted_objs
 
                     -- Link them all together
@@ -819,11 +807,9 @@ dynLinkObjs dflags pls objs = do
                             pls2 <- unload_wkr dflags [] pls1
                             return (pls2, Failed)
 
-
-dynLoadObjs :: DynFlags -> PersistentLinkerState -> [FilePath]
-            -> IO PersistentLinkerState
-dynLoadObjs _      pls []   = return pls
-dynLoadObjs dflags pls objs = do
+dynLoadObjs :: DynFlags -> [FilePath] -> IO ()
+dynLoadObjs _      []   = return ()
+dynLoadObjs dflags objs = do
     let platform = targetPlatform dflags
     soFile <- newTempName dflags (soExt platform)
     let -- When running TH for a non-dynamic way, we still need to make
@@ -831,22 +817,10 @@ dynLoadObjs dflags pls objs = do
         -- Opt_Static off
         dflags1 = gopt_unset dflags Opt_Static
         dflags2 = dflags1 {
-                      -- We don't want the original ldInputs in
-                      -- (they're already linked in), but we do want
-                      -- to link against the previous dynLoadObjs
-                      -- library if there was one, so that the linker
-                      -- can resolve dependencies when it loads this
-                      -- library.
-                      ldInputs =
-                        case last_temp_so pls of
-                          Nothing -> []
-                          Just so  ->
-                                 let (lp, l) = splitFileName so in
-                                 [ Option ("-L" ++ lp)
-                                 , Option ("-Wl,-rpath")
-                                 , Option ("-Wl," ++ lp)
-                                 , Option ("-l:" ++ l)
-                                 ],
+                      -- We don't want to link the ldInputs in; we'll
+                      -- be calling dynLoadObjs with any objects that
+                      -- need to be linked.
+                      ldInputs = [],
                       -- Even if we're e.g. profiling, we still want
                       -- the vanilla dynamic libraries, so we set the
                       -- ways / build tag to be just WayDyn.
@@ -858,7 +832,7 @@ dynLoadObjs dflags pls objs = do
     consIORef (filesToNotIntermediateClean dflags) soFile
     m <- loadDLL soFile
     case m of
-        Nothing -> return pls { last_temp_so = Just soFile }
+        Nothing -> return ()
         Just err -> panic ("Loading temp shared object failed: " ++ err)
 
 rmDupLinkables :: [Linkable]    -- Already loaded
index f7f554c..e5e61bb 100644 (file)
@@ -1798,7 +1798,7 @@ internal_dlopen(const char *dll_name)
    // (see POSIX also)
 
    ACQUIRE_LOCK(&dl_mutex);
-   hdl = dlopen(dll_name, RTLD_LAZY|RTLD_LOCAL); /* see Note [RTLD_LOCAL] */
+   hdl = dlopen(dll_name, RTLD_LAZY | RTLD_GLOBAL);
 
    errmsg = NULL;
    if (hdl == NULL) {
@@ -1808,12 +1808,11 @@ internal_dlopen(const char *dll_name)
       errmsg_copy = stgMallocBytes(strlen(errmsg)+1, "addDLL");
       strcpy(errmsg_copy, errmsg);
       errmsg = errmsg_copy;
-   } else {
-      o_so = stgMallocBytes(sizeof(OpenedSO), "addDLL");
-      o_so->handle = hdl;
-      o_so->next   = openedSOs;
-      openedSOs    = o_so;
    }
+   o_so = stgMallocBytes(sizeof(OpenedSO), "addDLL");
+   o_so->handle = hdl;
+   o_so->next   = openedSOs;
+   openedSOs    = o_so;
 
    RELEASE_LOCK(&dl_mutex);
    //--------------- End critical section -------------------
@@ -1821,39 +1820,14 @@ internal_dlopen(const char *dll_name)
    return errmsg;
 }
 
-/*
-  Note [RTLD_LOCAL]
-
-  In GHCi we want to be able to override previous .so's with newly
-  loaded .so's when we recompile something.  This further implies that
-  when we look up a symbol in internal_dlsym() we have to iterate
-  through the loaded libraries (in order from most recently loaded to
-  oldest) looking up the symbol in each one until we find it.
-
-  However, this can cause problems for some symbols that are copied
-  by the linker into the executable image at runtime - see #8935 for a
-  lengthy discussion.  To solve that problem we need to look up
-  symbols in the main executable *first*, before attempting to look
-  them up in the loaded .so's.  But in order to make that work, we
-  have to always call dlopen with RTLD_LOCAL, so that the loaded
-  libraries don't populate the global symbol table.
-*/
-
 static void *
-internal_dlsym(const char *symbol) {
+internal_dlsym(void *hdl, const char *symbol) {
     OpenedSO* o_so;
     void *v;
 
     // We acquire dl_mutex as concurrent dl* calls may alter dlerror
     ACQUIRE_LOCK(&dl_mutex);
     dlerror();
-    // look in program first
-    v = dlsym(dl_prog_handle, symbol);
-    if (dlerror() == NULL) {
-        RELEASE_LOCK(&dl_mutex);
-        return v;
-    }
-
     for (o_so = openedSOs; o_so != NULL; o_so = o_so->next) {
         v = dlsym(o_so->handle, symbol);
         if (dlerror() == NULL) {
@@ -1861,6 +1835,7 @@ internal_dlsym(const char *symbol) {
             return v;
         }
     }
+    v = dlsym(hdl, symbol);
     RELEASE_LOCK(&dl_mutex);
     return v;
 }
@@ -2028,7 +2003,7 @@ lookupSymbol( char *lbl )
     if (!ghciLookupSymbolTable(symhash, lbl, &val)) {
         IF_DEBUG(linker, debugBelch("lookupSymbol: symbol not found\n"));
 #       if defined(OBJFORMAT_ELF)
-        return internal_dlsym(lbl);
+        return internal_dlsym(dl_prog_handle, lbl);
 #       elif defined(OBJFORMAT_MACHO)
 #       if HAVE_DLFCN_H
         /* On OS X 10.3 and later, we use dlsym instead of the old legacy
@@ -2042,7 +2017,7 @@ lookupSymbol( char *lbl )
         */
         IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s with dlsym\n", lbl));
         ASSERT(lbl[0] == '_');
-        return internal_dlsym(lbl + 1);
+        return internal_dlsym(dl_prog_handle, lbl + 1);
 #       else
         if (NSIsSymbolNameDefined(lbl)) {
             NSSymbol symbol = NSLookupAndBindSymbol(lbl);