/* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.103 2002/09/13 15:02:50 simonpj Exp $
+ * $Id: Linker.c,v 1.105 2002/10/12 23:12:08 wolfgang Exp $
*
* (c) The GHC Team, 2000, 2001
*
#include <sys/stat.h>
#endif
-#ifdef HAVE_DLFCN_H
+#if defined(HAVE_FRAMEWORK_HASKELLSUPPORT)
+#include <HaskellSupport/dlfcn.h>
+#elif defined(HAVE_DLFCN_H)
#include <dlfcn.h>
#endif
# include <windows.h>
# include <math.h>
#elif defined(darwin_TARGET_OS)
+# include <mach-o/ppc/reloc.h>
# define OBJFORMAT_MACHO
# include <mach-o/loader.h>
# include <mach-o/nlist.h>
#define RTS_EXTRA_SYMBOLS \
Sym(__divsf3)
#elif defined(powerpc_TARGET_ARCH)
-#define RTS_EXTRA_SYMBOLS \
+#define RTS_EXTRA_SYMBOLS \
Sym(__divdi3) \
Sym(__udivdi3) \
Sym(__moddi3) \
- Sym(__umoddi3) \
- Sym(__ashldi3) \
- Sym(__ashrdi3) \
- Sym(__lshrdi3) \
- SymX(__eprintf)
+ Sym(__umoddi3) \
+ Sym(__ashldi3) \
+ Sym(__ashrdi3) \
+ Sym(__lshrdi3) \
+ Sym(__eprintf)
#else
#define RTS_EXTRA_SYMBOLS /* nothing */
#endif
if(reloc->r_pcrel && !reloc->r_extern)
continue;
- if(!reloc->r_pcrel
- && reloc->r_length == 2
- && reloc->r_type == GENERIC_RELOC_VANILLA)
+ if(!reloc->r_pcrel && reloc->r_length == 2)
{
- unsigned long* word = (unsigned long*) (image + sect->offset + reloc->r_address);
+ unsigned long word;
+
+ unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
+ if(reloc->r_type == GENERIC_RELOC_VANILLA)
+ {
+ word = *wordPtr;
+ }
+ else if(reloc->r_type == PPC_RELOC_LO16)
+ {
+ word = ((unsigned short*) wordPtr)[1];
+ word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
+ }
+ else if(reloc->r_type == PPC_RELOC_HI16)
+ {
+ word = ((unsigned short*) wordPtr)[1] << 16;
+ word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
+ }
+ else if(reloc->r_type == PPC_RELOC_HA16)
+ {
+ word = ((unsigned short*) wordPtr)[1] << 16;
+ word += ((short)relocs[i+1].r_address & (short)0xFFFF);
+ }
+
if(!reloc->r_extern)
{
long delta =
- sections[reloc->r_symbolnum-1].addr
+ ((long) image);
- *word += delta;
+ word += delta;
}
else
{
struct nlist *symbol = &nlist[reloc->r_symbolnum];
char *nm = image + symLC->stroff + symbol->n_un.n_strx;
- *word = (unsigned long) (lookupSymbol(nm));
- ASSERT(*word);
+ word = (unsigned long) (lookupSymbol(nm));
+ ASSERT(word);
+ }
+
+ if(reloc->r_type == GENERIC_RELOC_VANILLA)
+ {
+ *wordPtr = word;
+ continue;
+ }
+ else if(reloc->r_type == PPC_RELOC_LO16)
+ {
+ ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
+ i++; continue;
+ }
+ else if(reloc->r_type == PPC_RELOC_HI16)
+ {
+ ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
+ i++; continue;
+ }
+ else if(reloc->r_type == PPC_RELOC_HA16)
+ {
+ ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
+ + ((word & (1<<15)) ? 1 : 0);
+ i++; continue;
}
continue;
}