summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2022-02-04 08:44:49 -0500
committerBen Gamari <ben@smart-cactus.org>2022-04-06 16:25:25 -0400
commitd286a55caebca8a4e5e73bbfeeb766e333271a09 (patch)
treed1c9c1dd3e34e2bd3661aae9719f094015799388
parent42bf7528559fb518092fef3902afb73af5de146e (diff)
downloadhaskell-d286a55caebca8a4e5e73bbfeeb766e333271a09.tar.gz
rts/linker: Preserve information about symbol types
As noted in #20978, the linker would previously handle overflowed relocations by creating a jump island. While this is fine in the case of code symbols, it's very much not okay in the case of data symbols. To fix this we must keep track of whether each symbol is code or data and relocate them appropriately. This patch takes the first step in this direction, adding a symbol type field to the linker's symbol table. It doesn't yet change relocation behavior to take advantage of this knowledge. Fixes #20978.
-rw-r--r--rts/Linker.c59
-rw-r--r--rts/LinkerInternals.h23
-rw-r--r--rts/RtsSymbols.c10
-rw-r--r--rts/RtsSymbols.h1
-rw-r--r--rts/include/rts/Linker.h2
-rw-r--r--rts/linker/Elf.c14
-rw-r--r--rts/linker/MachO.c24
-rw-r--r--rts/linker/PEi386.c32
-rw-r--r--rts/linker/PEi386.h2
-rw-r--r--rts/linker/elf_got.c2
10 files changed, 128 insertions, 41 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 43eff730b8..c1918ecbba 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -185,6 +185,17 @@ static void ghciRemoveSymbolTable(StrHashTable *table, const SymbolName* key,
stgFree(pinfo);
}
+static const char *
+symbolTypeString (SymType type)
+{
+ switch (type) {
+ case SYM_TYPE_CODE: return "code";
+ case SYM_TYPE_DATA: return "data";
+ case SYM_TYPE_INDIRECT_DATA: return "indirect-data";
+ default: barf("symbolTypeString: unknown symbol type");
+ }
+}
+
/* -----------------------------------------------------------------------------
* Insert symbols into hash tables, checking for duplicates.
*
@@ -212,6 +223,7 @@ int ghciInsertSymbolTable(
const SymbolName* key,
SymbolAddr* data,
SymStrength strength,
+ SymType type,
ObjectCode *owner)
{
RtsSymbolInfo *pinfo = lookupStrHashTable(table, key);
@@ -221,9 +233,20 @@ int ghciInsertSymbolTable(
pinfo->value = data;
pinfo->owner = owner;
pinfo->strength = strength;
+ pinfo->type = type;
insertStrHashTable(table, key, pinfo);
return 1;
}
+ else if (pinfo->type != type)
+ {
+ debugBelch("Symbol type mismatch.\n");
+ debugBelch("Symbol %s was defined by %" PATH_FMT " to be a %s symbol.\n",
+ key, obj_name, symbolTypeString(type));
+ debugBelch(" yet was defined by %" PATH_FMT " to be a %s symbol.\n",
+ pinfo->owner ? pinfo->owner->fileName : WSTR("<builtin>"),
+ symbolTypeString(pinfo->type));
+ return 1;
+ }
else if (pinfo->strength == STRENGTH_STRONG)
{
/* The existing symbol is strong meaning we must never override it */
@@ -398,7 +421,7 @@ initLinker_ (int retain_cafs)
for (const RtsSymbolVal *sym = rtsSyms; sym->lbl != NULL; sym++) {
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"),
symhash, sym->lbl, sym->addr,
- sym->strength, NULL)) {
+ sym->strength, sym->type, NULL)) {
barf("ghciInsertSymbolTable failed");
}
IF_DEBUG(linker, debugBelch("initLinker: inserting rts symbol %s, %p\n", sym->lbl, sym->addr));
@@ -408,7 +431,7 @@ initLinker_ (int retain_cafs)
if (! ghciInsertSymbolTable(WSTR("(GHCi built-in symbols)"), symhash,
MAYBE_LEADING_UNDERSCORE_STR("newCAF"),
retain_cafs ? newRetainedCAF : newGCdCAF,
- HS_BOOL_FALSE, NULL)) {
+ HS_BOOL_FALSE, SYM_TYPE_CODE, NULL)) {
barf("ghciInsertSymbolTable failed");
}
@@ -775,14 +798,14 @@ HsBool removeLibrarySearchPath(HsPtr dll_path_index)
}
/* -----------------------------------------------------------------------------
- * insert a symbol in the hash table
+ * insert a code symbol in the hash table
*
* Returns: 0 on failure, nonzero on success
*/
HsInt insertSymbol(pathchar* obj_name, SymbolName* key, SymbolAddr* data)
{
return ghciInsertSymbolTable(obj_name, symhash, key, data, HS_BOOL_FALSE,
- NULL);
+ SYM_TYPE_CODE, NULL);
}
/* -----------------------------------------------------------------------------
@@ -792,16 +815,16 @@ HsInt insertSymbol(pathchar* obj_name, SymbolName* key, SymbolAddr* data)
* symbol.
*/
#if defined(OBJFORMAT_PEi386)
-SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
+SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent, SymType *type)
{
(void)dependent; // TODO
ASSERT_LOCK_HELD(&linker_mutex);
- return lookupSymbol_PEi386(lbl);
+ return lookupSymbol_PEi386(lbl, type);
}
#else
-SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
+SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent, SymType *type)
{
ASSERT_LOCK_HELD(&linker_mutex);
IF_DEBUG(linker_verbose, debugBelch("lookupSymbol: looking up '%s'\n", lbl));
@@ -825,6 +848,11 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
# if defined(OBJFORMAT_ELF)
SymbolAddr *ret = internal_dlsym(lbl);
+ if (type) {
+ // We assume that the symbol is code since this is usually the case
+ // and dlsym doesn't tell us.
+ *type = SYM_TYPE_CODE;
+ }
// Generally the dynamic linker would define _DYNAMIC, which is
// supposed to point to various bits of dynamic linker state (see
@@ -835,6 +863,9 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
if (ret == NULL && strcmp(lbl, "_DYNAMIC") == 0) {
static void *RTS_DYNAMIC = NULL;
ret = (SymbolAddr *) &RTS_DYNAMIC;
+ if (type) {
+ *type = SYM_TYPE_DATA;
+ }
}
return ret;
# elif defined(OBJFORMAT_MACHO)
@@ -848,6 +879,11 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
IF_DEBUG(linker, debugBelch("lookupSymbol: looking up %s with dlsym\n",
lbl));
CHECK(lbl[0] == '_');
+ if (type) {
+ // We assume that the symbol is code since this is usually the case
+ // and dlsym doesn't tell us.
+ *type = SYM_TYPE_CODE;
+ }
return internal_dlsym(lbl + 1);
# else
@@ -857,6 +893,10 @@ SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent)
static void *RTS_NO_FINI = NULL;
if (strcmp(lbl, "__fini_array_end") == 0) { return (SymbolAddr *) &RTS_NO_FINI; }
if (strcmp(lbl, "__fini_array_start") == 0) { return (SymbolAddr *) &RTS_NO_FINI; }
+ if (type) {
+ // This is an assumption
+ *type = pinfo->type;
+ }
if (dependent) {
// Add dependent as symbol's owner's dependency
@@ -945,7 +985,7 @@ SymbolAddr* lookupSymbol( SymbolName* lbl )
ACQUIRE_LOCK(&linker_mutex);
// NULL for "don't add dependent". When adding a dependency we call
// lookupDependentSymbol directly.
- SymbolAddr* r = lookupDependentSymbol(lbl, NULL);
+ SymbolAddr* r = lookupDependentSymbol(lbl, NULL, NULL);
if (!r) {
errorBelch("^^ Could not load '%s', dependency unresolved. "
"See top entry above.\n", lbl);
@@ -1562,7 +1602,8 @@ int ocTryLoad (ObjectCode* oc) {
if ( symbol.name
&& !ghciInsertSymbolTable(oc->fileName, symhash, symbol.name,
symbol.addr,
- isSymbolWeak(oc, symbol.name), oc)) {
+ isSymbolWeak(oc, symbol.name),
+ symbol.type, oc)) {
return 0;
}
}
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index eb76a979bc..61c054363f 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -38,6 +38,20 @@ typedef char SymbolName;
typedef struct _ObjectCode ObjectCode;
typedef struct _Section Section;
+/*
+ * Note [Processing overflowed relocations]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * TODO
+ */
+
+/* What kind of thing a symbol identifies. We need to know this to determine how
+ * to process overflowing relocations. See Note [Processing overflowed relocations]. */
+typedef enum _SymType {
+ SYM_TYPE_CODE, /* the symbol is a function and can be relocated via a jump island */
+ SYM_TYPE_DATA, /* the symbol is data */
+} SymType;
+
+
#if defined(OBJFORMAT_ELF)
# include "linker/ElfTypes.h"
#elif defined(OBJFORMAT_PEi386)
@@ -55,6 +69,7 @@ typedef struct _Symbol
{
SymbolName *name;
SymbolAddr *addr;
+ SymType type;
} Symbol_t;
typedef struct NativeCodeRange_ {
@@ -339,7 +354,7 @@ extern Mutex linker_mutex;
#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
extern Mutex dl_mutex;
#endif
-#endif
+#endif /* THREADED_RTS */
/* Type of the initializer */
typedef void (*init_t) (int argc, char **argv, char **env);
@@ -366,6 +381,7 @@ typedef struct _RtsSymbolInfo {
SymbolAddr* value;
ObjectCode *owner;
SymStrength strength;
+ SymType type;
} RtsSymbolInfo;
void exitLinker( void );
@@ -390,11 +406,12 @@ int ghciInsertSymbolTable(
const SymbolName* key,
SymbolAddr* data,
SymStrength weak,
+ SymType type,
ObjectCode *owner);
/* Lock-free version of lookupSymbol. When 'dependent' is not NULL, adds it as a
- * dependent to the owner of the symbol. */
-SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent);
+ * dependent to the owner of the symbol. The type of the symbol is stored in 'type'. */
+SymbolAddr* lookupDependentSymbol (SymbolName* lbl, ObjectCode *dependent, SymType *type);
/* Perform TLSGD symbol lookup returning the address of the resulting GOT entry,
* which in this case holds the module id and the symbol offset. */
diff --git a/rts/RtsSymbols.c b/rts/RtsSymbols.c
index 5f97568b62..400e3122bc 100644
--- a/rts/RtsSymbols.c
+++ b/rts/RtsSymbols.c
@@ -1127,11 +1127,11 @@ RTS_LIBFFI_SYMBOLS
#undef SymE_NeedsDataProto
#define SymI_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)(&(vvv)), STRENGTH_NORMAL },
+ (void*)(&(vvv)), STRENGTH_NORMAL, SYM_TYPE_CODE },
#define SymI_HasDataProto(vvv) \
SymI_HasProto(vvv)
#define SymE_HasProto(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)DLL_IMPORT_DATA_REF(vvv), STRENGTH_NORMAL },
+ (void*)DLL_IMPORT_DATA_REF(vvv), STRENGTH_NORMAL, SYM_TYPE_CODE },
#define SymE_HasDataProto(vvv) \
SymE_HasProto(vvv)
@@ -1144,7 +1144,7 @@ RTS_LIBFFI_SYMBOLS
// another symbol. See newCAF/newRetainedCAF/newGCdCAF for an example.
#define SymI_HasProto_redirect(vvv,xxx,strength) \
{ MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
- (void*)(&(xxx)), strength },
+ (void*)(&(xxx)), strength, SYM_TYPE_CODE },
// SymI_HasProto_deprecated allows us to redirect references from their deprecated
// names to the undeprecated ones. e.g. access -> _access.
@@ -1154,7 +1154,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, STRENGTH_WEAK },
+ { #vvv, (void*)0xBAADF00D, STRENGTH_WEAK, SYM_TYPE_CODE },
RtsSymbolVal rtsSyms[] = {
RTS_SYMBOLS
@@ -1174,5 +1174,5 @@ RtsSymbolVal rtsSyms[] = {
// lazy pointers as nonlazy.
{ "dyld_stub_binding_helper", (void*)0xDEADBEEF, STRENGTH_NORMAL },
#endif
- { 0, 0, STRENGTH_NORMAL } /* sentinel */
+ { 0, 0, STRENGTH_NORMAL, SYM_TYPE_CODE } /* sentinel */
};
diff --git a/rts/RtsSymbols.h b/rts/RtsSymbols.h
index 0efc16be0f..44760066db 100644
--- a/rts/RtsSymbols.h
+++ b/rts/RtsSymbols.h
@@ -22,6 +22,7 @@ typedef struct _RtsSymbolVal {
const SymbolName* lbl;
SymbolAddr* addr;
SymStrength strength;
+ SymType type;
} RtsSymbolVal;
extern RtsSymbolVal rtsSyms[];
diff --git a/rts/include/rts/Linker.h b/rts/include/rts/Linker.h
index 1f3719c0c7..143f1328d5 100644
--- a/rts/include/rts/Linker.h
+++ b/rts/include/rts/Linker.h
@@ -41,7 +41,7 @@ void initLinker (void);
*/
void initLinker_ (int retain_cafs);
-/* insert a symbol in the hash table */
+/* insert a code symbol in the hash table */
HsInt insertSymbol(pathchar* obj_name, char* key, void* data);
/* lookup a symbol in the hash table */
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 70f3c8870b..ae4721e6f3 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -977,6 +977,13 @@ ocGetNames_ELF ( ObjectCode* oc )
}
}
+ SymType sym_type;
+ if (ELF_ST_TYPE(symbol->elf_sym->st_info) == STT_FUNC) {
+ sym_type = SYM_TYPE_CODE;
+ } else {
+ sym_type = SYM_TYPE_DATA;
+ }
+
/* And the decision is ... */
if (symbol->addr != NULL) {
@@ -988,12 +995,13 @@ ocGetNames_ELF ( ObjectCode* oc )
setWeakSymbol(oc, nm);
}
if (!ghciInsertSymbolTable(oc->fileName, symhash,
- nm, symbol->addr, isWeak, oc)
+ nm, symbol->addr, isWeak, sym_type, oc)
) {
goto fail;
}
oc->symbols[curSymbol].name = nm;
oc->symbols[curSymbol].addr = symbol->addr;
+ oc->symbols[curSymbol].type = sym_type;
curSymbol++;
}
} else {
@@ -1123,7 +1131,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
if (ELF_ST_BIND(symbol->elf_sym->st_info) == STB_LOCAL || strncmp(symbol->name, "_GLOBAL_OFFSET_TABLE_", 21) == 0) {
S = (Elf_Addr)symbol->addr;
} else {
- S_tmp = lookupDependentSymbol( symbol->name, oc );
+ S_tmp = lookupDependentSymbol( symbol->name, oc, NULL );
S = (Elf_Addr)S_tmp;
}
if (!S) {
@@ -1569,7 +1577,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
} else {
/* If not local, look up the name in our global table. */
symbol = strtab + sym.st_name;
- S_tmp = lookupDependentSymbol( symbol, oc );
+ S_tmp = lookupDependentSymbol( symbol, oc, NULL );
S = (Elf_Addr)S_tmp;
}
if (!S) {
diff --git a/rts/linker/MachO.c b/rts/linker/MachO.c
index a45ec70b39..b37e2c9bc3 100644
--- a/rts/linker/MachO.c
+++ b/rts/linker/MachO.c
@@ -241,7 +241,7 @@ resolveImports(
addr = (SymbolAddr*) (symbol->nlist->n_value);
IF_DEBUG(linker, debugBelch("resolveImports: undefined external %s has value %p\n", symbol->name, addr));
} else {
- addr = lookupDependentSymbol(symbol->name, oc);
+ addr = lookupDependentSymbol(symbol->name, oc, NULL);
IF_DEBUG(linker, debugBelch("resolveImports: looking up %s, %p\n", symbol->name, addr));
}
@@ -506,7 +506,7 @@ relocateSectionAarch64(ObjectCode * oc, Section * section)
* or asking the system, if not found
* in the symbol hashmap
*/
- value = (uint64_t)lookupDependentSymbol((char*)symbol->name, oc);
+ value = (uint64_t)lookupDependentSymbol((char*)symbol->name, oc, NULL);
if(!value)
barf("Could not lookup symbol: %s!", symbol->name);
} else {
@@ -546,7 +546,7 @@ relocateSectionAarch64(ObjectCode * oc, Section * section)
uint64_t pc = (uint64_t)section->start + ri->r_address;
uint64_t value = 0;
if(symbol->nlist->n_type & N_EXT) {
- value = (uint64_t)lookupDependentSymbol((char*)symbol->name, oc);
+ value = (uint64_t)lookupDependentSymbol((char*)symbol->name, oc, NULL);
if(!value)
barf("Could not lookup symbol: %s!", symbol->name);
} else {
@@ -739,7 +739,7 @@ relocateSection(ObjectCode* oc, int curSection)
// symtab, or it is undefined, meaning dlsym must be used
// to resolve it.
- addr = lookupDependentSymbol(nm, oc);
+ addr = lookupDependentSymbol(nm, oc, NULL);
IF_DEBUG(linker_verbose,
debugBelch("relocateSection: looked up %s, "
"external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n"
@@ -804,7 +804,7 @@ relocateSection(ObjectCode* oc, int curSection)
nm, (void *)value));
}
else {
- addr = lookupDependentSymbol(nm, oc);
+ addr = lookupDependentSymbol(nm, oc, NULL);
if (addr == NULL)
{
errorBelch("\nlookupSymbol failed in relocateSection (relocate external)\n"
@@ -1342,7 +1342,7 @@ ocGetNames_MachO(ObjectCode* oc)
if (oc->info->nlist[i].n_type & N_EXT)
{
if ( (oc->info->nlist[i].n_desc & N_WEAK_DEF)
- && lookupDependentSymbol(nm, oc)) {
+ && lookupDependentSymbol(nm, oc, NULL)) {
// weak definition, and we already have a definition
IF_DEBUG(linker_verbose, debugBelch(" weak: %s\n", nm));
}
@@ -1350,16 +1350,20 @@ ocGetNames_MachO(ObjectCode* oc)
{
IF_DEBUG(linker_verbose, debugBelch("ocGetNames_MachO: inserting %s\n", nm));
SymbolAddr* addr = oc->info->macho_symbols[i].addr;
-
+ MachOSection *sect = &oc->info->macho_sections[oc->info->macho_symbols[i].nlist->n_sect-1];
+ // TODO: Make figure out how to determine this from the object file
+ SymType sym_type = SYM_TYPE_CODE;
ghciInsertSymbolTable( oc->fileName
, symhash
, nm
, addr
, HS_BOOL_FALSE
+ , sym_type
, oc);
oc->symbols[curSymbol].name = nm;
oc->symbols[curSymbol].addr = addr;
+ oc->symbols[curSymbol].type = sym_type;
curSymbol++;
}
}
@@ -1392,10 +1396,12 @@ ocGetNames_MachO(ObjectCode* oc)
/* also set the final address to the macho_symbol */
oc->info->macho_symbols[i].addr = (void*)commonCounter;
+ /* TODO: Figure out how to determine this from object */
+ SymType sym_type = SYM_TYPE_CODE;
IF_DEBUG(linker_verbose, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
ghciInsertSymbolTable(oc->fileName, symhash, nm,
- (void*)commonCounter, HS_BOOL_FALSE, oc);
+ (void*)commonCounter, HS_BOOL_FALSE, sym_type, oc);
oc->symbols[curSymbol].name = nm;
oc->symbols[curSymbol].addr = oc->info->macho_symbols[i].addr;
curSymbol++;
@@ -1517,7 +1523,7 @@ ocResolve_MachO(ObjectCode* oc)
* have the address.
*/
if(NULL == symbol->addr) {
- symbol->addr = lookupDependentSymbol((char*)symbol->name, oc);
+ symbol->addr = lookupDependentSymbol((char*)symbol->name, oc, NULL);
if(NULL == symbol->addr) {
errorBelch("Failed to lookup symbol: %s", symbol->name);
return 0;
diff --git a/rts/linker/PEi386.c b/rts/linker/PEi386.c
index 67cf049a62..00c28a959d 100644
--- a/rts/linker/PEi386.c
+++ b/rts/linker/PEi386.c
@@ -183,10 +183,10 @@
#include "RtsSymbolInfo.h"
#include "GetEnv.h"
#include "CheckUnload.h"
+#include "LinkerInternals.h"
#include "linker/PEi386.h"
#include "linker/PEi386Types.h"
#include "linker/SymbolExtras.h"
-#include "LinkerInternals.h"
#include <windows.h>
#include <shfolder.h> /* SHGetFolderPathW */
@@ -205,7 +205,8 @@ static size_t makeSymbolExtra_PEi386(
ObjectCode* oc,
uint64_t index,
size_t s,
- SymbolName* symbol);
+ SymbolName* symbol,
+ SymType sym_type);
#endif
static void addDLLHandle(
@@ -289,7 +290,7 @@ const void* __rts_iob_func = (void*)&__acrt_iob_func;
void initLinker_PEi386()
{
if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
- symhash, "__image_base__", __image_base, HS_BOOL_TRUE, NULL)) {
+ symhash, "__image_base__", __image_base, HS_BOOL_TRUE, SYM_TYPE_CODE, NULL)) {
barf("ghciInsertSymbolTable failed");
}
@@ -1495,7 +1496,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
sname = strdup (sname);
addr = strdup (addr);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false, oc)) {
+ addr, false, SYM_TYPE_DATA, oc)) {
releaseOcInfo (oc);
stgFree (oc->image);
oc->image = NULL;
@@ -1625,6 +1626,15 @@ ocGetNames_PEi386 ( ObjectCode* oc )
sname = get_sym_name (getSymShortName (info, sym), oc);
Section *section = secNumber > 0 ? &oc->sections[secNumber-1] : NULL;
+ SymType type;
+ switch (sym->og.Type) {
+ case 0x00: type = SYM_TYPE_DATA; break;
+ case 0x20: type = SYM_TYPE_CODE; break;
+ default:
+ debugBelch("Invalid symbol type\n");
+ return 1;
+ }
+
if ( secNumber != IMAGE_SYM_UNDEFINED
&& secNumber > 0
&& section
@@ -1713,7 +1723,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
stgFree(tmp);
sname = strdup (sname);
if (!ghciInsertSymbolTable(oc->fileName, symhash, sname,
- addr, false, oc))
+ addr, false, type, oc))
return false;
break;
@@ -1727,12 +1737,13 @@ ocGetNames_PEi386 ( ObjectCode* oc )
ASSERT(i < (uint32_t)oc->n_symbols);
oc->symbols[i].name = sname;
oc->symbols[i].addr = addr;
+ oc->symbols[i].type = type;
if (isWeak) {
setWeakSymbol(oc, sname);
}
if (! ghciInsertSymbolTable(oc->fileName, symhash, sname, addr,
- isWeak, oc))
+ isWeak, type, oc))
return false;
} else {
/* We're skipping the symbol, but if we ever load this
@@ -1848,7 +1859,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
} else {
copyName ( getSymShortName (info, sym), oc, symbol,
sizeof(symbol)-1 );
- S = (size_t) lookupDependentSymbol( (char*)symbol, oc );
+ S = (size_t) lookupDependentSymbol( (char*)symbol, oc, NULL );
if ((void*)S == NULL) {
errorBelch(" | %" PATH_FMT ": unknown symbol `%s'", oc->fileName, symbol);
releaseOcInfo (oc);
@@ -2102,7 +2113,7 @@ ocRunInit_PEi386 ( ObjectCode *oc )
return true;
}
-SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl)
+SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl, SymType *type)
{
RtsSymbolInfo *pinfo;
@@ -2115,9 +2126,12 @@ SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl)
#if !defined(x86_64_HOST_ARCH)
zapTrailingAtSign ( lbl );
#endif
+ if (type) *type = SYM_TYPE_CODE; // TODO
sym = lookupSymbolInDLLs(lbl);
return sym; // might be NULL if not found
} else {
+ if (type) *type = pinfo->type;
+
// If Windows, perform initialization of uninitialized
// Symbols from the C runtime which was loaded above.
// We do this on lookup to prevent the hit when
@@ -2133,7 +2147,7 @@ SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl)
else if (pinfo && pinfo->owner && isSymbolImport (pinfo->owner, lbl))
{
/* See Note [BFD import library]. */
- HINSTANCE dllInstance = (HINSTANCE)lookupDependentSymbol(pinfo->value, NULL);
+ HINSTANCE dllInstance = (HINSTANCE)lookupDependentSymbol(pinfo->value, NULL, type);
if (!dllInstance && pinfo->value)
return pinfo->value;
diff --git a/rts/linker/PEi386.h b/rts/linker/PEi386.h
index 8e6e844efb..7148ba7436 100644
--- a/rts/linker/PEi386.h
+++ b/rts/linker/PEi386.h
@@ -56,7 +56,7 @@ bool ocResolve_PEi386 ( ObjectCode* oc );
bool ocRunInit_PEi386 ( ObjectCode *oc );
bool ocGetNames_PEi386 ( ObjectCode* oc );
bool ocVerifyImage_PEi386 ( ObjectCode* oc );
-SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl);
+SymbolAddr *lookupSymbol_PEi386(SymbolName *lbl, SymType *type);
bool ocAllocateExtras_PEi386 ( ObjectCode* oc );
SymbolAddr *lookupSymbolInDLLs ( const SymbolName* lbl );
/* See Note [mingw-w64 name decoration scheme] */
diff --git a/rts/linker/elf_got.c b/rts/linker/elf_got.c
index eefdae34c6..0f511e663f 100644
--- a/rts/linker/elf_got.c
+++ b/rts/linker/elf_got.c
@@ -92,7 +92,7 @@ fillGot(ObjectCode * oc) {
if( STT_NOTYPE == ELF_ST_TYPE(symbol->elf_sym->st_info)
|| STB_WEAK == ELF_ST_BIND(symbol->elf_sym->st_info)) {
if(0x0 == symbol->addr) {
- symbol->addr = lookupDependentSymbol(symbol->name, oc);
+ symbol->addr = lookupDependentSymbol(symbol->name, oc, NULL);
if(0x0 == symbol->addr) {
if(0 == strncmp(symbol->name,"_GLOBAL_OFFSET_TABLE_",21)) {
symbol->addr = oc->info->got_start;