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
