summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-09-09 18:37:24 -0400
committerBen Gamari <ben@well-typed.com>2021-10-06 08:47:38 +0000
commit51ad6f86ff2ceeee9acffbaa03ca5ad15a4bf3c8 (patch)
treea1cf5562408fef887fc40695422ef3fd13475c34
parentf18bf614b4e45704d190f82abc3c85e6375c846d (diff)
downloadhaskell-51ad6f86ff2ceeee9acffbaa03ca5ad15a4bf3c8.tar.gz
rts/linker: Introduce a notion of strong symbols
-rw-r--r--rts/Linker.c35
-rw-r--r--rts/LinkerInternals.h10
-rw-r--r--rts/RtsSymbols.c30
-rw-r--r--rts/RtsSymbols.h2
4 files changed, 51 insertions, 26 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 05d9f5b53b..8f4a8cceff 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -266,7 +266,7 @@ int ghciInsertSymbolTable(
StrHashTable *table,
const SymbolName* key,
SymbolAddr* data,
- HsBool weak,
+ SymStrength strength,
ObjectCode *owner)
{
RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
@@ -275,18 +275,27 @@ int ghciInsertSymbolTable(
pinfo = stgMallocBytes(sizeof (*pinfo), "ghciInsertToSymbolTable");
pinfo->value = data;
pinfo->owner = owner;
- pinfo->weak = weak;
+ pinfo->strength = strength;
insertStrHashTable(table, key, pinfo);
return 1;
}
- else if (weak && data && pinfo->weak && !pinfo->value)
+ else if (pinfo->strength == STRENGTH_STRONG)
+ {
+ /* The existing symbol is strong meaning we must never override it */
+ IF_DEBUG(linker, debugBelch("%s is already defined as a strong symbol; ignoring redefinition...", key));
+ return 1;
+ }
+ else if (strength == STRENGTH_WEAK &&
+ data &&
+ pinfo->strength == STRENGTH_WEAK &&
+ !pinfo->value)
{
/* The existing symbol is weak with a zero value; replace it with the new symbol. */
pinfo->value = data;
pinfo->owner = owner;
return 1;
}
- else if (weak)
+ else if (strength == STRENGTH_WEAK)
{
return 1; /* weak symbol, because the symbol is weak, data = 0 and we
already know of another copy throw this one away.
@@ -296,12 +305,12 @@ int ghciInsertSymbolTable(
This also preserves the semantics of linking against
the first symbol we find. */
}
- else if (pinfo->weak && !weak) /* weak symbol is in the table */
+ else if (pinfo->strength == STRENGTH_WEAK && strength != STRENGTH_WEAK) /* weak symbol is in the table */
{
/* override the weak definition with the non-weak one */
pinfo->value = data;
pinfo->owner = owner;
- pinfo->weak = HS_BOOL_FALSE;
+ pinfo->strength = strength;
return 1;
}
else if ( pinfo->owner
@@ -322,7 +331,7 @@ int ghciInsertSymbolTable(
if (owner && (owner->status == OBJECT_NEEDED || owner->status == OBJECT_RESOLVED)) {
pinfo->value = data;
pinfo->owner = owner;
- pinfo->weak = weak;
+ pinfo->strength = strength;
}
return 1;
@@ -376,10 +385,11 @@ HsBool ghciLookupSymbolInfo(StrHashTable *table,
*result = NULL;
return HS_BOOL_FALSE;
}
- if (pinfo->weak)
+ if (pinfo->strength == STRENGTH_WEAK) {
IF_DEBUG(linker, debugBelch("lookupSymbolInfo: promoting %s\n", key));
- /* Once it's looked up, it can no longer be overridden */
- pinfo->weak = HS_BOOL_FALSE;
+ /* Once it's looked up, it can no longer be overridden */
+ pinfo->strength = STRENGTH_NORMAL;
+ }
*result = pinfo;
return HS_BOOL_TRUE;
@@ -412,7 +422,6 @@ void initLinker (void)
void
initLinker_ (int retain_cafs)
{
- RtsSymbolVal *sym;
#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
int compileResult;
#endif
@@ -441,10 +450,10 @@ initLinker_ (int retain_cafs)
symhash = allocStrHashTable();
/* populate the symbol table with stuff from the RTS */
- for (sym = rtsSyms; sym->lbl != NULL; sym++) {
+ for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) {
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
symhash, sym->lbl, sym->addr,
- sym->weak, NULL)) {
+ sym->strength, NULL)) {
barf("ghciInsertSymbolTable failed");
}
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 167a14202d..7058ad355b 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -345,6 +345,12 @@ extern Mutex dl_mutex;
/* Type of the initializer */
typedef void (*init_t) (int argc, char **argv, char **env);
+typedef enum _SymStrength {
+ STRENGTH_NORMAL,
+ STRENGTH_WEAK,
+ STRENGTH_STRONG,
+} SymStrength;
+
/* SymbolInfo tracks a symbol's address, the object code from which
it originated, and whether or not it's weak.
@@ -360,7 +366,7 @@ typedef void (*init_t) (int argc, char **argv, char **env);
typedef struct _RtsSymbolInfo {
SymbolAddr* value;
ObjectCode *owner;
- HsBool weak;
+ SymStrength strength;
} RtsSymbolInfo;
void exitLinker( void );
@@ -389,7 +395,7 @@ int ghciInsertSymbolTable(
StrHashTable *table,
const SymbolName* key,
SymbolAddr* data,
- HsBool weak,
+ SymStrength weak,
ObjectCode *owner);
/* Lock-free version of lookupSymbol. When 'dependent' is not NULL, adds it as a
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index e8c60d2c07..0a821de64b 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -81,6 +81,16 @@
#endif
/*
+ * Note [Strong symbols]
+ * ~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The notion of a *weak* symbol is fairly common in linking: a symbol is weak
+ * if it is declared but not defined, allowing it to be defined by an object
+ * which is loaded later. GHC generalizes this notion, allowing symbol
+ * definitions to be declared as *strong*. A strong symbol is one which will
+ * silently supercede definitions of the same name by later objects.
+ */
+/*
* Note [Symbols for MinGW's printf]
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
@@ -150,9 +160,9 @@
/* ^^ Need to figure out why this is needed. */ \
/* See Note [_iob_func symbol] */ \
RTS_WIN64_ONLY(SymI_HasProto_redirect( \
- __imp___acrt_iob_func, __rts_iob_func, true)) \
+ __imp___acrt_iob_func, __rts_iob_func, STRENGTH_WEAK)) \
RTS_WIN32_ONLY(SymI_HasProto_redirect( \
- __imp____acrt_iob_func, __rts_iob_func, true)) \
+ __imp____acrt_iob_func, __rts_iob_func, STRENGTH_WEAK)) \
SymI_HasProto(__mingw_vsnwprintf) \
/* ^^ Need to figure out why this is needed. */ \
SymI_HasProto(__mingw_vfprintf) \
@@ -1059,7 +1069,7 @@
#define SymE_HasProto(vvv) SymI_HasProto(vvv)
#endif
#define SymI_HasProto(vvv) /**/
-#define SymI_HasProto_redirect(vvv,xxx,weak) /**/
+#define SymI_HasProto_redirect(vvv,xxx,strength) /**/
#define SymI_HasProto_deprecated(vvv) /**/
RTS_SYMBOLS
RTS_RET_SYMBOLS
@@ -1080,11 +1090,11 @@ RTS_LIBFFI_SYMBOLS
#undef SymE_NeedsDataProto
#define SymI_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)(&(vvv)), false },
+ (void*)(&(vvv)), STRENGTH_NORMAL },
#define SymI_HasDataProto(vvv) \
SymI_HasProto(vvv)
#define SymE_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)DLL_IMPORT_DATA_REF(vvv), false },
+ (void*)DLL_IMPORT_DATA_REF(vvv), STRENGTH_NORMAL },
#define SymE_HasDataProto(vvv) \
SymE_HasProto(vvv)
@@ -1095,9 +1105,9 @@ RTS_LIBFFI_SYMBOLS
// SymI_HasProto_redirect allows us to redirect references to one symbol to
// another symbol. See newCAF/newRetainedCAF/newGCdCAF for an example.
-#define SymI_HasProto_redirect(vvv,xxx,weak) \
+#define SymI_HasProto_redirect(vvv,xxx,strength) \
{ MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)(&(xxx)), weak },
+ (void*)(&(xxx)), strength },
// SymI_HasProto_deprecated allows us to redirect references from their deprecated
// names to the undeprecated ones. e.g. access -> _access.
@@ -1107,7 +1117,7 @@ RTS_LIBFFI_SYMBOLS
// define them, since on Windows these functions shouldn't be in the top level
// namespace, but we have them for POSIX compatibility.
#define SymI_HasProto_deprecated(vvv) \
- { #vvv, (void*)0xBAADF00D, true },
+ { #vvv, (void*)0xBAADF00D, STRENGTH_WEAK },
RtsSymbolVal rtsSyms[] = {
RTS_SYMBOLS
@@ -1124,7 +1134,7 @@ RtsSymbolVal rtsSyms[] = {
// dyld stub code contains references to this,
// but it should never be called because we treat
// lazy pointers as nonlazy.
- { "dyld_stub_binding_helper", (void*)0xDEADBEEF, false },
+ { "dyld_stub_binding_helper", (void*)0xDEADBEEF, STRENGTH_NORMAL },
#endif
- { 0, 0, false } /* sentinel */
+ { 0, 0, STRENGTH_NORMAL } /* sentinel */
};
diff --git a/rts/RtsSymbols.h b/rts/RtsSymbols.h
index b17c56e0dd..0efc16be0f 100644
--- a/rts/RtsSymbols.h
+++ b/rts/RtsSymbols.h
@@ -21,7 +21,7 @@
typedef struct _RtsSymbolVal {
const SymbolName* lbl;
SymbolAddr* addr;
- bool weak;
+ SymStrength strength;
} RtsSymbolVal;
extern RtsSymbolVal rtsSyms[];