Fix GHC ticket 2615 (linker scripts in .so files)
Howard B. Golden
hgolden at socal.rr.com
Tue Dec 1 01:49:12 EST 2009
Mon Nov 30 22:12:34 PST 2009 howard_b_golden at yahoo.com
* 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)
howard_b_golden at yahoo.com**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) */
{
}
More information about the Cvs-ghc
mailing list