#pragma once #if defined(OBJFORMAT_MACHO) #include "ghcplatform.h" #include #if defined(x86_64_HOST_ARCH) \ || defined(aarch64_HOST_ARCH) || defined(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; #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 information (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; 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; }; /* 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 ObjectCode and not per Section. * * TODO: Merge SymbolExtras and Stubs. */ typedef struct _Stub { void * addr; void * target; /* flags can hold architecture specific information they are used during * lookup of stubs as well. Thus two stubs for the same target with * different flags are considered unequal. */ uint8_t flags; struct _Stub * next; } Stub; 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; }; #endif /* OBJECTFORMAT_MACHO */