#include "RtsFlags.h"
#include "HsFFI.h"
#include "Hash.h"
+#include "Storage.h"
+#include "Stable.h"
#include "Linker.h"
#include "LinkerInternals.h"
#include "RtsUtils.h"
#include "Schedule.h"
-#include "Storage.h"
#include "Sparks.h"
+#include "RtsTypeable.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
/* Hash table mapping symbol names to Symbol */
static /*Str*/HashTable *symhash;
+typedef struct {
+ void *addr;
+} rootEntry;
+
+/* Hash table mapping symbol names to StgStablePtr */
+static /*Str*/HashTable *stablehash;
+rootEntry *root_ptr_table = NULL;
+static rootEntry *root_ptr_free = NULL;
+
+static unsigned int RPT_size = 0;
+
/* List of currently loaded objects */
ObjectCode *objects = NULL; /* initially empty */
Sym(mktime) \
Sym(_imp___timezone) \
Sym(_imp___tzname) \
+ Sym(_imp__tzname) \
Sym(_imp___iob) \
Sym(_imp___osver) \
Sym(localtime) \
SymX(catchzh_fast) \
SymX(catchRetryzh_fast) \
SymX(catchSTMzh_fast) \
+ SymX(checkzh_fast) \
SymX(closure_flags) \
SymX(cmp_thread) \
SymX(cmpIntegerzh_fast) \
SymX(forkOS_createThread) \
SymX(freeHaskellFunctionPtr) \
SymX(freeStablePtr) \
+ SymX(getOrSetTypeableStore) \
SymX(gcdIntegerzh_fast) \
SymX(gcdIntegerIntzh_fast) \
SymX(gcdIntzh_fast) \
SymX(isFloatNegativeZero) \
SymX(killThreadzh_fast) \
SymX(loadObj) \
+ SymX(insertStableSymbol) \
+ SymX(insertSymbol) \
SymX(lookupSymbol) \
SymX(makeStablePtrzh_fast) \
SymX(minusIntegerzh_fast) \
SymX(stg_interp_constr6_entry) \
SymX(stg_interp_constr7_entry) \
SymX(stg_interp_constr8_entry) \
- SymX(stgMallocBytesRWX) \
+ SymX(allocateExec) \
+ SymX(freeExec) \
SymX(getAllocations) \
SymX(revertCAFs) \
SymX(RtsFlags) \
{ 0, 0 } /* sentinel */
};
+
+/* -----------------------------------------------------------------------------
+ * Utilities for handling root pointers.
+ * -------------------------------------------------------------------------- */
+
+
+#define INIT_RPT_SIZE 64
+
+STATIC_INLINE void
+initFreeList(rootEntry *table, nat n, rootEntry *free)
+{
+ rootEntry *p;
+
+ for (p = table + n - 1; p >= table; p--) {
+ p->addr = (P_)free;
+ free = p;
+ }
+ root_ptr_free = table;
+}
+
+static void
+initRootPtrTable(void)
+{
+ if (RPT_size > 0)
+ return;
+
+ RPT_size = INIT_RPT_SIZE;
+ root_ptr_table = stgMallocBytes(RPT_size * sizeof(rootEntry),
+ "initRootPtrTable");
+
+ initFreeList(root_ptr_table,INIT_RPT_SIZE,NULL);
+}
+
+
+static void
+enlargeRootPtrTable(void)
+{
+ nat old_RPT_size = RPT_size;
+
+ // 2nd and subsequent times
+ RPT_size *= 2;
+ root_ptr_table =
+ stgReallocBytes(root_ptr_table,
+ RPT_size * sizeof(rootEntry),
+ "enlargeRootPtrTable");
+
+ initFreeList(root_ptr_table + old_RPT_size, old_RPT_size, NULL);
+}
+
+static void
+addRootObject(void *addr)
+{
+ StgWord rt;
+ initRootPtrTable();
+ if (root_ptr_free == NULL) {
+ enlargeRootPtrTable();
+ }
+
+ rt = root_ptr_free - root_ptr_table;
+ root_ptr_free = (rootEntry*)(root_ptr_free->addr);
+ root_ptr_table[rt].addr = addr;
+}
+
+/* -----------------------------------------------------------------------------
+ * Treat root pointers as roots for the garbage collector.
+ * -------------------------------------------------------------------------- */
+
+void
+markRootPtrTable(evac_fn evac)
+{
+ rootEntry *p, *end_root_ptr_table;
+ StgPtr q;
+
+ end_root_ptr_table = &root_ptr_table[RPT_size];
+
+ for (p = root_ptr_table; p < end_root_ptr_table; p++) {
+ q = p->addr;
+
+ if (q && (q < (P_)root_ptr_table || q >= (P_)end_root_ptr_table)) {
+ evac((StgClosure **)p->addr);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------------------
+ * End of utilities for handling root pointers.
+ * -------------------------------------------------------------------------- */
+
+
/* -----------------------------------------------------------------------------
* Insert symbols into hash tables, checking for duplicates.
*/
static void *dl_prog_handle;
#endif
-/* dlopen(NULL,..) doesn't work so we grab libc explicitly */
-#if defined(openbsd_HOST_OS)
-static void *dl_libc_handle;
-#endif
-
void
initLinker( void )
{
linker_init_done = 1;
}
+ stablehash = allocStrHashTable();
symhash = allocStrHashTable();
/* populate the symbol table with stuff from the RTS */
dl_prog_handle = RTLD_DEFAULT;
# else
dl_prog_handle = dlopen(NULL, RTLD_LAZY);
-# if defined(openbsd_HOST_OS)
- dl_libc_handle = dlopen("libc.so", RTLD_LAZY);
-# endif
# endif /* RTLD_DEFAULT */
# endif
}
}
/* -----------------------------------------------------------------------------
+ * insert a stable symbol in the hash table
+ */
+
+void
+insertStableSymbol(char* obj_name, char* key, StgPtr p)
+{
+ ghciInsertStrHashTable(obj_name, stablehash, key, getStablePtr(p));
+}
+
+
+/* -----------------------------------------------------------------------------
+ * insert a symbol in the hash table
+ */
+void
+insertSymbol(char* obj_name, char* key, void* data)
+{
+ ghciInsertStrHashTable(obj_name, symhash, key, data);
+}
+
+/* -----------------------------------------------------------------------------
* lookup a symbol in the hash table
*/
void *
if (val == NULL) {
# if defined(OBJFORMAT_ELF)
-# if defined(openbsd_HOST_OS)
- val = dlsym(dl_prog_handle, lbl);
- return (val != NULL) ? val : dlsym(dl_libc_handle,lbl);
-# elif defined(x86_64_HOST_ARCH)
+# if defined(x86_64_HOST_ARCH)
val = dlsym(dl_prog_handle, lbl);
if (val >= (void *)0x80000000) {
void *new_val;
} else {
return val;
}
-# else /* not openbsd */
+# else
return dlsym(dl_prog_handle, lbl);
# endif
# elif defined(OBJFORMAT_MACHO)
&& 0 != strcmp(".stabstr", sectab_i->Name)
/* ignore constructor section for now */
&& 0 != strcmp(".ctors", sectab_i->Name)
+ /* ignore section generated from .ident */
+ && 0!= strcmp("/4", sectab_i->Name)
) {
errorBelch("Unknown PEi386 section name `%s' (while processing: %s)", sectab_i->Name, oc->fileName);
return 0;
+ sym->Value);
} else {
copyName ( sym->Name, strtab, symbol, 1000-1 );
- (void*)S = lookupLocalSymbol( oc, symbol );
+ S = (UInt32) lookupLocalSymbol( oc, symbol );
if ((void*)S != NULL) goto foundit;
- (void*)S = lookupSymbol( symbol );
+ S = (UInt32) lookupSymbol( symbol );
if ((void*)S != NULL) goto foundit;
zapTrailingAtSign ( symbol );
- (void*)S = lookupLocalSymbol( oc, symbol );
+ S = (UInt32) lookupLocalSymbol( oc, symbol );
if ((void*)S != NULL) goto foundit;
- (void*)S = lookupSymbol( symbol );
+ S = (UInt32) lookupSymbol( symbol );
if ((void*)S != NULL) goto foundit;
/* Newline first because the interactive linker has printed "linking..." */
errorBelch("\n%s: unknown symbol `%s'", oc->fileName, symbol);
IF_DEBUG(linker,debugBelch( "Architecture is " ));
switch (ehdr->e_machine) {
case EM_386: IF_DEBUG(linker,debugBelch( "x86" )); break;
+#ifdef EM_SPARC32PLUS
+ case EM_SPARC32PLUS:
+#endif
case EM_SPARC: IF_DEBUG(linker,debugBelch( "sparc" )); break;
#ifdef EM_IA_64
case EM_IA_64: IF_DEBUG(linker,debugBelch( "ia64" )); break;
Elf_Addr S;
void* S_tmp;
Elf_Addr value;
+ StgStablePtr stablePtr;
+ StgPtr stableVal;
IF_DEBUG(linker,debugBelch( "Rel entry %3d is raw(%6p %6p)",
j, (void*)offset, (void*)info ));
+ stab[ELF_R_SYM(info)].st_value);
} else {
- /* No, so look up the name in our global table. */
symbol = strtab + sym.st_name;
- S_tmp = lookupSymbol( symbol );
- S = (Elf_Addr)S_tmp;
+ 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 );
+ addRootObject((void*)P);
+ S_tmp = stableVal;
+ S = (Elf_Addr)S_tmp;
+ }
}
if (!S) {
errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol);