diff options
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Linker.c | 6 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 28 | ||||
-rw-r--r-- | rts/linker/MachOTypes.h | 133 |
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 */ |