History

Add new macho object format to tccmacho

Apple has a new object format that uses chained fixups. I have implemented this with a configure option '--config-new_macho' See configure and Makefile tccmacho.c contains the biggest change. I split the lazy_bind_rebase structure into lazy_bind and rebase for the old format. Under the macro CONFIG_NEW_MACHO there is the new macho format code. In arm64-gen.c we do not need to push all registers on stack for variadic functions. variadic parameters are pushed on stack for apple. There is still one open isue. The export trie is empty. This only effects dlsym when a local symbol is used. tested on apple x86_64(10.5) and arm64(12.3).

herman ten brugge committed 3 years ago

Commit b86d82c1 parent d605d754 files · +597 −84Browse files

Unified · Split

4 files
  1. Makefile +1 −0
  2. arm64-gen.c +2 −2
  3. configure +1 −0
  4. tccmacho.c +593 −82
Makefile+1−0
@@ -93,6 +93,7 @@ NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS) · 92 unmodified lines
93NATIVE_DEFINES_$(CONFIG_Android) += -DTARGETOS_ANDROID93NATIVE_DEFINES_$(CONFIG_Android) += -DTARGETOS_ANDROID
94NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE94NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE
95NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC95NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC
96NATIVE_DEFINES_$(CONFIG_new_macho) += -DCONFIG_NEW_MACHO
96NATIVE_DEFINES_$(CONFIG_new-dtags) += -DCONFIG_NEW_DTAGS97NATIVE_DEFINES_$(CONFIG_new-dtags) += -DCONFIG_NEW_DTAGS
97NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=098NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0
98NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=099NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0
arm64-gen.c+2−2
@@ -1202,16 +1202,16 @@ ST_FUNC void gfunc_prolog(Sym *func_sym) · 1201 unmodified lines
1202 1202
1203 arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, n - 1, t, a);1203 arm64_func_va_list_stack = arm64_pcs(variadic ? var_nb_arg : 0, n - 1, t, a);
1204 1204
1205#if !defined(__APPLE__)
1205 if (variadic) {1206 if (variadic) {
1206 use_x8 = 1;1207 use_x8 = 1;
1207 last_int = 4;1208 last_int = 4;
1208 last_float = 4;1209 last_float = 4;
1209 }1210 }
1211#endif
1210 if (a && a[0] == 1)1212 if (a && a[0] == 1)
1211 use_x8 = 1;1213 use_x8 = 1;
1212 for (i = 1, sym = func_type->ref->next; sym; i++, sym = sym->next) {1214 for (i = 1, sym = func_type->ref->next; sym; i++, sym = sym->next) {
1213 if (a[i] == 1)
1214 use_x8 = 1;
1215 if (a[i] < 16) {1215 if (a[i] < 16) {
1216 int last, align, size = type_size(&sym->type, &align);1216 int last, align, size = type_size(&sym->type, &align);
1217 last = a[i] / 4 + 1 + (size - 1) / 8;1217 last = a[i] / 4 + 1 + (size - 1) / 8;
configure+1−0
@@ -350,6 +350,7 @@ Advanced options (experts only): · 349 unmodified lines
350 --config-backtrace=no disable stack backtraces (with -run or -bt)350 --config-backtrace=no disable stack backtraces (with -run or -bt)
351 --config-bcheck=no disable bounds checker (-b)351 --config-bcheck=no disable bounds checker (-b)
352 --config-predefs=no do not compile tccdefs.h, instead just include352 --config-predefs=no do not compile tccdefs.h, instead just include
353 --config-new_macho Use apple new macho object format
353 --dwarf=x Use dwarf debug info instead of stabs (x=2..5)354 --dwarf=x Use dwarf debug info instead of stabs (x=2..5)
354EOF355EOF
355exit 1356exit 1
tccmacho.c+593−82
@@ -107,6 +107,8 @@ struct load_command { · 106 unmodified lines
107#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)107#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)
108#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)108#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)
109#define LC_MAIN (0x28|LC_REQ_DYLD)109#define LC_MAIN (0x28|LC_REQ_DYLD)
110#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD)
111#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD)
110 112
111typedef int vm_prot_t;113typedef int vm_prot_t;
112 114
@@ -139,6 +141,79 @@ struct section_64 { /* for 64-bit architectures */ · 26 unmodified lines
139 uint32_t reserved3; /* reserved */141 uint32_t reserved3; /* reserved */
140};142};
141 143
144enum {
145 DYLD_CHAINED_IMPORT = 1,
146};
147
148struct dyld_chained_fixups_header {
149 uint32_t fixups_version; ///< 0
150 uint32_t starts_offset; ///< Offset of dyld_chained_starts_in_image.
151 uint32_t imports_offset; ///< Offset of imports table in chain_data.
152 uint32_t symbols_offset; ///< Offset of symbol strings in chain_data.
153 uint32_t imports_count; ///< Number of imported symbol names.
154 uint32_t imports_format; ///< DYLD_CHAINED_IMPORT*
155 uint32_t symbols_format; ///< 0 => uncompressed, 1 => zlib compressed
156};
157
158struct dyld_chained_starts_in_image
159{
160 uint32_t seg_count;
161 uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment
162 // followed by pool of dyld_chain_starts_in_segment data
163};
164
165enum {
166 DYLD_CHAINED_PTR_64 = 2, // target is vmaddr
167 DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset
168};
169
170enum {
171 DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups
172};
173
174#define SEG_PAGE_SIZE 16384
175
176struct dyld_chained_starts_in_segment
177{
178 uint32_t size; // size of this (amount kernel needs to copy)
179 uint16_t page_size; // 0x1000 or 0x4000
180 uint16_t pointer_format; // DYLD_CHAINED_PTR_*
181 uint64_t segment_offset; // offset in memory to start of segment
182 uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer
183 uint16_t page_count; // how many pages are in array
184 uint16_t page_start[1]; // each entry is offset in each page of first element in chain
185 // or DYLD_CHAINED_PTR_START_NONE if no fixups on page
186};
187
188enum BindSpecialDylib {
189 BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2,
190};
191
192struct dyld_chained_import
193{
194 uint32_t lib_ordinal : 8,
195 weak_import : 1,
196 name_offset : 23;
197};
198
199struct dyld_chained_ptr_64_rebase
200{
201 uint64_t target : 36, // vmaddr, 64GB max image size
202 high8 : 8, // top 8 bits set to this after slide added
203 reserved : 7, // all zeros
204 next : 12, // 4-byte stride
205 bind : 1; // == 0
206};
207
208struct dyld_chained_ptr_64_bind
209{
210 uint64_t ordinal : 24,
211 addend : 8, // 0 thru 255
212 reserved : 19, // all zeros
213 next : 12, // 4-byte stride
214 bind : 1; // == 1
215};
216
142#define S_REGULAR 0x0217#define S_REGULAR 0x0
143#define S_ZEROFILL 0x1218#define S_ZEROFILL 0x1
144#define S_NON_LAZY_SYMBOL_POINTERS 0x6219#define S_NON_LAZY_SYMBOL_POINTERS 0x6
@@ -169,6 +244,18 @@ struct dylinker_command { · 24 unmodified lines
169 lc_str name; /* dynamic linker's path name */244 lc_str name; /* dynamic linker's path name */
170};245};
171 246
247struct linkedit_data_command {
248 uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
249 LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
250 LC_DYLIB_CODE_SIGN_DRS,
251 LC_LINKER_OPTIMIZATION_HINT,
252 LC_DYLD_EXPORTS_TRIE, or
253 LC_DYLD_CHAINED_FIXUPS. */
254 uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
255 uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
256 uint32_t datasize; /* file size of data in __LINKEDIT segment */
257};
258
172struct symtab_command {259struct symtab_command {
173 uint32_t cmd; /* LC_SYMTAB */260 uint32_t cmd; /* LC_SYMTAB */
174 uint32_t cmdsize; /* sizeof(struct symtab_command) */261 uint32_t cmdsize; /* sizeof(struct symtab_command) */
@@ -226,6 +313,10 @@ struct dysymtab_command { · 51 unmodified lines
226 313
227#define REBASE_TYPE_POINTER 1314#define REBASE_TYPE_POINTER 1
228 315
316#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00
317#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02
318#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04
319
229struct dyld_info_command {320struct dyld_info_command {
230 uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */321 uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
231 uint32_t cmdsize; /* sizeof(struct dyld_info_command) */322 uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
@@ -304,26 +395,41 @@ struct macho { · 72 unmodified lines
304 } sk_to_sect[sk_last];395 } sk_to_sect[sk_last];
305 int *elfsectomacho;396 int *elfsectomacho;
306 int *e2msym;397 int *e2msym;
307 Section *rebase, *binding, *weak_binding, *lazy_binding, *exports;398 Section *symtab, *strtab, *wdata, *indirsyms, *stubs, *exports;
308 Section *symtab, *strtab, *wdata, *indirsyms;
309 Section *stubs, *stub_helper, *la_symbol_ptr;
310 int nr_plt, n_got;
311 struct dyld_info_command *dyldinfo;
312 int stubsym, helpsym, lasym, dyld_private, dyld_stub_binder;
313 uint32_t ilocal, iextdef, iundef;399 uint32_t ilocal, iextdef, iundef;
314 int n_lazy_bind_rebase; 400 int stubsym, n_got, nr_plt;
315 struct lazy_bind_rebase {401#ifdef CONFIG_NEW_MACHO
402 Section *chained_fixups;
403 int n_bind;
404 int n_bind_rebase;
405 struct bind_rebase {
406 int section;
407 int bind;
408 ElfW_Rel rel;
409 } *bind_rebase;
410#else
411 Section *rebase, *binding, *weak_binding, *lazy_binding;
412 Section *stub_helper, *la_symbol_ptr;
413 struct dyld_info_command *dyldinfo;
414 int helpsym, lasym, dyld_private, dyld_stub_binder;
415 int n_lazy_bind;
416 struct s_lazy_bind {
316 int section;417 int section;
317 int bind;
318 int bind_offset;418 int bind_offset;
319 int la_symbol_offset;419 int la_symbol_offset;
320 ElfW_Rel rel;420 ElfW_Rel rel;
321 } *lazy_bind_rebase;421 } *s_lazy_bind;
422 int n_rebase;
423 struct s_rebase {
424 int section;
425 ElfW_Rel rel;
426 } *s_rebase;
322 int n_bind; 427 int n_bind;
323 struct bind {428 struct bind {
324 int section;429 int section;
325 ElfW_Rel rel;430 ElfW_Rel rel;
326 } *bind;431 } *bind;
432#endif
327};433};
328 434
329#define SHT_LINKEDIT (SHT_LOOS + 42)435#define SHT_LINKEDIT (SHT_LOOS + 42)
@@ -386,6 +492,7 @@ static void * add_dylib(struct macho *mo, char *name) · 56 unmodified lines
386 return lc;492 return lc;
387}493}
388 494
495#ifndef CONFIG_NEW_MACHO
389static void write_uleb128(Section *section, uint64_t value)496static void write_uleb128(Section *section, uint64_t value)
390{497{
391 do {498 do {
@@ -396,6 +503,7 @@ static void write_uleb128(Section *section, uint64_t value) · 4 unmodified lines
396 *ptr = byte | (value ? 0x80 : 0);503 *ptr = byte | (value ? 0x80 : 0);
397 } while (value != 0);504 } while (value != 0);
398}505}
506#endif
399 507
400static void tcc_macho_add_destructor(TCCState *s1)508static void tcc_macho_add_destructor(TCCState *s1)
401{509{
@@ -492,6 +600,135 @@ static void tcc_macho_add_destructor(TCCState *s1) · 90 unmodified lines
492 add_array (s1, ".init_array", init_sym);600 add_array (s1, ".init_array", init_sym);
493}601}
494 602
603#ifdef CONFIG_NEW_MACHO
604static void bind_rebase_add(struct macho *mo, int bind, int sh_info,
605 ElfW_Rel *rel, struct sym_attr *attr)
606{
607 mo->bind_rebase = tcc_realloc(mo->bind_rebase, (mo->n_bind_rebase + 1) *
608 sizeof(struct bind_rebase));
609 mo->bind_rebase[mo->n_bind_rebase].section = sh_info;
610 mo->bind_rebase[mo->n_bind_rebase].bind = bind;
611 mo->bind_rebase[mo->n_bind_rebase].rel = *rel;
612 if (attr)
613 mo->bind_rebase[mo->n_bind_rebase].rel.r_offset = attr->got_offset;
614 mo->n_bind_rebase++;
615 mo->n_bind += bind;
616}
617
618static void check_relocs(TCCState *s1, struct macho *mo)
619{
620 Section *s;
621 ElfW_Rel *rel;
622 ElfW(Sym) *sym;
623 int i, type, gotplt_entry, sym_index, for_code;
624 int sh_num, debug;
625 uint32_t *pi, *goti;
626 struct sym_attr *attr;
627
628 mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
629 goti = NULL;
630 mo->nr_plt = mo->n_got = 0;
631 for (i = 1; i < s1->nb_sections; i++) {
632 s = s1->sections[i];
633 if (s->sh_type != SHT_RELX)
634 continue;
635 sh_num = s1->sections[s->sh_info]->sh_num;
636 debug = sh_num >= s1->dwlo && sh_num < s1->dwhi;
637 if (debug)
638 continue;
639 for_each_elem(s, 0, rel, ElfW_Rel) {
640 type = ELFW(R_TYPE)(rel->r_info);
641 gotplt_entry = gotplt_entry_type(type);
642 for_code = code_reloc(type);
643 /* We generate a non-lazy pointer for used undefined symbols
644 and for defined symbols that must have a place for their
645 address due to codegen (i.e. a reloc requiring a got slot). */
646 sym_index = ELFW(R_SYM)(rel->r_info);
647 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
648 if (sym->st_shndx == SHN_UNDEF
649 || gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
650 attr = get_sym_attr(s1, sym_index, 1);
651 if (!attr->dyn_index) {
652 attr->got_offset = s1->got->data_offset;
653 attr->plt_offset = -1;
654 attr->dyn_index = 1; /* used as flag */
655 section_ptr_add(s1->got, PTR_SIZE);
656 put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
657 R_DATA_PTR, sym_index);
658 goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
659 if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
660 if (sym->st_shndx == SHN_UNDEF)
661 tcc_error("undefined local symbo: '%s'",
662 (char *) symtab_section->link->data + sym->st_name);
663 goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL;
664 } else {
665 goti[mo->n_got++] = mo->e2msym[sym_index];
666 if (sym->st_shndx == SHN_UNDEF
667#ifdef TCC_TARGET_X86_64
668 && type == R_X86_64_GOTPCREL
669#elif defined TCC_TARGET_ARM64
670 && type == R_AARCH64_ADR_GOT_PAGE
671#endif
672 ) {
673 bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr);
674 attr->plt_offset = 0; // ignore next bind
675 s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
676 }
677 if (for_code)
678 s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
679 }
680 }
681 if (for_code) {
682 if (attr->plt_offset == -1) {
683 uint8_t *jmp;
684
685 attr->plt_offset = mo->stubs->data_offset;
686#ifdef TCC_TARGET_X86_64
687 if (type != R_X86_64_PLT32)
688 continue;
689 jmp = section_ptr_add(mo->stubs, 6);
690 jmp[0] = 0xff; /* jmpq *ofs(%rip) */
691 jmp[1] = 0x25;
692 put_elf_reloc(s1->symtab, mo->stubs,
693 attr->plt_offset + 2,
694 R_X86_64_GOTPCREL, sym_index);
695#elif defined TCC_TARGET_ARM64
696 if (type != R_AARCH64_CALL26)
697 continue;
698 jmp = section_ptr_add(mo->stubs, 12);
699 put_elf_reloc(s1->symtab, mo->stubs,
700 attr->plt_offset,
701 R_AARCH64_ADR_GOT_PAGE, sym_index);
702 write32le(jmp, // adrp x16, #sym
703 0x90000010);
704 put_elf_reloc(s1->symtab, mo->stubs,
705 attr->plt_offset + 4,
706 R_AARCH64_LD64_GOT_LO12_NC, sym_index);
707 write32le(jmp + 4, // ld x16,[x16, #sym]
708 0xf9400210);
709 write32le(jmp + 8, // br x16
710 0xd61f0200);
711#endif
712 bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr);
713 pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
714 *pi = mo->e2msym[sym_index];
715 mo->nr_plt++;
716 }
717 rel->r_info = ELFW(R_INFO)(mo->stubsym, type);
718 rel->r_addend += attr->plt_offset;
719 }
720 }
721 if (type == R_DATA_PTR)
722 bind_rebase_add(mo, 0, s->sh_info, rel, NULL);
723 }
724 }
725 pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
726 memcpy(pi, goti, mo->n_got * sizeof(*pi));
727 tcc_free(goti);
728}
729
730#else
731
495static void check_relocs(TCCState *s1, struct macho *mo)732static void check_relocs(TCCState *s1, struct macho *mo)
496{733{
497 uint8_t *jmp;734 uint8_t *jmp;
@@ -594,9 +831,6 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 96 unmodified lines
594 }831 }
595 if (for_code && sym->st_shndx == SHN_UNDEF) {832 if (for_code && sym->st_shndx == SHN_UNDEF) {
596 if (attr->plt_offset == -1) {833 if (attr->plt_offset == -1) {
597 pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
598 *pi = mo->e2msym[sym_index];
599 mo->nr_plt++;
600 attr->plt_offset = mo->stubs->data_offset;834 attr->plt_offset = mo->stubs->data_offset;
601#ifdef TCC_TARGET_X86_64835#ifdef TCC_TARGET_X86_64
602 if (type != R_X86_64_PLT32)836 if (type != R_X86_64_PLT32)
@@ -623,7 +857,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 20 unmodified lines
623 mo->la_symbol_ptr->data_offset,857 mo->la_symbol_ptr->data_offset,
624 R_DATA_PTR, mo->helpsym,858 R_DATA_PTR, mo->helpsym,
625 mo->stub_helper->data_offset - 10);859 mo->stub_helper->data_offset - 10);
626 jmp = section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);860 section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);
627#elif defined TCC_TARGET_ARM64861#elif defined TCC_TARGET_ARM64
628 if (type != R_AARCH64_CALL26)862 if (type != R_AARCH64_CALL26)
629 continue;863 continue;
@@ -661,35 +895,36 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 31 unmodified lines
661 mo->la_symbol_ptr->data_offset,895 mo->la_symbol_ptr->data_offset,
662 R_DATA_PTR, mo->helpsym,896 R_DATA_PTR, mo->helpsym,
663 mo->stub_helper->data_offset - 12);897 mo->stub_helper->data_offset - 12);
664 jmp = section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);898 section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);
665#endif899#endif
666 mo->lazy_bind_rebase =900 mo->s_lazy_bind =
667 tcc_realloc(mo->lazy_bind_rebase,901 tcc_realloc(mo->s_lazy_bind, (mo->n_lazy_bind + 1) *
668 (mo->n_lazy_bind_rebase + 1) *902 sizeof(struct s_lazy_bind));
669 sizeof(struct lazy_bind_rebase));903 mo->s_lazy_bind[mo->n_lazy_bind].section =
670 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].section =
671 mo->stub_helper->reloc->sh_info;904 mo->stub_helper->reloc->sh_info;
672 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].bind = 1;905 mo->s_lazy_bind[mo->n_lazy_bind].bind_offset =
673 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].bind_offset = bind_offset;906 bind_offset;
674 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].la_symbol_offset = la_symbol_offset;907 mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset =
675 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].rel = *rel;908 la_symbol_offset;
676 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].rel.r_offset =909 mo->s_lazy_bind[mo->n_lazy_bind].rel = *rel;
910 mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset =
677 attr->plt_offset;911 attr->plt_offset;
678 mo->n_lazy_bind_rebase++;912 mo->n_lazy_bind++;
913 pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
914 *pi = mo->e2msym[sym_index];
915 mo->nr_plt++;
679 }916 }
680 rel->r_info = ELFW(R_INFO)(mo->stubsym, type);917 rel->r_info = ELFW(R_INFO)(mo->stubsym, type);
681 rel->r_addend += attr->plt_offset;918 rel->r_addend += attr->plt_offset;
682 }919 }
683 }920 }
684 if (type == R_DATA_PTR) {921 if (type == R_DATA_PTR) {
685 mo->lazy_bind_rebase =922 mo->s_rebase =
686 tcc_realloc(mo->lazy_bind_rebase,923 tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
687 (mo->n_lazy_bind_rebase + 1) *924 sizeof(struct s_rebase));
688 sizeof(struct lazy_bind_rebase));925 mo->s_rebase[mo->n_rebase].section = s->sh_info;
689 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].section = s->sh_info;926 mo->s_rebase[mo->n_rebase].rel = *rel;
690 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].bind = 0;927 mo->n_rebase++;
691 mo->lazy_bind_rebase[mo->n_lazy_bind_rebase].rel = *rel;
692 mo->n_lazy_bind_rebase++;
693 }928 }
694 }929 }
695 }930 }
@@ -699,6 +934,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 3 unmodified lines
699 memcpy(pi, mo->indirsyms->data, mo->nr_plt * sizeof(*pi));934 memcpy(pi, mo->indirsyms->data, mo->nr_plt * sizeof(*pi));
700 tcc_free(goti);935 tcc_free(goti);
701}936}
937#endif
702 938
703static int check_symbols(TCCState *s1, struct macho *mo)939static int check_symbols(TCCState *s1, struct macho *mo)
704{940{
@@ -865,12 +1101,16 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 160 unmodified lines
865 /* Stub creation belongs to check_relocs, but we need to create1101 /* Stub creation belongs to check_relocs, but we need to create
866 the symbol now, so its included in the sorting. */1102 the symbol now, so its included in the sorting. */
867 mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);1103 mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
868 mo->stub_helper = new_section(s1, "__stub_helper", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
869 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);1104 s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
870 mo->la_symbol_ptr = new_section(s1, "__la_symbol_ptr", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
871 mo->stubsym = put_elf_sym(s1->symtab, 0, 0,1105 mo->stubsym = put_elf_sym(s1->symtab, 0, 0,
872 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,1106 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
873 mo->stubs->sh_num, ".__stubs");1107 mo->stubs->sh_num, ".__stubs");
1108#ifdef CONFIG_NEW_MACHO
1109 mo->chained_fixups = new_section(s1, "CHAINED_FIXUPS",
1110 SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
1111#else
1112 mo->stub_helper = new_section(s1, "__stub_helper", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
1113 mo->la_symbol_ptr = new_section(s1, "__la_symbol_ptr", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
874 mo->helpsym = put_elf_sym(s1->symtab, 0, 0,1114 mo->helpsym = put_elf_sym(s1->symtab, 0, 0,
875 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,1115 ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
876 mo->stub_helper->sh_num, ".__stub_helper");1116 mo->stub_helper->sh_num, ".__stub_helper");
@@ -889,6 +1129,7 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 12 unmodified lines
889 mo->binding = new_section(s1, "BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);1129 mo->binding = new_section(s1, "BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
890 mo->weak_binding = new_section(s1, "WEAK_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);1130 mo->weak_binding = new_section(s1, "WEAK_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
891 mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);1131 mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
1132#endif
892 mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);1133 mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
893 1134
894 mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);1135 mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
@@ -942,6 +1183,32 @@ const struct { · 47 unmodified lines
942 /*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },1183 /*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },
943};1184};
944 1185
1186#ifdef CONFIG_NEW_MACHO
1187static void calc_fixup_size(TCCState *s1, struct macho *mo)
1188{
1189 int i, size;
1190
1191 size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
1192 size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8;
1193 for (i = 1; i < mo->nseg - 1; i++) {
1194 int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
1195 size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8;
1196 }
1197 size += mo->n_bind * sizeof (struct dyld_chained_import) + 1;
1198 for (i = 0; i < mo->n_bind_rebase; i++) {
1199 if (mo->bind_rebase[i].bind) {
1200 int sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
1201 ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1202 const char *name = (char *) symtab_section->link->data + sym->st_name;
1203 size += strlen(name) + 1;
1204 }
1205 }
1206 size = (size + 7) & -8;
1207 section_ptr_add(mo->chained_fixups, size);
1208}
1209
1210#else
1211
945static void set_segment_and_offset(struct macho *mo, addr_t addr,1212static void set_segment_and_offset(struct macho *mo, addr_t addr,
946 uint8_t *ptr, int opcode,1213 uint8_t *ptr, int opcode,
947 Section *sec, addr_t offset)1214 Section *sec, addr_t offset)
@@ -958,49 +1225,51 @@ static void set_segment_and_offset(struct macho *mo, addr_t addr, · 10 unmodified lines
958 write_uleb128(sec, offset - seg->vmaddr);1225 write_uleb128(sec, offset - seg->vmaddr);
959}1226}
960 1227
961static void do_bind_rebase(TCCState *s1, struct macho *mo)1228static void bind_rebase(TCCState *s1, struct macho *mo)
962{1229{
963 int i;1230 int i;
964 uint8_t *ptr;1231 uint8_t *ptr;
965 ElfW(Sym) *sym;1232 ElfW(Sym) *sym;
966 char *name;1233 const char *name;
967 1234
968 for (i = 0; i < mo->n_lazy_bind_rebase; i++) {1235 for (i = 0; i < mo->n_lazy_bind; i++) {
969 int sym_index = ELFW(R_SYM)(mo->lazy_bind_rebase[i].rel.r_info);1236 int sym_index = ELFW(R_SYM)(mo->s_lazy_bind[i].rel.r_info);
970 Section *s = s1->sections[mo->lazy_bind_rebase[i].section];
971 1237
972 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];1238 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
973 name = (char *) symtab_section->link->data + sym->st_name;1239 name = (char *) symtab_section->link->data + sym->st_name;
974 if (mo->lazy_bind_rebase[i].bind) {1240 write32le(mo->stub_helper->data +
975 write32le(mo->stub_helper->data +1241 mo->s_lazy_bind[i].bind_offset,
976 mo->lazy_bind_rebase[i].bind_offset,1242 mo->lazy_binding->data_offset);
977 mo->lazy_binding->data_offset);1243 ptr = section_ptr_add(mo->lazy_binding, 1);
978 ptr = section_ptr_add(mo->lazy_binding, 1);1244 set_segment_and_offset(mo, mo->la_symbol_ptr->sh_addr, ptr,
979 set_segment_and_offset(mo, mo->la_symbol_ptr->sh_addr, ptr,1245 BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
980 BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,1246 mo->lazy_binding,
981 mo->lazy_binding,1247 mo->s_lazy_bind[i].la_symbol_offset +
982 mo->la_symbol_ptr->sh_addr +1248 mo->la_symbol_ptr->sh_addr);
983 mo->lazy_bind_rebase[i].la_symbol_offset);1249 ptr = section_ptr_add(mo->lazy_binding, 5 + strlen(name));
984 ptr = section_ptr_add(mo->lazy_binding, 5 + strlen(name));1250 *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
985 *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |1251 (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
986 (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);1252 *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;
987 *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;1253 strcpy(ptr, name);
988 strcpy(ptr, name);1254 ptr += strlen(name) + 1;
989 ptr += strlen(name) + 1;1255 *ptr++ = BIND_OPCODE_DO_BIND;
990 *ptr++ = BIND_OPCODE_DO_BIND;1256 *ptr = BIND_OPCODE_DONE;
991 *ptr = BIND_OPCODE_DONE;1257 }
992 }1258 for (i = 0; i < mo->n_rebase; i++) {
993 else {1259 int sym_index = ELFW(R_SYM)(mo->s_rebase[i].rel.r_info);
994 ptr = section_ptr_add(mo->rebase, 2);1260 Section *s = s1->sections[mo->s_rebase[i].section];
995 *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;1261
996 set_segment_and_offset(mo, s->sh_addr, ptr,1262 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
997 REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,1263 name = (char *) symtab_section->link->data + sym->st_name;
998 mo->rebase,1264 ptr = section_ptr_add(mo->rebase, 2);
999 mo->lazy_bind_rebase[i].rel.r_offset +1265 *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
1000 s->sh_addr);1266 set_segment_and_offset(mo, s->sh_addr, ptr,
1001 ptr = section_ptr_add(mo->rebase, 1);1267 REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
1002 *ptr = REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1;1268 mo->rebase,
1003 }1269 mo->s_rebase[i].rel.r_offset +
1270 s->sh_addr);
1271 ptr = section_ptr_add(mo->rebase, 1);
1272 *ptr = REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1;
1004 }1273 }
1005 for (i = 0; i < mo->n_bind; i++) {1274 for (i = 0; i < mo->n_bind; i++) {
1006 int sym_index = ELFW(R_SYM)(mo->bind[i].rel.r_info);1275 int sym_index = ELFW(R_SYM)(mo->bind[i].rel.r_info);
@@ -1018,10 +1287,10 @@ static void do_bind_rebase(TCCState *s1, struct macho *mo) · 11 unmodified lines
1018 strcpy(ptr, name);1287 strcpy(ptr, name);
1019 ptr += strlen(name) + 1;1288 ptr += strlen(name) + 1;
1020 *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;1289 *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;
1021 set_segment_and_offset(mo, s->sh_addr, ptr,1290 set_segment_and_offset(mo, s->sh_addr, ptr,
1022 BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,1291 BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
1023 binding,1292 binding,
1024 mo->bind[i].rel.r_offset + s->sh_addr);1293 mo->bind[i].rel.r_offset + s->sh_addr);
1025 ptr = section_ptr_add(binding, 1);1294 ptr = section_ptr_add(binding, 1);
1026 *ptr++ = BIND_OPCODE_DO_BIND;1295 *ptr++ = BIND_OPCODE_DO_BIND;
1027 }1296 }
@@ -1029,9 +1298,42 @@ static void do_bind_rebase(TCCState *s1, struct macho *mo) · 1 unmodified line
1029 ptr = section_ptr_add(mo->rebase, 1);1298 ptr = section_ptr_add(mo->rebase, 1);
1030 *ptr = REBASE_OPCODE_DONE;1299 *ptr = REBASE_OPCODE_DONE;
1031 }1300 }
1032 tcc_free(mo->lazy_bind_rebase);1301 if (mo->binding->data_offset) {
1302 ptr = section_ptr_add(mo->binding, 1);
1303 *ptr = BIND_OPCODE_DONE;
1304 }
1305 if (mo->weak_binding->data_offset) {
1306 ptr = section_ptr_add(mo->weak_binding, 1);
1307 *ptr = BIND_OPCODE_DONE;
1308 }
1309 tcc_free(mo->s_lazy_bind);
1310 tcc_free(mo->s_rebase);
1033 tcc_free(mo->bind);1311 tcc_free(mo->bind);
1034}1312}
1313#endif
1314
1315/* FIXME */
1316static void export_trie(TCCState *s1, struct macho *mo)
1317{
1318 int sym_index;
1319 int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));;
1320
1321 for (sym_index = 1; sym_index < sym_end; ++sym_index) {
1322 ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
1323 const char *name = (char*)symtab_section->link->data + sym->st_name;
1324
1325 if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE &&
1326 ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL) {
1327 int flag = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
1328
1329 if (sym->st_shndx == SHN_ABS)
1330 flag = EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE;
1331 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1332 flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
1333 dprintf ("%s %d %llx\n", name, flag, sym->st_value + s1->sections[sym->st_shndx]->sh_addr);
1334 }
1335 }
1336}
1035 1337
1036static void collect_sections(TCCState *s1, struct macho *mo)1338static void collect_sections(TCCState *s1, struct macho *mo)
1037{1339{
@@ -1039,6 +1341,10 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 1 unmodified line
1039 uint64_t curaddr, fileofs;1341 uint64_t curaddr, fileofs;
1040 Section *s;1342 Section *s;
1041 struct segment_command_64 *seg = NULL;1343 struct segment_command_64 *seg = NULL;
1344#ifdef CONFIG_NEW_MACHO
1345 struct linkedit_data_command *chained_fixups_lc;
1346 struct linkedit_data_command *export_trie_lc;
1347#endif
1042 struct dylinker_command *dyldlc;1348 struct dylinker_command *dyldlc;
1043 struct symtab_command *symlc;1349 struct symtab_command *symlc;
1044 struct dysymtab_command *dysymlc;1350 struct dysymtab_command *dysymlc;
@@ -1062,6 +1368,15 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 17 unmodified lines
1062 seg->maxprot = 7; // rwx1368 seg->maxprot = 7; // rwx
1063 seg->initprot = 1; // r--1369 seg->initprot = 1; // r--
1064 1370
1371#ifdef CONFIG_NEW_MACHO
1372 chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
1373 sizeof(struct linkedit_data_command));
1374 export_trie_lc = add_lc(mo, LC_DYLD_EXPORTS_TRIE,
1375 sizeof(struct linkedit_data_command));
1376#else
1377 mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo));
1378#endif
1379
1065 mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));1380 mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
1066 mo->ep->entryoff = 4096;1381 mo->ep->entryoff = 4096;
1067 1382
@@ -1071,7 +1386,6 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 3 unmodified lines
1071 str = (char*)dyldlc + dyldlc->name;1386 str = (char*)dyldlc + dyldlc->name;
1072 strcpy(str, "/usr/lib/dyld");1387 strcpy(str, "/usr/lib/dyld");
1073 1388
1074 mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo));
1075 symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));1389 symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
1076 dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));1390 dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
1077 1391
@@ -1109,12 +1423,14 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 31 unmodified lines
1109 case SHT_PROGBITS:1423 case SHT_PROGBITS:
1110 if (s == mo->stubs)1424 if (s == mo->stubs)
1111 sk = sk_stubs;1425 sk = sk_stubs;
1426#ifndef CONFIG_NEW_MACHO
1112 else if (s == mo->stub_helper)1427 else if (s == mo->stub_helper)
1113 sk = sk_stub_helper;1428 sk = sk_stub_helper;
1114 else if (s == s1->got)
1115 sk = sk_nl_ptr;
1116 else if (s == mo->la_symbol_ptr)1429 else if (s == mo->la_symbol_ptr)
1117 sk = sk_la_ptr;1430 sk = sk_la_ptr;
1431#endif
1432 else if (s == s1->got)
1433 sk = sk_nl_ptr;
1118 else if (s == stab_section)1434 else if (s == stab_section)
1119 sk = sk_stab;1435 sk = sk_stab;
1120 else if (s == dwarf_info_section)1436 else if (s == dwarf_info_section)
@@ -1150,15 +1466,23 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 29 unmodified lines
1150 mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);1466 mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
1151 for (sk = sk_unknown; sk < sk_last; sk++) {1467 for (sk = sk_unknown; sk < sk_last; sk++) {
1152 struct section_64 *sec = NULL;1468 struct section_64 *sec = NULL;
1153#define SEG_PAGE_SIZE 16384
1154 if (sk == sk_linkedit)
1155 do_bind_rebase(s1, mo);
1156 if (seg) {1469 if (seg) {
1157 seg->vmsize = (curaddr - seg->vmaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;1470 seg->vmsize = (curaddr - seg->vmaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
1158 seg->filesize = (fileofs - seg->fileoff + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;1471 seg->filesize = (fileofs - seg->fileoff + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
1159 curaddr = seg->vmaddr + seg->vmsize;1472 curaddr = seg->vmaddr + seg->vmsize;
1160 fileofs = seg->fileoff + seg->filesize;1473 fileofs = seg->fileoff + seg->filesize;
1161 }1474 }
1475#ifdef CONFIG_NEW_MACHO
1476 if (sk == sk_linkedit) {
1477 calc_fixup_size(s1, mo);
1478 export_trie(s1, mo);
1479 }
1480#else
1481 if (sk == sk_linkedit) {
1482 bind_rebase(s1, mo);
1483 export_trie(s1, mo);
1484 }
1485#endif
1162 if (skinfo[sk].seg && mo->sk_to_sect[sk].s) {1486 if (skinfo[sk].seg && mo->sk_to_sect[sk].s) {
1163 uint64_t al = 0;1487 uint64_t al = 0;
1164 int si;1488 int si;
@@ -1178,14 +1502,23 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 13 unmodified lines
1178#endif1502#endif
1179 if (sk == sk_nl_ptr)1503 if (sk == sk_nl_ptr)
1180 sec->reserved1 = mo->nr_plt;1504 sec->reserved1 = mo->nr_plt;
1505#ifndef CONFIG_NEW_MACHO
1181 if (sk == sk_la_ptr)1506 if (sk == sk_la_ptr)
1182 sec->reserved1 = mo->nr_plt + mo->n_got;1507 sec->reserved1 = mo->nr_plt + mo->n_got;
1508#endif
1183 }1509 }
1184 if (seg->vmaddr == -1) {1510 if (seg->vmaddr == -1) {
1511#ifdef CONFIG_NEW_MACHO
1512 curaddr = (curaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
1513 seg->vmaddr = curaddr;
1514 fileofs = (fileofs + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
1515 seg->fileoff = fileofs;
1516#else
1185 curaddr = (curaddr + 4095) & -4096;1517 curaddr = (curaddr + 4095) & -4096;
1186 seg->vmaddr = curaddr;1518 seg->vmaddr = curaddr;
1187 fileofs = (fileofs + 4095) & -4096;1519 fileofs = (fileofs + 4095) & -4096;
1188 seg->fileoff = fileofs;1520 seg->fileoff = fileofs;
1521#endif
1189 }1522 }
1190 1523
1191 for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {1524 for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
@@ -1266,6 +1599,16 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 74 unmodified lines
1266 dysymlc->indirectsymoff = mo->indirsyms->sh_offset;1599 dysymlc->indirectsymoff = mo->indirsyms->sh_offset;
1267 dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);1600 dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);
1268 1601
1602#ifdef CONFIG_NEW_MACHO
1603 if (mo->chained_fixups->data_offset) {
1604 chained_fixups_lc->dataoff = mo->chained_fixups->sh_offset;
1605 chained_fixups_lc->datasize = mo->chained_fixups->data_offset;
1606 }
1607 if (mo->exports->data_offset) {
1608 export_trie_lc->dataoff = mo->exports->sh_offset;
1609 export_trie_lc->datasize = mo->exports->data_offset;
1610 }
1611#else
1269 if (mo->rebase->data_offset) {1612 if (mo->rebase->data_offset) {
1270 mo->dyldinfo->rebase_off = mo->rebase->sh_offset;1613 mo->dyldinfo->rebase_off = mo->rebase->sh_offset;
1271 mo->dyldinfo->rebase_size = mo->rebase->data_offset;1614 mo->dyldinfo->rebase_size = mo->rebase->data_offset;
@@ -1286,6 +1629,7 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 14 unmodified lines
1286 mo->dyldinfo->export_off = mo->exports->sh_offset;1629 mo->dyldinfo->export_off = mo->exports->sh_offset;
1287 mo->dyldinfo->export_size = mo->exports->data_offset;1630 mo->dyldinfo->export_size = mo->exports->data_offset;
1288 }1631 }
1632#endif
1289}1633}
1290 1634
1291static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)1635static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
@@ -1333,6 +1677,170 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) · 41 unmodified lines
1333 }1677 }
1334}1678}
1335 1679
1680#ifdef CONFIG_NEW_MACHO
1681static int bind_rebase_cmp(const void *_a, const void *_b, void *arg)
1682{
1683 TCCState *s1 = arg;
1684 struct bind_rebase *a = (struct bind_rebase *) _a;
1685 struct bind_rebase *b = (struct bind_rebase *) _b;
1686 addr_t aa = s1->sections[a->section]->sh_addr + a->rel.r_offset;
1687 addr_t ab = s1->sections[b->section]->sh_addr + b->rel.r_offset;
1688
1689 return aa > ab ? 1 : aa < ab ? -1 : 0;
1690}
1691
1692ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
1693{
1694 int i, j, k, bind_index, size, page_count, sym_index;
1695 const char *name;
1696 ElfW_Rel rel;
1697 ElfW(Sym) *sym;
1698 unsigned char *data = mo->chained_fixups->data;
1699 struct segment_command_64 *seg;
1700 struct dyld_chained_fixups_header *header;
1701 struct dyld_chained_starts_in_image *image;
1702 struct dyld_chained_starts_in_segment *segment;
1703 struct dyld_chained_import *import;
1704
1705 tcc_qsort(mo->bind_rebase, mo->n_bind_rebase, sizeof(struct bind_rebase),
1706 bind_rebase_cmp, s1);
1707 for (i = 0; i < mo->n_bind_rebase - 1; i++)
1708 if (mo->bind_rebase[i].section == mo->bind_rebase[i + 1].section &&
1709 mo->bind_rebase[i].rel.r_offset == mo->bind_rebase[i + 1].rel.r_offset) {
1710 sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
1711 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1712 name = (char *) symtab_section->link->data + sym->st_name;
1713 tcc_error("Overlap bind/rebase %s:%s",
1714 s1->sections[mo->bind_rebase[i].section]->name, name);
1715 }
1716 header = (struct dyld_chained_fixups_header *) data;
1717 data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
1718 header->starts_offset = data - mo->chained_fixups->data;
1719 header->imports_count = mo->n_bind;
1720 header->imports_format = DYLD_CHAINED_IMPORT;
1721 header->symbols_format = 0;
1722 size = sizeof(struct dyld_chained_starts_in_image) +
1723 (mo->nseg - 1) * sizeof(uint32_t);
1724 image = (struct dyld_chained_starts_in_image *) data;
1725 data += (size + 7) & -8;
1726 image->seg_count = mo->nseg;
1727 for (i = 1; i < mo->nseg - 1; i++) {
1728 image->seg_info_offset[i] = (data - mo->chained_fixups->data) -
1729 header->starts_offset;
1730 seg = get_segment(mo, i);
1731 page_count = (seg->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
1732 size = sizeof(struct dyld_chained_starts_in_segment) +
1733 (page_count - 1) * sizeof(uint16_t);
1734 segment = (struct dyld_chained_starts_in_segment *) data;
1735 data += (size + 7) & -8;
1736 segment->size = size;
1737 segment->page_size = SEG_PAGE_SIZE;
1738#if 1
1739#define PTR_64_OFFSET 0
1740#define PTR_64_MASK 0x7FFFFFFFFFFULL
1741 segment->pointer_format = DYLD_CHAINED_PTR_64;
1742#else
1743#define PTR_64_OFFSET 0x100000000ULL
1744#define PTR_64_MASK 0xFFFFFFFFFFFFFFULL
1745 segment->pointer_format = DYLD_CHAINED_PTR_64_OFFSET;
1746#endif
1747 segment->segment_offset = seg->fileoff;
1748 segment->max_valid_pointer = 0;
1749 segment->page_count = page_count;
1750 // add bind/rebase
1751 for (j = 0; j < page_count; j++) {
1752 uint64_t start = seg->vmaddr + j * SEG_PAGE_SIZE;
1753 uint64_t end = start + SEG_PAGE_SIZE;
1754 void *last;
1755 addr_t last_o = 0;
1756 uint64_t cur_o, cur;
1757 struct dyld_chained_ptr_64_rebase *rebase;
1758 struct dyld_chained_ptr_64_bind *bind;
1759 Section *s;
1760
1761 segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE;
1762 for (k = 0, bind_index = 0; k < mo->n_bind_rebase; k++) {
1763 uint64_t addr;
1764
1765 s = s1->sections[mo->bind_rebase[k].section];
1766 rel = mo->bind_rebase[k].rel;
1767 if ((rel.r_offset & 3) ||
1768 (rel.r_offset & (SEG_PAGE_SIZE - 1)) >
1769 SEG_PAGE_SIZE - PTR_SIZE)
1770 tcc_error("Illegal rel_offset %s %lld",
1771 s->name, (long long)rel.r_offset);
1772 addr = s->sh_addr + rel.r_offset;
1773 if (addr >= start && addr < end) {
1774 cur_o = addr - start;
1775 if (mo->bind_rebase[k].bind) {
1776 if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE)
1777 segment->page_start[j] = cur_o;
1778 else {
1779 bind = (struct dyld_chained_ptr_64_bind *) last;
1780 bind->next = (cur_o - last_o) / 4;
1781 }
1782 bind = (struct dyld_chained_ptr_64_bind *)
1783 (s->data + rel.r_offset);
1784 last = bind;
1785 last_o = cur_o;
1786 bind->ordinal = bind_index;
1787 bind->addend = 0;
1788 bind->reserved = 0;
1789 bind->next = 0;
1790 bind->bind = 1;
1791 }
1792 else {
1793 if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE)
1794 segment->page_start[j] = cur_o;
1795 else {
1796 rebase = (struct dyld_chained_ptr_64_rebase *) last;
1797 rebase->next = (cur_o - last_o) / 4;
1798 }
1799 rebase = (struct dyld_chained_ptr_64_rebase *)
1800 (s->data + rel.r_offset);
1801 last = rebase;
1802 last_o = cur_o;
1803 cur = (*(uint64_t *) (s->data + rel.r_offset)) -
1804 PTR_64_OFFSET;
1805 rebase->target = cur & PTR_64_MASK;
1806 rebase->high8 = cur >> (64 - 8);
1807 if (cur != ((uint64_t)rebase->high8 << (64 - 8)) + rebase->target)
1808 tcc_error("rebase error");
1809 rebase->reserved = 0;
1810 rebase->next = 0;
1811 rebase->bind = 0;
1812 }
1813 }
1814 bind_index += mo->bind_rebase[k].bind;
1815 }
1816 }
1817 }
1818 // add imports
1819 header->imports_offset = data - mo->chained_fixups->data;
1820 import = (struct dyld_chained_import *) data;
1821 data += mo->n_bind * sizeof (struct dyld_chained_import);
1822 header->symbols_offset = data - mo->chained_fixups->data;
1823 data++;
1824 for (i = 0, bind_index = 0; i < mo->n_bind_rebase; i++) {
1825 if (mo->bind_rebase[i].bind) {
1826 import[bind_index].lib_ordinal =
1827 BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xffu;
1828 import[bind_index].name_offset =
1829 (data - mo->chained_fixups->data) - header->symbols_offset;
1830 sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
1831 sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1832 import[bind_index].weak_import =
1833 ELFW(ST_BIND)(sym->st_info) == STB_WEAK;
1834 name = (char *) symtab_section->link->data + sym->st_name;
1835 strcpy(data, name);
1836 data += strlen(name) + 1;
1837 bind_index++;
1838 }
1839 }
1840 tcc_free(mo->bind_rebase);
1841}
1842#endif
1843
1336ST_FUNC int macho_output_file(TCCState *s1, const char *filename)1844ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
1337{1845{
1338 int fd, mode, file_type;1846 int fd, mode, file_type;
@@ -1370,6 +1878,9 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 31 unmodified lines
1370 if (s1->nb_errors)1878 if (s1->nb_errors)
1371 goto do_ret;1879 goto do_ret;
1372 relocate_sections(s1);1880 relocate_sections(s1);
1881#ifdef CONFIG_NEW_MACHO
1882 bind_rebase_import(s1, &mo);
1883#endif
1373 convert_symbols(s1, &mo);1884 convert_symbols(s1, &mo);
1374 macho_write(s1, &mo, fp);1885 macho_write(s1, &mo, fp);
1375 }1886 }

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