diff options
author | Sergei Trofimovich <slyfox@gentoo.org> | 2011-03-27 19:44:17 +0000 |
---|---|---|
committer | Sergei Trofimovich <slyfox@gentoo.org> | 2011-03-27 19:44:17 +0000 |
commit | 75341664f3f5ad24d7a41ca779eebd62aa94a4a7 (patch) | |
tree | 9dc650879995e0742d89b579bd2fe54d2c6e9a34 /dev-lang/ghc/files | |
parent | stable ppc, bug 358681 (diff) | |
download | gentoo-2-75341664f3f5ad24d7a41ca779eebd62aa94a4a7.tar.gz gentoo-2-75341664f3f5ad24d7a41ca779eebd62aa94a4a7.tar.bz2 gentoo-2-75341664f3f5ad24d7a41ca779eebd62aa94a4a7.zip |
Migrated to EAPI=3: initial PREFIX support (based on work of grobian); USE=unicode for ncurses is a required depend (bug #326237 by Josh Cartwright and others). Added linker script support to workaround bug #311361 by Maciej Piechotka.
(Portage version: 2.1.9.42/cvs/Linux x86_64)
Diffstat (limited to 'dev-lang/ghc/files')
-rw-r--r-- | dev-lang/ghc/files/ghc-6.12.3-ticket-2615-linker-script.patch | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/dev-lang/ghc/files/ghc-6.12.3-ticket-2615-linker-script.patch b/dev-lang/ghc/files/ghc-6.12.3-ticket-2615-linker-script.patch new file mode 100644 index 000000000000..96fdcb6a8091 --- /dev/null +++ b/dev-lang/ghc/files/ghc-6.12.3-ticket-2615-linker-script.patch @@ -0,0 +1,278 @@ +Wed Dec 16 19:51:55 CET 2009 howard_b_golden@yahoo.com + * FIX #2615 (linker scripts in .so files) + This patch does not apply to Windows. It only applies to systems with + ELF binaries. + + This is a patch to rts/Linker.c to recognize linker scripts in .so + files and find the real target .so shared library for loading. +diff -rN -u old-ghc/rts/Linker.c new-ghc/rts/Linker.c +--- old-ghc/rts/Linker.c 2010-07-28 22:59:33.532759118 +0200 ++++ new-ghc/rts/Linker.c 2010-07-28 22:59:34.853759052 +0200 +@@ -39,6 +39,8 @@ + + #include <stdlib.h> + #include <string.h> ++#include <stdio.h> ++#include <assert.h> + + #ifdef HAVE_SYS_STAT_H + #include <sys/stat.h> +@@ -79,6 +81,8 @@ + + #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> // regex is already used by dlopen() so this is OK ++ // to use here without requiring an additional lib + #elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) + # define OBJFORMAT_PEi386 + # include <windows.h> +@@ -1095,12 +1099,19 @@ + + #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 ); ++#ifdef THREADED_RTS ++static Mutex dl_mutex; // mutex to protect dlopen/dlerror critical section ++#endif + #endif + + void + initLinker( void ) + { + RtsSymbolVal *sym; ++ int compileResult; + + /* Make initLinker idempotent, so we can call it + before evey relevant operation; that means we +@@ -1109,6 +1120,9 @@ + linker_init_done = 1; + } + ++#ifdef THREADED_RTS ++ initMutex(&dl_mutex); ++#endif + stablehash = allocStrHashTable(); + symhash = allocStrHashTable(); + +@@ -1127,6 +1141,15 @@ + # 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 ); + # endif + + #if defined(x86_64_HOST_ARCH) +@@ -1147,6 +1170,19 @@ + #endif + } + ++void ++exitLinker( void ) { ++#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) ++ if (linker_init_done == 1) { ++ regfree(&re_invalid); ++ regfree(&re_realso); ++#ifdef THREADED_RTS ++ closeMutex(&dl_mutex); ++#endif ++ } ++#endif ++} ++ + /* ----------------------------------------------------------------------------- + * Loading DLL or .so dynamic libraries + * ----------------------------------------------------------------------------- +@@ -1182,29 +1218,112 @@ + static OpenedDLL* opened_dlls = NULL; + #endif + +-const char * +-addDLL( char *dll_name ) +-{ + # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) +- /* ------------------- ELF DLL loader ------------------- */ +- void *hdl; +- const char *errmsg; + +- initLinker(); ++static char * ++internal_dlopen(const char *dll_name) ++{ ++ void *hdl; ++ char *errmsg, *errmsg_copy; + + // omitted: RTLD_NOW + // see http://www.haskell.org/pipermail/cvs-ghc/2007-September/038570.html +- hdl= dlopen(dll_name, RTLD_LAZY | RTLD_GLOBAL); ++ IF_DEBUG(linker, ++ debugBelch("internal_dlopen: dll_name = '%s'\n", dll_name)); + ++ //-------------- Begin critical section ------------------ ++ // This critical section is necessary because dlerror() is not ++ // required to be reentrant (see POSIX -- IEEE Std 1003.1-2008) ++ // Also, the error message returned must be copied to preserve it ++ // (see POSIX also) ++ ++ ACQUIRE_LOCK(&dl_mutex); ++ hdl = dlopen(dll_name, RTLD_LAZY | RTLD_GLOBAL); ++ ++ errmsg = NULL; + if (hdl == NULL) { + /* dlopen failed; return a ptr to the error msg. */ + errmsg = dlerror(); + if (errmsg == NULL) errmsg = "addDLL: unknown error"; +- return errmsg; +- } else { ++ errmsg_copy = stgMallocBytes(strlen(errmsg)+1, "addDLL"); ++ strcpy(errmsg_copy, errmsg); ++ errmsg = errmsg_copy; ++ } ++ RELEASE_LOCK(&dl_mutex); ++ //--------------- End critical section ------------------- ++ ++ return errmsg; ++} ++# endif ++ ++const char * ++addDLL( char *dll_name ) ++{ ++# if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) ++ /* ------------------- ELF DLL loader ------------------- */ ++ ++#define NMATCH 5 ++ regmatch_t match[NMATCH]; ++ char *errmsg; ++ FILE* fp; ++ size_t match_length; ++#define MAXLINE 1000 ++ char line[MAXLINE]; ++ int result; ++ ++ initLinker(); ++ ++ IF_DEBUG(linker, debugBelch("addDLL: dll_name = '%s'\n", dll_name)); ++ errmsg = internal_dlopen(dll_name); ++ ++ if (errmsg == NULL) { + return NULL; + } +- /*NOTREACHED*/ ++ ++ // GHC Trac ticket #2615 ++ // On some systems (e.g., Gentoo Linux) dynamic files (e.g. libc.so) ++ // contain linker scripts rather than ELF-format object code. This ++ // code handles the situation by recognizing the real object code ++ // file name given in the linker script. ++ // ++ // If an "invalid ELF header" error occurs, it is assumed that the ++ // .so file contains a linker script instead of ELF object code. ++ // In this case, the code looks for the GROUP ( ... ) linker ++ // directive. If one is found, the first file name inside the ++ // parentheses is treated as the name of a dynamic library and the ++ // code attempts to dlopen that file. If this is also unsuccessful, ++ // an error message is returned. ++ ++ // see if the error message is due to an invalid ELF header ++ IF_DEBUG(linker, debugBelch("errmsg = '%s'\n", errmsg)); ++ result = regexec(&re_invalid, errmsg, (size_t) NMATCH, match, 0); ++ IF_DEBUG(linker, debugBelch("result = %i\n", result)); ++ if (result == 0) { ++ // success -- try to read the named file as a linker script ++ match_length = (size_t) stg_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 ++ IF_DEBUG(linker, debugBelch ("file name = '%s'\n", line)); ++ if ((fp = fopen(line, "r")) == NULL) { ++ return errmsg; // return original error if open fails ++ } ++ // try to find a GROUP ( ... ) command ++ while (fgets(line, MAXLINE, fp) != NULL) { ++ IF_DEBUG(linker, debugBelch("input line = %s", line)); ++ if (regexec(&re_realso, line, (size_t) NMATCH, match, 0) == 0) { ++ // success -- try to dlopen the first named file ++ IF_DEBUG(linker, debugBelch("match%s\n","")); ++ line[match[1].rm_eo] = '\0'; ++ errmsg = internal_dlopen(line+match[1].rm_so); ++ break; ++ } ++ // if control reaches here, no GROUP ( ... ) directive was found ++ // and the original error message is returned to the caller ++ } ++ fclose(fp); ++ } ++ return errmsg; + + # elif defined(OBJFORMAT_PEi386) + /* ------------------- Win32 DLL loader ------------------- */ +@@ -4195,7 +4314,7 @@ + i++; + } + #endif +- else ++ else + { + barf ("Don't know how to handle this Mach-O " + "scattered relocation entry: " +@@ -4204,7 +4323,7 @@ + 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) +@@ -4250,8 +4369,8 @@ + "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) */ + { +diff -rN -u old-ghc/rts/LinkerInternals.h new-ghc/rts/LinkerInternals.h +--- old-ghc/rts/LinkerInternals.h 2010-07-28 22:59:33.532759118 +0200 ++++ new-ghc/rts/LinkerInternals.h 2010-07-28 22:59:34.854758341 +0200 +@@ -109,4 +109,6 @@ + + extern ObjectCode *objects; + ++void exitLinker( void ); ++ + #endif /* LINKERINTERNALS_H */ +diff -rN -u old-ghc/rts/RtsStartup.c new-ghc/rts/RtsStartup.c +--- old-ghc/rts/RtsStartup.c 2010-07-28 22:59:33.537758009 +0200 ++++ new-ghc/rts/RtsStartup.c 2010-07-28 22:59:34.859758558 +0200 +@@ -34,6 +34,7 @@ + #include "Profiling.h" + #include "Timer.h" + #include "Globals.h" ++void exitLinker( void ); // there is no Linker.h file to include + + #if defined(RTS_GTK_FRONTPANEL) + #include "FrontPanel.h" +@@ -388,6 +389,9 @@ + /* free shared Typeable store */ + exitGlobalStore(); + ++ /* free linker data */ ++ exitLinker(); ++ + /* free file locking tables, if necessary */ + #if !defined(mingw32_HOST_OS) + freeFileLocking(); |