in rts/Linker.c [254:359]
int ghciInsertSymbolTable(
pathchar* obj_name,
HashTable *table,
const SymbolName* key,
SymbolAddr* data,
HsBool weak,
ObjectCode *owner)
{
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 1;
}
else if (weak && data && pinfo->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)
{
return 1; /* weak symbol, because the symbol is weak, data = 0 and we
already know of another copy throw this one away.
or both weak symbols have a nonzero value. Keep the existing one.
This also preserves the semantics of linking against
the first symbol we find. */
}
else if (pinfo->weak && !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;
return 1;
}
else if ( pinfo->owner
&& pinfo->owner->status != OBJECT_RESOLVED
&& pinfo->owner->status != OBJECT_NEEDED)
{
/* If the other symbol hasn't been loaded or will be loaded and we want to
explicitly load the new one, we can just swap it out and load the one
that has been requested. If not, just keep the first one encountered.
Because the `symHash' table consists symbols we've also not loaded but
found during the initial scan this is safe to do. If however the existing
symbol has been loaded then it means we have a duplicate.
This is essentially emulating the behavior of a linker wherein it will always
link in object files that are .o file arguments, but only take object files
from archives as needed. */
if (owner && (owner->status == OBJECT_NEEDED || owner->status == OBJECT_RESOLVED)) {
pinfo->value = data;
pinfo->owner = owner;
pinfo->weak = weak;
}
return 1;
}
else if (pinfo->owner == owner)
{
/* If it's the same symbol, ignore. This makes ghciInsertSymbolTable idempotent */
return 1;
}
else if (owner && owner->status == OBJECT_LOADED)
{
/* If the duplicate symbol is just in state OBJECT_LOADED it means we're in discovery of an
member. It's not a real duplicate yet. If the Oc Becomes OBJECT_NEEDED then ocTryLoad will
call this function again to trigger the duplicate error. */
return 1;
}
pathchar* archiveName = NULL;
debugBelch(
"GHC runtime linker: fatal error: I found a duplicate definition for symbol\n"
" %s\n"
"whilst processing object file\n"
" %" PATH_FMT "\n"
"The symbol was previously defined in\n"
" %" PATH_FMT "\n"
"This could be caused by:\n"
" * Loading two different object files which export the same symbol\n"
" * Specifying the same object file twice on the GHCi command line\n"
" * An incorrect `package.conf' entry, causing some object to be\n"
" loaded twice.\n",
(char*)key,
obj_name,
pinfo->owner == NULL ? WSTR("(GHCi built-in symbols)") :
pinfo->owner->archiveMemberName ? archiveName = mkPath(pinfo->owner->archiveMemberName)
: pinfo->owner->fileName
);
if (archiveName)
{
stgFree(archiveName);
archiveName = NULL;
}
return 0;
}