diff options
author | Ben Gamari <ben@smart-cactus.org> | 2021-09-09 18:37:24 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-10-12 19:16:40 -0400 |
commit | 08aa7a1d2bb046398a2fc4c236b4267aa83244be (patch) | |
tree | b384e000a5ffca310e404aa5ec458aa2cce38762 | |
parent | 9ebda74ec5331911881d734b21fbb31c00a0a22f (diff) | |
download | haskell-08aa7a1d2bb046398a2fc4c236b4267aa83244be.tar.gz |
rts/linker: Introduce a notion of strong symbols
-rw-r--r-- | rts/Linker.c | 35 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 10 | ||||
-rw-r--r-- | rts/RtsSymbols.c | 30 | ||||
-rw-r--r-- | rts/RtsSymbols.h | 2 |
4 files changed, 51 insertions, 26 deletions
diff --git a/rts/Linker.c b/rts/Linker.c index bfbf8338af..9c1852d91c 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[]; |