You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gentoo-overlay/dev-lang/ghc/files/ghc-7.6.3-trac-3333-weak-sy...

388 lines
14 KiB

The patch set adds support for weak symbols to ghci.
For gentoo it fixes nonworking ghci / template haskell
for package base.
Steps to reproduce:
1. CFLAGS=-Os emerge ghc
2. ghci -package base
Loading package base ... linking ... ghc: /usr/lib64/ghc-7.6.3/base-4.6.0.1/HSbase-4.6.0.1.o: unknown symbol `stat'
When built with -O2 weak 'stat' resolved to '__xstat' and we don't see any errors.
But on olwer optimization levels 'stat' remains.
Patches-by: akio
Gentoo-bug: http://bugs.gentoo.org/452442
Upstream-bug: http://ghc.haskell.org/trac/ghc/ticket/3333
From 500d57d3a18412c78cab5abc4d91f1564edc964d Mon Sep 17 00:00:00 2001
From: Takano Akio <aljee@hyper.cx>
Date: Sat, 29 Dec 2012 11:47:22 +0900
Subject: [PATCH 1/3] Linker.c: remove stablehash, which is no longer used
---
includes/rts/Linker.h | 3 ---
rts/Linker.c | 31 ++-----------------------------
2 files changed, 2 insertions(+), 32 deletions(-)
diff --git a/includes/rts/Linker.h b/includes/rts/Linker.h
index e900e85..d20ebc2 100644
--- a/includes/rts/Linker.h
+++ b/includes/rts/Linker.h
@@ -23,9 +23,6 @@ typedef char pathchar;
/* initialize the object linker */
void initLinker( void );
-/* insert a stable symbol in the hash table */
-void insertStableSymbol(pathchar* obj_name, char* key, StgPtr data);
-
/* insert a symbol in the hash table */
void insertSymbol(pathchar* obj_name, char* key, void* data);
diff --git a/rts/Linker.c b/rts/Linker.c
index fa1de89..513fe3f 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -30,1 +30,0 @@
-#include "Stable.h"
@@ -150,9 +149,6 @@ int dynamicByDefault = 0;
/* Hash table mapping symbol names to Symbol */
static /*Str*/HashTable *symhash;
-/* Hash table mapping symbol names to StgStablePtr */
-static /*Str*/HashTable *stablehash;
-
/* List of currently loaded objects */
ObjectCode *objects = NULL; /* initially empty */
@@ -1126,1 +1126,0 @@ typedef struct _RtsSymbolVal {
- SymI_HasProto(insertStableSymbol) \
@@ -1488,7 +1483,6 @@ initLinker( void )
#if defined(THREADED_RTS) && (defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO))
initMutex(&dl_mutex);
#endif
- stablehash = allocStrHashTable();
symhash = allocStrHashTable();
/* populate the symbol table with stuff from the RTS */
@@ -1817,17 +1811,6 @@ error:
}
/* -----------------------------------------------------------------------------
- * insert a stable symbol in the hash table
- */
-
-void
-insertStableSymbol(pathchar* obj_name, char* key, StgPtr p)
-{
- ghciInsertStrHashTable(obj_name, stablehash, key, getStablePtr(p));
-}
-
-
-/* -----------------------------------------------------------------------------
* insert a symbol in the hash table
*/
void
@@ -4749,8 +4732,6 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
#ifdef i386_HOST_ARCH
Elf_Addr value;
#endif
- StgStablePtr stablePtr;
- StgPtr stableVal;
#ifdef arm_HOST_ARCH
int is_target_thm=0, T=0;
#endif
@@ -4773,16 +4754,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
} else {
symbol = strtab + sym.st_name;
- stablePtr = (StgStablePtr)lookupHashTable(stablehash, (StgWord)symbol);
- if (NULL == stablePtr) {
- /* No, so look up the name in our global table. */
- S_tmp = lookupSymbol( symbol );
- S = (Elf_Addr)S_tmp;
- } else {
- stableVal = deRefStablePtr( stablePtr );
- S_tmp = stableVal;
- S = (Elf_Addr)S_tmp;
- }
+ S_tmp = lookupSymbol( symbol );
+ S = (Elf_Addr)S_tmp;
}
if (!S) {
errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol);
--
1.7.9.5
From 2e5e0f7a90dd390adc5ae5fb2a3bc6e879aa42d6 Mon Sep 17 00:00:00 2001
From: Takano Akio <aljee@hyper.cx>
Date: Sat, 29 Dec 2012 11:59:34 +0900
Subject: [PATCH 2/3] ghci: add support for ELF weak symbols
---
rts/Linker.c | 102 ++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 78 insertions(+), 24 deletions(-)
diff --git a/rts/Linker.c b/rts/Linker.c
index 513fe3f..5105085 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -146,7 +146,13 @@ int dynamicByDefault = 1;
int dynamicByDefault = 0;
#endif
-/* Hash table mapping symbol names to Symbol */
+typedef struct _RtsSymbolInfo {
+ void *value;
+ const ObjectCode *owner;
+ HsBool weak;
+} RtsSymbolInfo;
+
+/* Hash table mapping symbol names to RtsSymbolInfo */
static /*Str*/HashTable *symhash;
/* List of currently loaded objects */
@@ -1415,15 +1421,31 @@ static RtsSymbolVal rtsSyms[] = {
* Insert symbols into hash tables, checking for duplicates.
*/
-static void ghciInsertStrHashTable ( pathchar* obj_name,
- HashTable *table,
- char* key,
- void *data
- )
+static void ghciInsertSymbolTable(
+ pathchar* obj_name,
+ HashTable *table,
+ char* key,
+ void *data,
+ HsBool weak,
+ ObjectCode *owner)
{
- if (lookupHashTable(table, (StgWord)key) == NULL)
+ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
+ if (!pinfo) /* new entry */
+ {
+ pinfo = stgMallocBytes(sizeof (*pinfo), "ghciInsertToSymbolTable");
+ pinfo->value = data;
+ pinfo->owner = owner;
+ pinfo->weak = weak;
+ insertStrHashTable(table, key, pinfo);
+ return;
+ } else if ((!pinfo->weak || pinfo->value) && weak) {
+ return; /* duplicate weak symbol, throw it away */
+ } else if (pinfo->weak) /* weak symbol is in the table */
{
- insertStrHashTable(table, (StgWord)key, data);
+ /* override the weak definition with the non-weak one */
+ pinfo->value = data;
+ pinfo->owner = owner;
+ pinfo->weak = HS_BOOL_FALSE;
return;
}
debugBelch(
@@ -1444,6 +1466,32 @@ static void ghciInsertStrHashTable ( pathchar* obj_name,
);
stg_exit(1);
}
+
+static HsBool ghciLookupSymbolTable(HashTable *table,
+ const char *key, void **result)
+{
+ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
+ if (!pinfo) {
+ *result = NULL;
+ return HS_BOOL_FALSE;
+ }
+ if (pinfo->weak)
+ IF_DEBUG(linker, debugBelch("lookup: promoting %s\n", key));
+ /* Once it's looked up, it can no longer be overridden */
+ pinfo->weak = HS_BOOL_FALSE;
+
+ *result = pinfo->value;
+ return HS_BOOL_TRUE;
+}
+
+static void ghciRemoveSymbolTable(HashTable *table, const char *key,
+ ObjectCode *owner)
+{
+ RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
+ if (!pinfo || owner != pinfo->owner) return;
+ removeStrHashTable(table, key, NULL);
+ stgFree(pinfo);
+}
/* -----------------------------------------------------------------------------
* initialize the object linker
*/
@@ -1487,8 +1535,8 @@ initLinker( void )
/* populate the symbol table with stuff from the RTS */
for (sym = rtsSyms; sym->lbl != NULL; sym++) {
- ghciInsertStrHashTable(WSTR("(GHCi built-in symbols)"),
- symhash, sym->lbl, sym->addr);
+ ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
+ symhash, sym->lbl, sym->addr, HS_BOOL_FALSE, NULL);
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
}
# if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH)
@@ -1816,7 +1864,7 @@ error:
void
insertSymbol(pathchar* obj_name, char* key, void* data)
{
- ghciInsertStrHashTable(obj_name, symhash, key, data);
+ ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE, NULL);
}
/* -----------------------------------------------------------------------------
@@ -1829,9 +1877,8 @@ lookupSymbol( char *lbl )
IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s\n", lbl));
initLinker() ;
ASSERT(symhash != NULL);
- val = lookupStrHashTable(symhash, lbl);
- if (val == NULL) {
+ if (!ghciLookupSymbolTable(symhash, lbl, &val)) {
IF_DEBUG(linker, debugBelch("lookupSymbol: symbol not found\n"));
# if defined(OBJFORMAT_ELF)
return internal_dlsym(dl_prog_handle, lbl);
@@ -1903,7 +1950,7 @@ void ghci_enquire ( char* addr )
if (sym == NULL) continue;
a = NULL;
if (a == NULL) {
- a = lookupStrHashTable(symhash, sym);
+ ghciLookupSymbolTable(symhash, sym, (void **)&a);
}
if (a == NULL) {
// debugBelch("ghci_enquire: can't find %s\n", sym);
@@ -2715,7 +2762,7 @@ unloadObj( pathchar *path )
int i;
for (i = 0; i < oc->n_symbols; i++) {
if (oc->symbols[i] != NULL) {
- removeStrHashTable(symhash, oc->symbols[i], NULL);
+ ghciRemoveSymbolTable(symhash, oc->symbols[i], oc);
}
}
}
@@ -3802,7 +3849,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
ASSERT(i >= 0 && i < oc->n_symbols);
/* cstring_from_COFF_symbol_name always succeeds. */
oc->symbols[i] = (char*)sname;
- ghciInsertStrHashTable(oc->fileName, symhash, (char*)sname, addr);
+ ghciInsertSymbolTable(oc->fileName, symhash, (char*)sname, addr,
+ HS_BOOL_FALSE, oc);
} else {
# if 0
debugBelch(
@@ -4595,6 +4643,7 @@ ocGetNames_ELF ( ObjectCode* oc )
for (j = 0; j < nent; j++) {
char isLocal = FALSE; /* avoids uninit-var warning */
+ HsBool isWeak = HS_BOOL_FALSE;
char* ad = NULL;
char* nm = strtab + stab[j].st_name;
int secno = stab[j].st_shndx;
@@ -4615,6 +4664,7 @@ ocGetNames_ELF ( ObjectCode* oc )
else
if ( ( ELF_ST_BIND(stab[j].st_info)==STB_GLOBAL
|| ELF_ST_BIND(stab[j].st_info)==STB_LOCAL
+ || ELF_ST_BIND(stab[j].st_info)==STB_WEAK
)
/* and not an undefined symbol */
&& stab[j].st_shndx != SHN_UNDEF
@@ -4638,7 +4688,8 @@ ocGetNames_ELF ( ObjectCode* oc )
ad = ehdrC + shdr[ secno ].sh_offset + stab[j].st_value;
if (ELF_ST_BIND(stab[j].st_info)==STB_LOCAL) {
isLocal = TRUE;
- } else {
+ isWeak = FALSE;
+ } else { /* STB_GLOBAL or STB_WEAK */
#ifdef ELF_FUNCTION_DESC
/* dlsym() and the initialisation table both give us function
* descriptors, so to be consistent we store function descriptors
@@ -4649,6 +4700,7 @@ ocGetNames_ELF ( ObjectCode* oc )
IF_DEBUG(linker,debugBelch( "addOTabName(GLOB): %10p %s %s\n",
ad, oc->fileName, nm ));
isLocal = FALSE;
+ isWeak = (ELF_ST_BIND(stab[j].st_info)==STB_WEAK);
}
}
@@ -4661,7 +4713,7 @@ ocGetNames_ELF ( ObjectCode* oc )
if (isLocal) {
/* Ignore entirely. */
} else {
- ghciInsertStrHashTable(oc->fileName, symhash, nm, ad);
+ ghciInsertSymbolTable(oc->fileName, symhash, nm, ad, isWeak, oc);
}
} else {
/* Skip. */
@@ -6306,11 +6358,13 @@ ocGetNames_MachO(ObjectCode* oc)
else
{
IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting %s\n", nm));
- ghciInsertStrHashTable(oc->fileName, symhash, nm,
+ ghciInsertSymbolTable(oc->fileName, symhash, nm,
image
+ sections[nlist[i].n_sect-1].offset
- sections[nlist[i].n_sect-1].addr
- + nlist[i].n_value);
+ + nlist[i].n_value,
+ HS_BOOL_FALSE,
+ oc);
oc->symbols[curSymbol++] = nm;
}
}
@@ -6341,8 +6395,8 @@ ocGetNames_MachO(ObjectCode* oc)
nlist[i].n_value = commonCounter;
IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
- ghciInsertStrHashTable(oc->fileName, symhash, nm,
- (void*)commonCounter);
+ ghciInsertSymbolTable(oc->fileName, symhash, nm,
+ (void*)commonCounter, HS_BOOL_FALSE, oc);
oc->symbols[curSymbol++] = nm;
commonCounter += sz;
@@ -6466,7 +6520,7 @@ machoInitSymbolsWithoutUnderscore(void)
#undef SymI_NeedsProto
#define SymI_NeedsProto(x) \
- ghciInsertStrHashTable("(GHCi built-in symbols)", symhash, #x, *p++);
+ ghciInsertSymbolTable("(GHCi built-in symbols)", symhash, #x, *p++, HS_BOOL_FALSE, NULL);
RTS_MACHO_NOUNDERLINE_SYMBOLS
--
1.7.9.5
From 916d7713b34b529ae7ec24eaa836a4eaca7724fc Mon Sep 17 00:00:00 2001
From: Takano Akio <aljee@hyper.cx>
Date: Sun, 6 Jan 2013 17:51:19 +0900
Subject: [PATCH 3/3] Linker.c: add dso_handle to the symbol table
---
rts/Linker.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/rts/Linker.c b/rts/Linker.c
index 5105085..0b2bf63 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1542,6 +1542,13 @@ initLinker( void )
# if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH)
machoInitSymbolsWithoutUnderscore();
# endif
+ /* GCC defines a special symbol __dso_handle which is resolved to NULL if
+ referenced from a statically linked module. We need to mimic this, but
+ we cannot use NULL because we use it to mean nonexistent symbols. So we
+ use an arbitrary (hopefully unique) address here.
+ */
+ ghciInsertSymbolTable(WSTR("(GHCi special symbols)"),
+ symhash, "__dso_handle", (void *)0x12345687, HS_BOOL_FALSE, NULL);
# if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
# if defined(RTLD_DEFAULT)
--
1.7.9.5