summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
Diffstat (limited to 'rts')
-rw-r--r--rts/Linker.c6
-rw-r--r--rts/LinkerInternals.h28
-rw-r--r--rts/linker/MachOTypes.h133
3 files changed, 165 insertions, 2 deletions
diff --git a/rts/Linker.c b/rts/Linker.c
index 7654f2b534..87f1eebf04 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1163,6 +1163,9 @@ void freeObjectCode (ObjectCode *oc)
break;
}
}
+ if (oc->sections[i].info) {
+ stgFree(oc->sections[i].info);
+ }
}
stgFree(oc->sections);
}
@@ -1732,6 +1735,9 @@ addSection (Section *s, SectionKind kind, SectionAlloc alloc,
s->mapped_start = mapped_start; /* start of mmap() block */
s->mapped_size = mapped_size; /* size of mmap() block */
+ s->info = (SectionFormatInfo*)stgCallocBytes(1, sizeof(SectionFormatInfo),
+ "addSection(SectionFormatInfo)");
+
IF_DEBUG(linker,
debugBelch("addSection: %p-%p (size %" FMT_Word "), kind %d\n",
start, (void*)((StgWord)start + size),
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 76497df257..2217c5e61b 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -21,6 +21,9 @@
typedef void SymbolAddr;
typedef char SymbolName;
+typedef struct _SectionFormatInfo SectionFormatInfo;
+typedef struct _ObjectCodeFormatInfo ObjectCodeFormatInfo;
+
/* See Linker.c Note [runtime-linker-phases] */
typedef enum {
OBJECT_LOADED,
@@ -63,6 +66,9 @@ typedef
StgWord mapped_offset; /* offset from the image of mapped_start */
void* mapped_start; /* start of mmap() block */
StgWord mapped_size; /* size of mmap() block */
+
+ /* A customizable type to augment the Section type. */
+ SectionFormatInfo* info;
}
Section;
@@ -86,7 +92,10 @@ typedef struct ForeignExportStablePtr_ {
} ForeignExportStablePtr;
#if powerpc_HOST_ARCH || x86_64_HOST_ARCH || arm_HOST_ARCH
+/* ios currently uses adjacent got tables, and no symbol extras */
+#if !defined(ios_HOST_OS)
#define NEED_SYMBOL_EXTRAS 1
+#endif /* ios_HOST_OS */
#endif
/* Jump Islands are sniplets of machine code required for relative
@@ -132,6 +141,10 @@ typedef struct _ObjectCode {
/* ptr to mem containing the object file image */
char* image;
+
+ /* A customizable type, that formats can use to augment ObjectCode */
+ ObjectCodeFormatInfo *info;
+
/* non-zero if the object file was mmap'd, otherwise malloc'd */
int imageMapped;
@@ -299,12 +312,23 @@ char *cstring_from_section_name(
#endif
/* Which object file format are we targetting? */
-#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(kfreebsdgnu_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) || defined(gnu_HOST_OS)
+#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) \
+|| defined(linux_android_HOST_OS) \
+|| defined(freebsd_HOST_OS) || defined(kfreebsdgnu_HOST_OS) \
+|| defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) \
+|| defined(openbsd_HOST_OS) || defined(gnu_HOST_OS)
# define OBJFORMAT_ELF
+typedef struct _ObjectCodeFormatInfo { void* placeholder;} ObjectCodeFormatInfo;
+typedef struct _SectionFormatInfo { void* placeholder; } SectionFormatInfo;
#elif defined (mingw32_HOST_OS)
# define OBJFORMAT_PEi386
-#elif defined(darwin_HOST_OS)
+typedef struct _ObjectCodeFormatInfo { void* placeholder;} ObjectCodeFormatInfo;
+typedef struct _SectionFormatInfo { void* placeholder; } SectionFormatInfo;
+#elif defined(darwin_HOST_OS) || defined(ios_HOST_OS)
# define OBJFORMAT_MACHO
+# include "linker/MachOTypes.h"
+#else
+#error "Unknown OBJECT_FORMAT for HOST_OS"
#endif
/* In order to simplify control flow a bit, some references to mmap-related
diff --git a/rts/linker/MachOTypes.h b/rts/linker/MachOTypes.h
new file mode 100644
index 0000000000..31bfdb49cd
--- /dev/null
+++ b/rts/linker/MachOTypes.h
@@ -0,0 +1,133 @@
+#ifndef MachOTypes_h
+#define MachOTypes_h
+
+#if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
+
+#include "ghcplatform.h"
+
+#include <mach-o/loader.h>
+
+#if x86_64_HOST_ARCH || powerpc64_HOST_ARCH \
+ || aarch64_HOST_ARCH || arm64_HOST_ARCH
+typedef struct mach_header_64 MachOHeader;
+typedef struct segment_command_64 MachOSegmentCommand;
+typedef struct section_64 MachOSection;
+typedef struct nlist_64 MachONList;
+#elif i386_HOST_ARCH || powerpc_HOST_ARCH || arm_HOST_ARCH
+typedef struct mach_header MachOHeader;
+typedef struct segment_command MachOSegmentCommand;
+typedef struct section MachOSection;
+typedef struct nlist MachONList;
+#else
+#error Unknown Darwin architecture
+#endif
+typedef struct load_command MachOLoadCommand;
+typedef struct symtab_command MachOSymtabCommand;
+typedef struct dysymtab_command MachODsymtabCommand;
+typedef struct relocation_info MachORelocationInfo;
+typedef struct scattered_relocation_info MachOScatteredRelocationInfo;
+
+/* Dealing with nlist symbol entries can become
+ * painful. We'll have our own Symbol struct that
+ * mirrors the symbol from the nlist and can carry
+ * some more infomration (like addr).
+ */
+typedef struct _MachOSymbol {
+ SymbolName * name; /* the name of the symbol. */
+ SymbolAddr * addr; /* the final resting place of the symbol */
+ void * got_addr; /* address of the got slot for this symbol, if any */
+ MachONList * nlist; /* the nlist symbol entry */
+} MachOSymbol;
+
+typedef struct _ObjectCodeFormatInfo {
+ // while we have the image
+ // we can store some pointers
+ // into it, so we don't have
+ // recompute them each time.
+ /* the object header */
+ MachOHeader *header;
+ MachOSymtabCommand *symCmd;
+ MachOSegmentCommand *segCmd;
+ MachODsymtabCommand *dsymCmd;
+ /* points to the first nlist in the image */
+ MachONList *nlist;
+ /* points to the names offset in the image */
+ char *names;
+
+ /* points to the start of the sections */
+ MachOSection *macho_sections;
+
+ /* A richer nlist type */
+ MachOSymbol *macho_symbols;
+ size_t n_macho_symbols;
+
+ /* pointer to the global offset table */
+ void *got_start;
+ size_t got_size;
+} ObjectCodeFormatInfo;
+
+/* When loading sections of the macho
+ * into different pages, such that the
+ * pages can be marked r+x for text and
+ * r+w for data, relocation may need
+ * to be done indirectly, as the symbol
+ * is not within reach of the of the
+ * call site. E.g. B/BL instructions on
+ * aarch64 have +-128mb relative
+ * range. When pages are mmap'd they
+ * may end up at random positions.
+ *
+ * Hence we reserve space for the stub
+ * slots right after the text section
+ *
+ * .----------. - page start
+ * | |
+ * | __TEXT |
+ * | |
+ * |----------|
+ * | Stubs |
+ * '----------'
+ *
+ * Therefore, unless the __TEXT section
+ * grows beyond 128mb-|Stubs|, we can
+ * always reach the corresponding stub
+ * for a symbol.
+ *
+ * Stubs will be rendered as
+ * - 8 bytes: target address
+ * - 4 bytes: relative load at -8bytes
+ instruction
+ * - 4 bytes: branch instruction
+ *
+ * These are very similar to the SymbolExtras
+ * below. However the SymbolExtras are allocated
+ * per ObejctCode and not per Section.
+ *
+ * TODO: Merge SymbolExtras and Stubs.
+ */
+typedef
+struct _Stub {
+ void * addr;
+ void * target;
+ struct _Stub * next;
+}
+Stub;
+
+typedef struct _SectionFormatInfo {
+ /*
+ * The following fields are relevant for stubs next to sections only.
+ */
+ void * stub_offset;
+ size_t stub_size;
+ size_t nstubs;
+ Stub * stubs;
+
+ /*
+ * The following fields make working with mach-o objects much easier.
+ */
+ MachOSection * macho_section;
+ MachORelocationInfo * relocation_info;
+} SectionFormatInfo;
+
+#endif /* darwin_HOST_OS || ios_HOST_OS */
+#endif /* MachOTypes_h */