History

macos: Tidy code

Michael Matz committed 6 years ago

Commit ac86fb51 parent c86760c1 file · +195 −231Browse files

Unified · Split

tccmacho.c+195−231
@@ -1,5 +1,5 @@
1/*1/*
2 * Mach-O file handling for TCC2 * Mach-O file handling for TCC
3 *3 *
4 * This library is free software; you can redistribute it and/or4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public5 * modify it under the terms of the GNU Lesser General Public
@@ -20,14 +20,32 @@ · 14 unmodified lines
20#define DEBUG_MACHO 020#define DEBUG_MACHO 0
21#define dprintf if (DEBUG_MACHO) printf21#define dprintf if (DEBUG_MACHO) printf
22 22
23struct fat_header {
24 uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
25 uint32_t nfat_arch; /* number of structs that follow */
26};
27
28struct 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
23struct mach_header {41struct 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
33struct mach_header_64 {51struct 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
44struct load_command {62struct 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
49typedef 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
51struct segment_command { /* for 32-bit architectures */77typedef 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
65struct segment_command_64 { /* for 64-bit architectures */79struct 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
79struct 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
93struct section_64 { /* for 64-bit architectures */93struct 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
108typedef uint32_t lc_str;117typedef uint32_t lc_str;
109 118
110struct dylib_command {119struct 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
120struct dylinker_command {129struct dylinker_command {
121 uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or130 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
127struct symtab_command {136struct 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
136struct dysymtab_command {145struct 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
168struct 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
178struct entry_point_command {178struct 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
210struct macho {215struct 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 0x80000000235static 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. */
242FILE *_fopen(const char*, const char*);
243FILE *_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
248static struct segment_command_64 * add_segment(struct macho *mo, char *name)245static 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_64249 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
253static 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
258static int add_section(struct macho *mo, struct segment_command_64 **_seg, char *name)258static 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
274static struct section_64 *get_section(struct segment_command_64 *seg, int i)274static 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
281static 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
288static void * add_dylib(struct macho *mo, char *name)279static 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
303static void check_relocs(TCCState *s1, struct macho *mo)292static 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 the328 /* 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 } else333 } 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 else434 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
456static void convert_symbols(TCCState *s1, struct macho *mo)445static 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
467static int machosymcmp(const void *_a, const void *_b)452static 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
540static void collect_sections(TCCState *s1, struct macho *mo)528static 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; // rwx545 seg->initprot = 5; // r-x
558 mo->seg[1]->initprot = 5; // r-x546
559 mo->seg[2]->vmaddr = -1;547 seg = add_segment(mo, "__DATA");
560 mo->seg[2]->maxprot = 7; // rwx548 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; // rwx551
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_LIB64728 mo->mh.mh.cpusubtype = 0x80000003;// all | CPU_SUBTYPE_LIB64
756 mo->mh.mh.filetype = 2; // MH_EXECUTE729 mo->mh.mh.filetype = 2; // MH_EXECUTE
757 mo->mh.mh.flags = 4; // DYLDLINK730 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 0xcafebabe814static uint32_t swap32(uint32_t x)
851#define FAT_CIGAM 0xbebafeca815{
852#define FAT_MAGIC_64 0xcafebabf816 return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8);
853#define FAT_CIGAM_64 0xbfbafeca817}
854 818#define SWAP(x) (swap ? swap32(x) : (x))
855struct fat_header {
856 uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
857 uint32_t nfat_arch; /* number of structs that follow */
858};
859
860struct 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))
869ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)820ST_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 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t