Mon Nov 30 22:12:34 PST 2009  [email protected]
  * Fix GHC ticket 2615 (linker scripts in .so files)
  This patch only applies to systems that use ELF format files.
  The patch modifies the addDLL function so that it recognizes
  "invalid ELF header" errors. If these occur, the file that was opened
  is scanned for a linker script GROUP ( ... ) directive. If found,
  the first file inside the GROUP ( ... ) will be sent to dlopen.
  Any errors reported by dlopen then will be reported  to the caller.

New patches:

[Fix GHC ticket 2615 (linker scripts in .so files)
[email protected]**20091201061234
 Ignore-this: 473d783b8019f375c737a4e6b0627710
 This patch only applies to systems that use ELF format files.
 The patch modifies the addDLL function so that it recognizes
 "invalid ELF header" errors. If these occur, the file that was opened
 is scanned for a linker script GROUP ( ... ) directive. If found,
 the first file inside the GROUP ( ... ) will be sent to dlopen.
 Any errors reported by dlopen then will be reported  to the caller.
] {
hunk ./rts/Linker.c 9
  *
  * 
---------------------------------------------------------------------------*/
 
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
 #if 0
 #include "PosixSource.h"
 #endif
hunk ./rts/Linker.c 43
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
+#include <assert.h>
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
hunk ./rts/Linker.c 85
 
 #if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || 
defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || 
defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #  define OBJFORMAT_ELF
+#  include <regex.h>
 #elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
 #  define OBJFORMAT_PEi386
 #  include <windows.h>
hunk ./rts/Linker.c 1102
 
 #if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
 static void *dl_prog_handle;
+static regex_t re_invalid;
+static regex_t re_realso;
+static void initLinkerCleanup( void );
 #endif
 
 void
hunk ./rts/Linker.c 1111
 initLinker( void )
 {
     RtsSymbolVal *sym;
+    int compileResult;
 
     /* Make initLinker idempotent, so we can call it
        before evey relevant operation; that means we
hunk ./rts/Linker.c 1138
 #   else
     dl_prog_handle = dlopen(NULL, RTLD_LAZY);
 #   endif /* RTLD_DEFAULT */
+    compileResult = regcomp(&re_invalid,
+               "(/[^ \\t()]+\\.so[^ \\t():]*):[ \\t]*invalid ELF header",
+               REG_EXTENDED);
+    ASSERT( compileResult == 0 );
+    compileResult = regcomp(&re_realso,
+               "GROUP *\\( *(([^ \\)])+)",
+               REG_EXTENDED);
+    ASSERT( compileResult == 0 );
+    atexit(initLinkerCleanup);
 #   endif
 
 #if defined(x86_64_HOST_ARCH)
hunk ./rts/Linker.c 1167
 #endif
 }
 
+#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
+void
+initLinkerCleanup( void ) {
+   regfree(&re_invalid);
+   regfree(&re_realso);
+}
+#endif
+
 /* 
-----------------------------------------------------------------------------
  *                  Loading DLL or .so dynamic libraries
  * 
-----------------------------------------------------------------------------
hunk ./rts/Linker.c 1210
 static OpenedDLL* opened_dlls = NULL;
 #endif
 
-const char *
-addDLL( char *dll_name )
-{
 #  if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
hunk ./rts/Linker.c 1211
-   /* ------------------- ELF DLL loader ------------------- */
+static char *
+internal_dlopen(const char *dll_name)
+{
    void *hdl;
hunk ./rts/Linker.c 1215
-   const char *errmsg;
-
-   initLinker();
+   char *errmsg;
 
    // omitted: RTLD_NOW
    // see http://www.haskell.org/pipermail/cvs-ghc/2007-September/038570.html
hunk ./rts/Linker.c 1219
-   hdl= dlopen(dll_name, RTLD_LAZY | RTLD_GLOBAL);
+   debugBelch("internal_dlopen: dll_name = '%s'\n", dll_name);
+   hdl = dlopen(dll_name, RTLD_LAZY | RTLD_GLOBAL);
 
hunk ./rts/Linker.c 1222
+   errmsg = NULL;
    if (hdl == NULL) {
       /* dlopen failed; return a ptr to the error msg. */
       errmsg = dlerror();
hunk ./rts/Linker.c 1227
       if (errmsg == NULL) errmsg = "addDLL: unknown error";
-      return errmsg;
-   } else {
+   }
+   return errmsg;
+}
+#  endif
+
+const char *
+addDLL( char *dll_name )
+{
+#  if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
+   /* ------------------- ELF DLL loader ------------------- */
+
+#define NMATCH 2
+   regmatch_t match[NMATCH];
+   char *errmsg;
+   FILE* fp;
+   size_t match_length;
+#define MAXLINE 1000
+   char line[MAXLINE];
+ 
+   initLinker();
+
+   debugBelch("addDLL: dll_name = '%s'\n", dll_name);
+   errmsg = internal_dlopen(dll_name);
+
+   if (errmsg == NULL) {
       return NULL;
    }
hunk ./rts/Linker.c 1254
-   /*NOTREACHED*/
+
+   // see if the error message is due to an invalid ELF header
+
+   debugBelch("errmsg = '%s'\n", errmsg);
+   if (regexec(&re_invalid, errmsg, (size_t) NMATCH, match, 0) == 0) {
+
+      // try to read the named file as a linker script
+
+      match_length = (size_t) MIN((match[1].rm_eo - match[1].rm_so),
+                                MAXLINE-1);
+      strncpy(line, (errmsg+(match[1].rm_so)),match_length);
+      line[match_length] = '\0'; // make sure string is null-terminated
+      debugBelch ("file name = '%s'\n", line);
+      if ((fp = fopen(line, "r")) == NULL) {
+        return errmsg;
+      }
+      // try to find a GROUP ( ... ) command
+      while (fgets(line, MAXLINE, fp) != NULL) {
+        debugBelch("input line = %s", line);
+        if (regexec(&re_realso, line, (size_t) NMATCH, match, 0) == 0) {
+           debugBelch("match%s\n","");
+           line[match[1].rm_eo] = '\0';
+           errmsg = internal_dlopen(line+match[1].rm_so);
+           break;
+        }
+      } 
+   }
+   fclose(fp);
+   return errmsg;
 
 #  elif defined(OBJFORMAT_PEi386)
    /* ------------------- Win32 DLL loader ------------------- */
hunk ./rts/Linker.c 4273
                         i++;
                     }
  #endif
-                    else 
+                    else
                     {
                        barf ("Don't know how to handle this Mach-O "
                              "scattered relocation entry: "
hunk ./rts/Linker.c 4282
                               oc->fileName, scat->r_type, scat->r_address);
                         return 0;
                      }
-                     
+
 #ifdef powerpc_HOST_ARCH
                     if(scat->r_type == GENERIC_RELOC_VANILLA
                         || scat->r_type == PPC_RELOC_SECTDIFF)
hunk ./rts/Linker.c 4328
                      "object file %s; entry type %ld; address %#lx\n", 
                      oc->fileName, scat->r_type, scat->r_address);
                return 0;
-            }
-      
+           }
+
        }
        else /* !(relocs[i].r_address & R_SCATTERED) */
        {
}

_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to