Unified · Split
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Mach-O file handling for TCC | 2 | * Mach-O file handling for TCC |
| 3 | * | 3 | * |
| 4 | * This library is free software; you can redistribute it and/or | 4 | * This library is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU Lesser General Public | 5 | * modify it under the terms of the GNU Lesser General Public |
| @@ -20,14 +20,32 @@ · 14 unmodified lines | |||
| 20 | #define DEBUG_MACHO 0 | 20 | #define DEBUG_MACHO 0 |
| 21 | #define dprintf if (DEBUG_MACHO) printf | 21 | #define dprintf if (DEBUG_MACHO) printf |
| 22 | 22 | ||
| 23 | struct fat_header { | ||
| 24 | uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ | ||
| 25 | uint32_t nfat_arch; /* number of structs that follow */ | ||
| 26 | }; | ||
| 27 | |||
| 28 | struct fat_arch { | ||
| 29 | int cputype; /* cpu specifier (int) */ | ||
| 30 | int cpusubtype; /* machine specifier (int) */ | ||
| 31 | uint32_t offset; /* file offset to this object file */ | ||
| 32 | uint32_t size; /* size of this object file */ | ||
| 33 | uint32_t align; /* alignment as a power of 2 */ | ||
| 34 | }; | ||
| 35 | |||
| 36 | #define FAT_MAGIC 0xcafebabe | ||
| 37 | #define FAT_CIGAM 0xbebafeca | ||
| 38 | #define FAT_MAGIC_64 0xcafebabf | ||
| 39 | #define FAT_CIGAM_64 0xbfbafeca | ||
| 40 | |||
| 23 | struct mach_header { | 41 | struct mach_header { |
| 24 | uint32_t magic; /* mach magic number identifier */ | 42 | uint32_t magic; /* mach magic number identifier */ |
| 25 | int cputype; /* cpu specifier */ | 43 | int cputype; /* cpu specifier */ |
| 26 | int cpusubtype; /* machine specifier */ | 44 | int cpusubtype; /* machine specifier */ |
| 27 | uint32_t filetype; /* type of file */ | 45 | uint32_t filetype; /* type of file */ |
| 28 | uint32_t ncmds; /* number of load commands */ | 46 | uint32_t ncmds; /* number of load commands */ |
| 29 | uint32_t sizeofcmds; /* the size of all the load commands */ | 47 | uint32_t sizeofcmds; /* the size of all the load commands */ |
| 30 | uint32_t flags; /* flags */ | 48 | uint32_t flags; /* flags */ |
| 31 | }; | 49 | }; |
| 32 | 50 | ||
| 33 | struct mach_header_64 { | 51 | struct mach_header_64 { |
| @@ -42,95 +60,86 @@ struct mach_header_64 { · 8 unmodified lines | |||
| 42 | #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ | 60 | #define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ |
| 43 | 61 | ||
| 44 | struct load_command { | 62 | struct load_command { |
| 45 | uint32_t cmd; /* type of load command */ | 63 | uint32_t cmd; /* type of load command */ |
| 46 | uint32_t cmdsize; /* total size of command in bytes */ | 64 | uint32_t cmdsize; /* total size of command in bytes */ |
| 47 | }; | 65 | }; |
| 48 | 66 | ||
| 49 | typedef int vm_prot_t; | 67 | #define LC_REQ_DYLD 0x80000000 |
| 68 | #define LC_SYMTAB 0x2 | ||
| 69 | #define LC_DYSYMTAB 0xb | ||
| 70 | #define LC_LOAD_DYLIB 0xc | ||
| 71 | #define LC_ID_DYLIB 0xd | ||
| 72 | #define LC_LOAD_DYLINKER 0xe | ||
| 73 | #define LC_SEGMENT_64 0x19 | ||
| 74 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) | ||
| 75 | #define LC_MAIN (0x28|LC_REQ_DYLD) | ||
| 50 | 76 | ||
| 51 | struct segment_command { /* for 32-bit architectures */ | 77 | typedef int vm_prot_t; |
| 52 | uint32_t cmd; /* LC_SEGMENT */ | ||
| 53 | uint32_t cmdsize; /* includes sizeof section structs */ | ||
| 54 | char segname[16]; /* segment name */ | ||
| 55 | uint32_t vmaddr; /* memory address of this segment */ | ||
| 56 | uint32_t vmsize; /* memory size of this segment */ | ||
| 57 | uint32_t fileoff; /* file offset of this segment */ | ||
| 58 | uint32_t filesize; /* amount to map from the file */ | ||
| 59 | vm_prot_t maxprot; /* maximum VM protection */ | ||
| 60 | vm_prot_t initprot; /* initial VM protection */ | ||
| 61 | uint32_t nsects; /* number of sections in segment */ | ||
| 62 | uint32_t flags; /* flags */ | ||
| 63 | }; | ||
| 64 | 78 | ||
| 65 | struct segment_command_64 { /* for 64-bit architectures */ | 79 | struct segment_command_64 { /* for 64-bit architectures */ |
| 66 | uint32_t cmd; /* LC_SEGMENT_64 */ | 80 | uint32_t cmd; /* LC_SEGMENT_64 */ |
| 67 | uint32_t cmdsize; /* includes sizeof section_64 structs */ | 81 | uint32_t cmdsize; /* includes sizeof section_64 structs */ |
| 68 | char segname[16]; /* segment name */ | 82 | char segname[16]; /* segment name */ |
| 69 | uint64_t vmaddr; /* memory address of this segment */ | 83 | uint64_t vmaddr; /* memory address of this segment */ |
| 70 | uint64_t vmsize; /* memory size of this segment */ | 84 | uint64_t vmsize; /* memory size of this segment */ |
| 71 | uint64_t fileoff; /* file offset of this segment */ | 85 | uint64_t fileoff; /* file offset of this segment */ |
| 72 | uint64_t filesize; /* amount to map from the file */ | 86 | uint64_t filesize; /* amount to map from the file */ |
| 73 | vm_prot_t maxprot; /* maximum VM protection */ | 87 | vm_prot_t maxprot; /* maximum VM protection */ |
| 74 | vm_prot_t initprot; /* initial VM protection */ | 88 | vm_prot_t initprot; /* initial VM protection */ |
| 75 | uint32_t nsects; /* number of sections in segment */ | 89 | uint32_t nsects; /* number of sections in segment */ |
| 76 | uint32_t flags; /* flags */ | 90 | uint32_t flags; /* flags */ |
| 77 | }; | ||
| 78 | |||
| 79 | struct section { /* for 32-bit architectures */ | ||
| 80 | char sectname[16]; /* name of this section */ | ||
| 81 | char segname[16]; /* segment this section goes in */ | ||
| 82 | uint32_t addr; /* memory address of this section */ | ||
| 83 | uint32_t size; /* size in bytes of this section */ | ||
| 84 | uint32_t offset; /* file offset of this section */ | ||
| 85 | uint32_t align; /* section alignment (power of 2) */ | ||
| 86 | uint32_t reloff; /* file offset of relocation entries */ | ||
| 87 | uint32_t nreloc; /* number of relocation entries */ | ||
| 88 | uint32_t flags; /* flags (section type and attributes)*/ | ||
| 89 | uint32_t reserved1; /* reserved (for offset or index) */ | ||
| 90 | uint32_t reserved2; /* reserved (for count or sizeof) */ | ||
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | struct section_64 { /* for 64-bit architectures */ | 93 | struct section_64 { /* for 64-bit architectures */ |
| 94 | char sectname[16]; /* name of this section */ | 94 | char sectname[16]; /* name of this section */ |
| 95 | char segname[16]; /* segment this section goes in */ | 95 | char segname[16]; /* segment this section goes in */ |
| 96 | uint64_t addr; /* memory address of this section */ | 96 | uint64_t addr; /* memory address of this section */ |
| 97 | uint64_t size; /* size in bytes of this section */ | 97 | uint64_t size; /* size in bytes of this section */ |
| 98 | uint32_t offset; /* file offset of this section */ | 98 | uint32_t offset; /* file offset of this section */ |
| 99 | uint32_t align; /* section alignment (power of 2) */ | 99 | uint32_t align; /* section alignment (power of 2) */ |
| 100 | uint32_t reloff; /* file offset of relocation entries */ | 100 | uint32_t reloff; /* file offset of relocation entries */ |
| 101 | uint32_t nreloc; /* number of relocation entries */ | 101 | uint32_t nreloc; /* number of relocation entries */ |
| 102 | uint32_t flags; /* flags (section type and attributes)*/ | 102 | uint32_t flags; /* flags (section type and attributes)*/ |
| 103 | uint32_t reserved1; /* reserved (for offset or index) */ | 103 | uint32_t reserved1; /* reserved (for offset or index) */ |
| 104 | uint32_t reserved2; /* reserved (for count or sizeof) */ | 104 | uint32_t reserved2; /* reserved (for count or sizeof) */ |
| 105 | uint32_t reserved3; /* reserved */ | 105 | uint32_t reserved3; /* reserved */ |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | #define S_REGULAR 0x0 | ||
| 109 | #define S_ZEROFILL 0x1 | ||
| 110 | #define S_NON_LAZY_SYMBOL_POINTERS 0x6 | ||
| 111 | #define S_MOD_INIT_FUNC_POINTERS 0x9 | ||
| 112 | #define S_MOD_TERM_FUNC_POINTERS 0xa | ||
| 113 | |||
| 114 | #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 | ||
| 115 | #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 | ||
| 116 | |||
| 108 | typedef uint32_t lc_str; | 117 | typedef uint32_t lc_str; |
| 109 | 118 | ||
| 110 | struct dylib_command { | 119 | struct dylib_command { |
| 111 | uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, | 120 | uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, |
| 112 | LC_REEXPORT_DYLIB */ | 121 | LC_REEXPORT_DYLIB */ |
| 113 | uint32_t cmdsize; /* includes pathname string */ | 122 | uint32_t cmdsize; /* includes pathname string */ |
| 114 | lc_str name; /* library's path name */ | 123 | lc_str name; /* library's path name */ |
| 115 | uint32_t timestamp; /* library's build time stamp */ | 124 | uint32_t timestamp; /* library's build time stamp */ |
| 116 | uint32_t current_version; /* library's current version number */ | 125 | uint32_t current_version; /* library's current version number */ |
| 117 | uint32_t compatibility_version; /* library's compatibility vers number*/ | 126 | uint32_t compatibility_version; /* library's compatibility vers number*/ |
| 118 | }; | 127 | }; |
| 119 | 128 | ||
| 120 | struct dylinker_command { | 129 | struct dylinker_command { |
| 121 | uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or | 130 | uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or |
| 122 | LC_DYLD_ENVIRONMENT */ | 131 | LC_DYLD_ENVIRONMENT */ |
| 123 | uint32_t cmdsize; /* includes pathname string */ | 132 | uint32_t cmdsize; /* includes pathname string */ |
| 124 | lc_str name; /* dynamic linker's path name */ | 133 | lc_str name; /* dynamic linker's path name */ |
| 125 | }; | 134 | }; |
| 126 | 135 | ||
| 127 | struct symtab_command { | 136 | struct symtab_command { |
| 128 | uint32_t cmd; /* LC_SYMTAB */ | 137 | uint32_t cmd; /* LC_SYMTAB */ |
| 129 | uint32_t cmdsize; /* sizeof(struct symtab_command) */ | 138 | uint32_t cmdsize; /* sizeof(struct symtab_command) */ |
| 130 | uint32_t symoff; /* symbol table offset */ | 139 | uint32_t symoff; /* symbol table offset */ |
| 131 | uint32_t nsyms; /* number of symbol table entries */ | 140 | uint32_t nsyms; /* number of symbol table entries */ |
| 132 | uint32_t stroff; /* string table offset */ | 141 | uint32_t stroff; /* string table offset */ |
| 133 | uint32_t strsize; /* string table size in bytes */ | 142 | uint32_t strsize; /* string table size in bytes */ |
| 134 | }; | 143 | }; |
| 135 | 144 | ||
| 136 | struct dysymtab_command { | 145 | struct dysymtab_command { |
| @@ -152,28 +161,19 @@ struct dysymtab_command { · 15 unmodified lines | |||
| 152 | uint32_t modtaboff; /* file offset to module table */ | 161 | uint32_t modtaboff; /* file offset to module table */ |
| 153 | uint32_t nmodtab; /* number of module table entries */ | 162 | uint32_t nmodtab; /* number of module table entries */ |
| 154 | 163 | ||
| 155 | uint32_t extrefsymoff; /* offset to referenced symbol table */ | 164 | uint32_t extrefsymoff; /* offset to referenced symbol table */ |
| 156 | uint32_t nextrefsyms; /* number of referenced symbol table entries */ | 165 | uint32_t nextrefsyms; /* number of referenced symbol table entries */ |
| 157 | 166 | ||
| 158 | uint32_t indirectsymoff; /* file offset to the indirect symbol table */ | 167 | uint32_t indirectsymoff;/* file offset to the indirect symbol table */ |
| 159 | uint32_t nindirectsyms; /* number of indirect symbol table entries */ | 168 | uint32_t nindirectsyms; /* number of indirect symbol table entries */ |
| 160 | 169 | ||
| 161 | uint32_t extreloff; /* offset to external relocation entries */ | 170 | uint32_t extreloff; /* offset to external relocation entries */ |
| 162 | uint32_t nextrel; /* number of external relocation entries */ | 171 | uint32_t nextrel; /* number of external relocation entries */ |
| 163 | uint32_t locreloff; /* offset to local relocation entries */ | 172 | uint32_t locreloff; /* offset to local relocation entries */ |
| 164 | uint32_t nlocrel; /* number of local relocation entries */ | 173 | uint32_t nlocrel; /* number of local relocation entries */ |
| 165 | |||
| 166 | }; | 174 | }; |
| 167 | 175 | ||
| 168 | struct linkedit_data_command { | 176 | #define INDIRECT_SYMBOL_LOCAL 0x80000000 |
| 169 | uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, | ||
| 170 | LC_FUNCTION_STARTS, LC_DATA_IN_CODE, | ||
| 171 | LC_DYLIB_CODE_SIGN_DRS or | ||
| 172 | LC_LINKER_OPTIMIZATION_HINT. */ | ||
| 173 | uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ | ||
| 174 | uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ | ||
| 175 | uint32_t datasize; /* file size of data in __LINKEDIT segment */ | ||
| 176 | }; | ||
| 177 | 177 | ||
| 178 | struct entry_point_command { | 178 | struct entry_point_command { |
| 179 | uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ | 179 | uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ |
| @@ -207,20 +207,24 @@ struct nlist_64 { · 27 unmodified lines | |||
| 207 | uint64_t n_value; /* value of this symbol (or stab offset) */ | 207 | uint64_t n_value; /* value of this symbol (or stab offset) */ |
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | #define N_UNDF 0x0 | ||
| 211 | #define N_ABS 0x2 | ||
| 212 | #define N_EXT 0x1 | ||
| 213 | #define N_SECT 0xe | ||
| 214 | |||
| 210 | struct macho { | 215 | struct macho { |
| 211 | struct mach_header_64 mh; | 216 | struct mach_header_64 mh; |
| 212 | struct segment_command_64 *seg[4]; | 217 | int seg2lc[4], nseg; |
| 213 | int nseg; | ||
| 214 | struct load_command **lc; | 218 | struct load_command **lc; |
| 219 | struct entry_point_command *ep; | ||
| 215 | int nlc; | 220 | int nlc; |
| 216 | struct entry_point_command ep; | ||
| 217 | struct { | 221 | struct { |
| 218 | Section *s; | 222 | Section *s; |
| 219 | int machosect; | 223 | int machosect; |
| 220 | } sk_to_sect[sk_last]; | 224 | } sk_to_sect[sk_last]; |
| 221 | int *elfsectomacho; | 225 | int *elfsectomacho; |
| 222 | int *e2msym; | 226 | int *e2msym; |
| 223 | Section *linkedit, *symtab, *strtab, *wdata, *indirsyms, *stubs; | 227 | Section *symtab, *strtab, *wdata, *indirsyms, *stubs; |
| 224 | int stubsym; | 228 | int stubsym; |
| 225 | uint32_t ilocal, iextdef, iundef; | 229 | uint32_t ilocal, iextdef, iundef; |
| 226 | }; | 230 | }; |
| @@ -228,33 +232,29 @@ struct macho { · 1 unmodified line | |||
| 228 | #define SHT_LINKEDIT (SHT_LOOS + 42) | 232 | #define SHT_LINKEDIT (SHT_LOOS + 42) |
| 229 | #define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */ | 233 | #define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */ |
| 230 | 234 | ||
| 231 | #define LC_REQ_DYLD 0x80000000 | 235 | static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize) |
| 232 | #define LC_SYMTAB 0x2 | ||
| 233 | #define LC_DYSYMTAB 0xb | ||
| 234 | #define LC_LOAD_DYLIB 0xc | ||
| 235 | #define LC_ID_DYLIB 0xd | ||
| 236 | #define LC_LOAD_DYLINKER 0xe | ||
| 237 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) | ||
| 238 | #define LC_MAIN (0x28|LC_REQ_DYLD) | ||
| 239 | |||
| 240 | /* Hack for now, 46_grep.c needs fopen, but due to aliasing games | ||
| 241 | in darwin headers it's searching for _fopen also via dlsym. */ | ||
| 242 | FILE *_fopen(const char*, const char*); | ||
| 243 | FILE *_fopen(const char * filename, const char *mode) | ||
| 244 | { | 236 | { |
| 245 | return fopen(filename, mode); | 237 | struct load_command *lc = tcc_mallocz(cmdsize); |
| 238 | lc->cmd = cmd; | ||
| 239 | lc->cmdsize = cmdsize; | ||
| 240 | mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1)); | ||
| 241 | mo->lc[mo->nlc++] = lc; | ||
| 242 | return lc; | ||
| 246 | } | 243 | } |
| 247 | 244 | ||
| 248 | static struct segment_command_64 * add_segment(struct macho *mo, char *name) | 245 | static struct segment_command_64 * add_segment(struct macho *mo, char *name) |
| 249 | { | 246 | { |
| 250 | struct segment_command_64 *sc = tcc_mallocz(sizeof *sc); | 247 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); |
| 251 | strncpy(sc->segname, name, 16); | 248 | strncpy(sc->segname, name, 16); |
| 252 | sc->cmd = 0x19; // LC_SEGMENT_64 | 249 | mo->seg2lc[mo->nseg++] = mo->nlc - 1; |
| 253 | sc->cmdsize = sizeof(*sc); | ||
| 254 | mo->seg[mo->nseg++] = sc; | ||
| 255 | return sc; | 250 | return sc; |
| 256 | } | 251 | } |
| 257 | 252 | ||
| 253 | static struct segment_command_64 * get_segment(struct macho *mo, int i) | ||
| 254 | { | ||
| 255 | return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]); | ||
| 256 | } | ||
| 257 | |||
| 258 | static int add_section(struct macho *mo, struct segment_command_64 **_seg, char *name) | 258 | static int add_section(struct macho *mo, struct segment_command_64 **_seg, char *name) |
| 259 | { | 259 | { |
| 260 | struct segment_command_64 *seg = *_seg; | 260 | struct segment_command_64 *seg = *_seg; |
| @@ -273,31 +273,20 @@ static int add_section(struct macho *mo, struct segment_command_64 **_seg, char · 12 unmodified lines | |||
| 273 | 273 | ||
| 274 | static struct section_64 *get_section(struct segment_command_64 *seg, int i) | 274 | static struct section_64 *get_section(struct segment_command_64 *seg, int i) |
| 275 | { | 275 | { |
| 276 | struct section_64 *sec; | 276 | return (struct section_64*)((char*)seg + sizeof(*seg)) + i; |
| 277 | sec = (struct section_64*)((char*)seg + sizeof(*seg)) + i; | ||
| 278 | return sec; | ||
| 279 | } | ||
| 280 | |||
| 281 | static void * add_lc(struct macho *mo, void *lc) | ||
| 282 | { | ||
| 283 | mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1)); | ||
| 284 | mo->lc[mo->nlc++] = lc; | ||
| 285 | return lc; | ||
| 286 | } | 277 | } |
| 287 | 278 | ||
| 288 | static void * add_dylib(struct macho *mo, char *name) | 279 | static void * add_dylib(struct macho *mo, char *name) |
| 289 | { | 280 | { |
| 290 | struct dylib_command *lc; | 281 | struct dylib_command *lc; |
| 291 | int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8; | 282 | int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8; |
| 292 | lc = tcc_mallocz(sz); | 283 | lc = add_lc(mo, LC_LOAD_DYLIB, sz); |
| 293 | lc->cmd = LC_LOAD_DYLIB; | ||
| 294 | lc->cmdsize = sz; | ||
| 295 | lc->name = sizeof(*lc); | 284 | lc->name = sizeof(*lc); |
| 296 | strcpy((char*)lc + lc->name, name); | 285 | strcpy((char*)lc + lc->name, name); |
| 297 | lc->timestamp = 2; | 286 | lc->timestamp = 2; |
| 298 | lc->current_version = 1 << 16; | 287 | lc->current_version = 1 << 16; |
| 299 | lc->compatibility_version = 1 << 16; | 288 | lc->compatibility_version = 1 << 16; |
| 300 | return add_lc(mo, lc); | 289 | return lc; |
| 301 | } | 290 | } |
| 302 | 291 | ||
| 303 | static void check_relocs(TCCState *s1, struct macho *mo) | 292 | static void check_relocs(TCCState *s1, struct macho *mo) |
| @@ -335,10 +324,10 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 31 unmodified lines | |||
| 335 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { | 324 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { |
| 336 | if (sym->st_shndx == SHN_UNDEF) | 325 | if (sym->st_shndx == SHN_UNDEF) |
| 337 | tcc_error("undefined local symbol???"); | 326 | tcc_error("undefined local symbol???"); |
| 338 | *pi = 0x80000000; /* INDIRECT_SYMBOL_LOCAL */ | 327 | *pi = INDIRECT_SYMBOL_LOCAL; |
| 339 | /* The pointer slot we generated must point to the | 328 | /* The pointer slot we generated must point to the |
| 340 | symbol, whose address is only known after layout, | 329 | symbol, whose address is only known after layout, |
| 341 | so register a simply relocation for that. */ | 330 | so register a simple relocation for that. */ |
| 342 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, | 331 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, |
| 343 | R_DATA_PTR, sym_index); | 332 | R_DATA_PTR, sym_index); |
| 344 | } else | 333 | } else |
| @@ -422,10 +411,10 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) · 77 unmodified lines | |||
| 422 | case STT_OBJECT: | 411 | case STT_OBJECT: |
| 423 | case STT_FUNC: | 412 | case STT_FUNC: |
| 424 | case STT_SECTION: | 413 | case STT_SECTION: |
| 425 | n.n_type = 0xe; /* default type is N_SECT */ | 414 | n.n_type = N_SECT; |
| 426 | break; | 415 | break; |
| 427 | case STT_FILE: | 416 | case STT_FILE: |
| 428 | n.n_type = 2; /* N_ABS */ | 417 | n.n_type = N_ABS; |
| 429 | break; | 418 | break; |
| 430 | default: | 419 | default: |
| 431 | tcc_error("unhandled ELF symbol type %d %s", | 420 | tcc_error("unhandled ELF symbol type %d %s", |
| @@ -434,9 +423,9 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) · 2 unmodified lines | |||
| 434 | if (sym->st_shndx == SHN_UNDEF) | 423 | if (sym->st_shndx == SHN_UNDEF) |
| 435 | tcc_error("should have been rewritten to SHN_FROMDLL"); | 424 | tcc_error("should have been rewritten to SHN_FROMDLL"); |
| 436 | else if (sym->st_shndx == SHN_FROMDLL) | 425 | else if (sym->st_shndx == SHN_FROMDLL) |
| 437 | n.n_type = 0 /* N_UNDF */, n.n_sect = 0; | 426 | n.n_type = N_UNDF, n.n_sect = 0; |
| 438 | else if (sym->st_shndx == SHN_ABS) | 427 | else if (sym->st_shndx == SHN_ABS) |
| 439 | n.n_type = 2 /* N_ABS */, n.n_sect = 0; | 428 | n.n_type = N_ABS, n.n_sect = 0; |
| 440 | else if (sym->st_shndx >= SHN_LORESERVE) | 429 | else if (sym->st_shndx >= SHN_LORESERVE) |
| 441 | tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name); | 430 | tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name); |
| 442 | else if (!mo->elfsectomacho[sym->st_shndx]) | 431 | else if (!mo->elfsectomacho[sym->st_shndx]) |
| @@ -445,7 +434,7 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) · 2 unmodified lines | |||
| 445 | else | 434 | else |
| 446 | n.n_sect = mo->elfsectomacho[sym->st_shndx]; | 435 | n.n_sect = mo->elfsectomacho[sym->st_shndx]; |
| 447 | if (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL) | 436 | if (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL) |
| 448 | n.n_type |= 1; /* N_EXT */ | 437 | n.n_type |= N_EXT; |
| 449 | else if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) | 438 | else if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) |
| 450 | tcc_error("weak symbol %s unhandled", name); | 439 | tcc_error("weak symbol %s unhandled", name); |
| 451 | n.n_strx = pn->n_strx; | 440 | n.n_strx = pn->n_strx; |
| @@ -455,13 +444,9 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) · 3 unmodified lines | |||
| 455 | 444 | ||
| 456 | static void convert_symbols(TCCState *s1, struct macho *mo) | 445 | static void convert_symbols(TCCState *s1, struct macho *mo) |
| 457 | { | 446 | { |
| 458 | int sym_index, sym_end; | 447 | struct nlist_64 *pn; |
| 459 | struct nlist_64 *pn = (struct nlist_64 *)mo->symtab->data; | 448 | for_each_elem(mo->symtab, 0, pn, struct nlist_64) |
| 460 | 449 | convert_symbol(s1, mo, pn); | |
| 461 | sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); | ||
| 462 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { | ||
| 463 | convert_symbol(s1, mo, pn + sym_index - 1); | ||
| 464 | } | ||
| 465 | } | 450 | } |
| 466 | 451 | ||
| 467 | static int machosymcmp(const void *_a, const void *_b) | 452 | static int machosymcmp(const void *_a, const void *_b) |
| @@ -472,6 +457,8 @@ static int machosymcmp(const void *_a, const void *_b) · 4 unmodified lines | |||
| 472 | ElfSym *sa = (ElfSym *)symtab_section->data + ea; | 457 | ElfSym *sa = (ElfSym *)symtab_section->data + ea; |
| 473 | ElfSym *sb = (ElfSym *)symtab_section->data + eb; | 458 | ElfSym *sb = (ElfSym *)symtab_section->data + eb; |
| 474 | int r; | 459 | int r; |
| 460 | /* locals, then defined externals, then undefined externals, the | ||
| 461 | last two sections also by name, otherwise stable sort */ | ||
| 475 | r = (ELFW(ST_BIND)(sb->st_info) == STB_LOCAL) | 462 | r = (ELFW(ST_BIND)(sb->st_info) == STB_LOCAL) |
| 476 | - (ELFW(ST_BIND)(sa->st_info) == STB_LOCAL); | 463 | - (ELFW(ST_BIND)(sa->st_info) == STB_LOCAL); |
| 477 | if (r) | 464 | if (r) |
| @@ -498,7 +485,7 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 20 unmodified lines | |||
| 498 | the symbol now, so its included in the sorting. */ | 485 | the symbol now, so its included in the sorting. */ |
| 499 | mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); | 486 | mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); |
| 500 | mo->stubsym = put_elf_sym(s1->symtab, 0, 0, | 487 | mo->stubsym = put_elf_sym(s1->symtab, 0, 0, |
| 501 | ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE), 0, | 488 | ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0, |
| 502 | mo->stubs->sh_num, ".__stubs"); | 489 | mo->stubs->sh_num, ".__stubs"); |
| 503 | 490 | ||
| 504 | mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 491 | mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| @@ -527,14 +514,15 @@ struct { · 22 unmodified lines | |||
| 527 | uint32_t flags; | 514 | uint32_t flags; |
| 528 | char *name; | 515 | char *name; |
| 529 | } skinfo[sk_last] = { | 516 | } skinfo[sk_last] = { |
| 530 | [sk_text] = { 1, 0x80000400, "__text" }, | 517 | [sk_text] = { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS |
| 531 | [sk_ro_data] = { 1, 0x0, "__rodata" }, | 518 | | S_ATTR_SOME_INSTRUCTIONS, "__text" }, |
| 532 | [sk_nl_ptr] = { 2, 0x6, "__got" }, /* S_NON_LAZY_SYMBOL_POINTERS */ | 519 | [sk_ro_data] = { 1, S_REGULAR, "__rodata" }, |
| 533 | [sk_init] = { 2, 0x9, "__mod_init_func" }, /* S_MOD_INIT_FUNC_POINTERS */ | 520 | [sk_nl_ptr] = { 2, S_NON_LAZY_SYMBOL_POINTERS, "__got" }, |
| 534 | [sk_fini] = { 2, 0xa, "__mod_term_func" }, /* S_MOD_TERM_FUNC_POINTERS */ | 521 | [sk_init] = { 2, S_MOD_INIT_FUNC_POINTERS, "__mod_init_func" }, |
| 535 | [sk_rw_data] = { 2, 0x0, "__data" }, | 522 | [sk_fini] = { 2, S_MOD_TERM_FUNC_POINTERS, "__mod_term_func" }, |
| 536 | [sk_bss] = { 2, 0x1, "__bss" }, /* S_ZEROFILL */ | 523 | [sk_rw_data] = { 2, S_REGULAR, "__data" }, |
| 537 | [sk_linkedit] = { 3, 0x0, NULL }, | 524 | [sk_bss] = { 2, S_ZEROFILL, "__bss" }, |
| 525 | [sk_linkedit] = { 3, S_REGULAR, NULL }, | ||
| 538 | }; | 526 | }; |
| 539 | 527 | ||
| 540 | static void collect_sections(TCCState *s1, struct macho *mo) | 528 | static void collect_sections(TCCState *s1, struct macho *mo) |
| @@ -547,46 +535,36 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 6 unmodified lines | |||
| 547 | struct symtab_command *symlc; | 535 | struct symtab_command *symlc; |
| 548 | struct dysymtab_command *dysymlc; | 536 | struct dysymtab_command *dysymlc; |
| 549 | char *str; | 537 | char *str; |
| 550 | //struct segment_command_64 *zc, *tc, *sc, *lc; | 538 | |
| 551 | add_segment(mo, "__PAGEZERO"); | 539 | seg = add_segment(mo, "__PAGEZERO"); |
| 552 | add_segment(mo, "__TEXT"); | 540 | seg->vmsize = (uint64_t)1 << 32; |
| 553 | add_segment(mo, "__DATA"); | 541 | |
| 554 | add_segment(mo, "__LINKEDIT"); | 542 | seg = add_segment(mo, "__TEXT"); |
| 555 | mo->seg[0]->vmsize = (uint64_t)1 << 32; | 543 | seg->vmaddr = (uint64_t)1 << 32; |
| 556 | mo->seg[1]->vmaddr = (uint64_t)1 << 32; | 544 | seg->maxprot = 7; // rwx |
| 557 | mo->seg[1]->maxprot = 7; // rwx | 545 | seg->initprot = 5; // r-x |
| 558 | mo->seg[1]->initprot = 5; // r-x | 546 | |
| 559 | mo->seg[2]->vmaddr = -1; | 547 | seg = add_segment(mo, "__DATA"); |
| 560 | mo->seg[2]->maxprot = 7; // rwx | 548 | seg->vmaddr = -1; |
| 561 | mo->seg[2]->initprot = 3; // rw- | 549 | seg->maxprot = 7; // rwx |
| 562 | mo->seg[3]->vmaddr = -1; | 550 | seg->initprot = 3; // rw- |
| 563 | mo->seg[3]->maxprot = 7; // rwx | 551 | |
| 564 | mo->seg[3]->initprot = 1; // r-- | 552 | seg = add_segment(mo, "__LINKEDIT"); |
| 565 | 553 | seg->vmaddr = -1; | |
| 566 | mo->ep.cmd = LC_MAIN; | 554 | seg->maxprot = 7; // rwx |
| 567 | mo->ep.cmdsize = sizeof(mo->ep); | 555 | seg->initprot = 1; // r-- |
| 568 | mo->ep.entryoff = 4096; | 556 | |
| 569 | mo->ep.stacksize = 0; | 557 | mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| 570 | add_lc(mo, &mo->ep); | 558 | mo->ep->entryoff = 4096; |
| 571 | 559 | ||
| 572 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; | 560 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; |
| 573 | dyldlc = tcc_mallocz(i); | 561 | dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); |
| 574 | dyldlc->cmd = LC_LOAD_DYLINKER; | ||
| 575 | dyldlc->cmdsize = i; | ||
| 576 | dyldlc->name = sizeof(*dyldlc); | 562 | dyldlc->name = sizeof(*dyldlc); |
| 577 | str = (char*)dyldlc + dyldlc->name; | 563 | str = (char*)dyldlc + dyldlc->name; |
| 578 | strcpy(str, "/usr/lib/dyld"); | 564 | strcpy(str, "/usr/lib/dyld"); |
| 579 | add_lc(mo, dyldlc); | ||
| 580 | 565 | ||
| 581 | symlc = tcc_mallocz(sizeof(*symlc)); | 566 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); |
| 582 | symlc->cmd = LC_SYMTAB; | 567 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); |
| 583 | symlc->cmdsize = sizeof(*symlc); | ||
| 584 | add_lc(mo, symlc); | ||
| 585 | |||
| 586 | dysymlc = tcc_mallocz(sizeof(*dysymlc)); | ||
| 587 | dysymlc->cmd = LC_DYSYMTAB; | ||
| 588 | dysymlc->cmdsize = sizeof(*dysymlc); | ||
| 589 | add_lc(mo, dysymlc); | ||
| 590 | 568 | ||
| 591 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 569 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 592 | DLLReference *dllref = s1->loaded_dlls[i]; | 570 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -594,14 +572,9 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 1 unmodified line | |||
| 594 | add_dylib(mo, dllref->name); | 572 | add_dylib(mo, dllref->name); |
| 595 | } | 573 | } |
| 596 | 574 | ||
| 597 | mo->linkedit = new_section(s1, "LINKEDIT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 575 | /* dyld requires a writable segment with classic Mach-O, but it ignores |
| 598 | /* LINKEDIT can't be empty (XXX remove once we have symbol table) */ | 576 | zero-sized segments for this, so force to have some data. */ |
| 599 | section_ptr_add(mo->linkedit, 256); | 577 | section_ptr_add(data_section, 1); |
| 600 | |||
| 601 | /* dyld requires a writable segment, but ignores zero-sized segments | ||
| 602 | for this, so force to have some data. */ | ||
| 603 | mo->wdata = new_section(s1, " wdata", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); | ||
| 604 | section_ptr_add(mo->wdata, 64); | ||
| 605 | memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); | 578 | memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); |
| 606 | for (i = s1->nb_sections; i-- > 1;) { | 579 | for (i = s1->nb_sections; i-- > 1;) { |
| 607 | int type, flags; | 580 | int type, flags; |
| @@ -636,7 +609,7 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 28 unmodified lines | |||
| 636 | mo->sk_to_sect[sk].s = s; | 609 | mo->sk_to_sect[sk].s = s; |
| 637 | } | 610 | } |
| 638 | fileofs = 4096; /* leave space for mach-o headers */ | 611 | fileofs = 4096; /* leave space for mach-o headers */ |
| 639 | curaddr = mo->seg[1]->vmaddr; | 612 | curaddr = get_segment(mo, 1)->vmaddr; |
| 640 | curaddr += 4096; | 613 | curaddr += 4096; |
| 641 | seg = NULL; | 614 | seg = NULL; |
| 642 | numsec = 0; | 615 | numsec = 0; |
| @@ -650,11 +623,11 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 7 unmodified lines | |||
| 650 | if (skinfo[sk].seg && mo->sk_to_sect[sk].s) { | 623 | if (skinfo[sk].seg && mo->sk_to_sect[sk].s) { |
| 651 | uint64_t al = 0; | 624 | uint64_t al = 0; |
| 652 | int si; | 625 | int si; |
| 653 | seg = mo->seg[skinfo[sk].seg]; | 626 | seg = get_segment(mo, skinfo[sk].seg); |
| 654 | if (skinfo[sk].name) { | 627 | if (skinfo[sk].name) { |
| 655 | si = add_section(mo, &seg, skinfo[sk].name); | 628 | si = add_section(mo, &seg, skinfo[sk].name); |
| 656 | numsec++; | 629 | numsec++; |
| 657 | mo->seg[skinfo[sk].seg] = seg; | 630 | mo->lc[mo->seg2lc[skinfo[sk].seg]] = (struct load_command*)seg; |
| 658 | mo->sk_to_sect[sk].machosect = si; | 631 | mo->sk_to_sect[sk].machosect = si; |
| 659 | sec = get_section(seg, si); | 632 | sec = get_section(seg, si); |
| 660 | sec->flags = skinfo[sk].flags; | 633 | sec->flags = skinfo[sk].flags; |
| @@ -755,19 +728,13 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) · 94 unmodified lines | |||
| 755 | mo->mh.mh.cpusubtype = 0x80000003;// all | CPU_SUBTYPE_LIB64 | 728 | mo->mh.mh.cpusubtype = 0x80000003;// all | CPU_SUBTYPE_LIB64 |
| 756 | mo->mh.mh.filetype = 2; // MH_EXECUTE | 729 | mo->mh.mh.filetype = 2; // MH_EXECUTE |
| 757 | mo->mh.mh.flags = 4; // DYLDLINK | 730 | mo->mh.mh.flags = 4; // DYLDLINK |
| 758 | mo->mh.mh.ncmds = mo->nseg + mo->nlc; | 731 | mo->mh.mh.ncmds = mo->nlc; |
| 759 | mo->mh.mh.sizeofcmds = 0; | 732 | mo->mh.mh.sizeofcmds = 0; |
| 760 | for (i = 0; i < mo->nseg; i++) | ||
| 761 | mo->mh.mh.sizeofcmds += mo->seg[i]->cmdsize; | ||
| 762 | for (i = 0; i < mo->nlc; i++) | 733 | for (i = 0; i < mo->nlc; i++) |
| 763 | mo->mh.mh.sizeofcmds += mo->lc[i]->cmdsize; | 734 | mo->mh.mh.sizeofcmds += mo->lc[i]->cmdsize; |
| 764 | 735 | ||
| 765 | fwrite(&mo->mh, 1, sizeof(mo->mh), fp); | 736 | fwrite(&mo->mh, 1, sizeof(mo->mh), fp); |
| 766 | fileofs += sizeof(mo->mh); | 737 | fileofs += sizeof(mo->mh); |
| 767 | for (i = 0; i < mo->nseg; i++) { | ||
| 768 | fwrite(mo->seg[i], 1, mo->seg[i]->cmdsize, fp); | ||
| 769 | fileofs += mo->seg[i]->cmdsize; | ||
| 770 | } | ||
| 771 | for (i = 0; i < mo->nlc; i++) { | 738 | for (i = 0; i < mo->nlc; i++) { |
| 772 | fwrite(mo->lc[i], 1, mo->lc[i]->cmdsize, fp); | 739 | fwrite(mo->lc[i], 1, mo->lc[i]->cmdsize, fp); |
| 773 | fileofs += mo->lc[i]->cmdsize; | 740 | fileofs += mo->lc[i]->cmdsize; |
| @@ -775,13 +742,9 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) · 1 unmodified line | |||
| 775 | 742 | ||
| 776 | for (sk = sk_unknown; sk < sk_last; sk++) { | 743 | for (sk = sk_unknown; sk < sk_last; sk++) { |
| 777 | struct segment_command_64 *seg; | 744 | struct segment_command_64 *seg; |
| 778 | //struct section_64 *sec; | ||
| 779 | if (!skinfo[sk].seg || !mo->sk_to_sect[sk].s) | 745 | if (!skinfo[sk].seg || !mo->sk_to_sect[sk].s) |
| 780 | continue; | 746 | continue; |
| 781 | seg = mo->seg[skinfo[sk].seg]; | 747 | seg = get_segment(mo, skinfo[sk].seg); |
| 782 | /*sec = get_section(seg, mo->sk_to_sect[sk].machosect); | ||
| 783 | while (fileofs < sec->offset) | ||
| 784 | fputc(0, fp), fileofs++;*/ | ||
| 785 | for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { | 748 | for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { |
| 786 | if (s->sh_type != SHT_NOBITS) { | 749 | if (s->sh_type != SHT_NOBITS) { |
| 787 | while (fileofs < s->sh_offset) | 750 | while (fileofs < s->sh_offset) |
| @@ -827,7 +790,8 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 39 unmodified lines | |||
| 827 | Section *s; | 790 | Section *s; |
| 828 | collect_sections(s1, &mo); | 791 | collect_sections(s1, &mo); |
| 829 | relocate_syms(s1, s1->symtab, 0); | 792 | relocate_syms(s1, s1->symtab, 0); |
| 830 | mo.ep.entryoff = get_sym_addr(s1, "_main", 1, 0) - mo.seg[1]->vmaddr; | 793 | mo.ep->entryoff = get_sym_addr(s1, "_main", 1, 0) |
| 794 | - get_segment(&mo, 1)->vmaddr; | ||
| 831 | if (s1->nb_errors) | 795 | if (s1->nb_errors) |
| 832 | goto do_ret; | 796 | goto do_ret; |
| 833 | 797 | ||
| @@ -847,25 +811,12 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 13 unmodified lines | |||
| 847 | return ret; | 811 | return ret; |
| 848 | } | 812 | } |
| 849 | 813 | ||
| 850 | #define FAT_MAGIC 0xcafebabe | 814 | static uint32_t swap32(uint32_t x) |
| 851 | #define FAT_CIGAM 0xbebafeca | 815 | { |
| 852 | #define FAT_MAGIC_64 0xcafebabf | 816 | return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8); |
| 853 | #define FAT_CIGAM_64 0xbfbafeca | 817 | } |
| 854 | 818 | #define SWAP(x) (swap ? swap32(x) : (x)) | |
| 855 | struct fat_header { | ||
| 856 | uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */ | ||
| 857 | uint32_t nfat_arch; /* number of structs that follow */ | ||
| 858 | }; | ||
| 859 | |||
| 860 | struct fat_arch { | ||
| 861 | int cputype; /* cpu specifier (int) */ | ||
| 862 | int cpusubtype; /* machine specifier (int) */ | ||
| 863 | uint32_t offset; /* file offset to this object file */ | ||
| 864 | uint32_t size; /* size of this object file */ | ||
| 865 | uint32_t align; /* alignment as a power of 2 */ | ||
| 866 | }; | ||
| 867 | 819 | ||
| 868 | #define SWAP(x) (swap ? ntohl(x) : (x)) | ||
| 869 | ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) | 820 | ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) |
| 870 | { | 821 | { |
| 871 | unsigned char buf[sizeof(struct mach_header_64)]; | 822 | unsigned char buf[sizeof(struct mach_header_64)]; |
| @@ -917,19 +868,27 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 45 unmodified lines | |||
| 917 | buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds); | 868 | buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds); |
| 918 | for (i = 0, lc = buf2; i < mh.ncmds; i++) { | 869 | for (i = 0, lc = buf2; i < mh.ncmds; i++) { |
| 919 | dprintf("lc %2d: 0x%08x\n", i, lc->cmd); | 870 | dprintf("lc %2d: 0x%08x\n", i, lc->cmd); |
| 920 | if (lc->cmd == LC_SYMTAB) { | 871 | switch (lc->cmd) { |
| 872 | case LC_SYMTAB: | ||
| 873 | { | ||
| 921 | struct symtab_command *sc = (struct symtab_command*)lc; | 874 | struct symtab_command *sc = (struct symtab_command*)lc; |
| 922 | nsyms = sc->nsyms; | 875 | nsyms = sc->nsyms; |
| 923 | symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab)); | 876 | symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab)); |
| 924 | strsize = sc->strsize; | 877 | strsize = sc->strsize; |
| 925 | strtab = load_data(fd, machofs + sc->stroff, strsize); | 878 | strtab = load_data(fd, machofs + sc->stroff, strsize); |
| 926 | } else if (lc->cmd == LC_ID_DYLIB) { | 879 | break; |
| 880 | } | ||
| 881 | case LC_ID_DYLIB: | ||
| 882 | { | ||
| 927 | struct dylib_command *dc = (struct dylib_command*)lc; | 883 | struct dylib_command *dc = (struct dylib_command*)lc; |
| 928 | soname = (char*)lc + dc->name; | 884 | soname = (char*)lc + dc->name; |
| 929 | dprintf(" ID_DYLIB %d 0x%x 0x%x %s\n", | 885 | dprintf(" ID_DYLIB %d 0x%x 0x%x %s\n", |
| 930 | dc->timestamp, dc->current_version, | 886 | dc->timestamp, dc->current_version, |
| 931 | dc->compatibility_version, soname); | 887 | dc->compatibility_version, soname); |
| 932 | } else if (lc->cmd == LC_REEXPORT_DYLIB) { | 888 | break; |
| 889 | } | ||
| 890 | case LC_REEXPORT_DYLIB: | ||
| 891 | { | ||
| 933 | struct dylib_command *dc = (struct dylib_command*)lc; | 892 | struct dylib_command *dc = (struct dylib_command*)lc; |
| 934 | char *name = (char*)lc + dc->name; | 893 | char *name = (char*)lc + dc->name; |
| 935 | dprintf(" REEXPORT %s\n", name); | 894 | dprintf(" REEXPORT %s\n", name); |
| @@ -942,10 +901,15 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev) · 6 unmodified lines | |||
| 942 | macho_load_dll(s1, subfd, name, lev + 1); | 901 | macho_load_dll(s1, subfd, name, lev + 1); |
| 943 | close(subfd); | 902 | close(subfd); |
| 944 | } | 903 | } |
| 945 | } else if (lc->cmd == LC_DYSYMTAB) { | 904 | break; |
| 905 | } | ||
| 906 | case LC_DYSYMTAB: | ||
| 907 | { | ||
| 946 | struct dysymtab_command *dc = (struct dysymtab_command*)lc; | 908 | struct dysymtab_command *dc = (struct dysymtab_command*)lc; |
| 947 | iextdef = dc->iextdefsym; | 909 | iextdef = dc->iextdefsym; |
| 948 | nextdef = dc->nextdefsym; | 910 | nextdef = dc->nextdefsym; |
| 911 | break; | ||
| 912 | } | ||
| 949 | } | 913 | } |
| 950 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); | 914 | lc = (struct load_command*) ((char*)lc + lc->cmdsize); |
| 951 | } | 915 | } |