| @@ -40,6 +40,7 @@ · 39 unmodified lines |
| 40 | | 40 | |
| 41 | #define MH_EXECUTE (0x2) | 41 | #define MH_EXECUTE (0x2) |
| 42 | #define MH_DYLDLINK (0x4) | 42 | #define MH_DYLDLINK (0x4) |
| | 43 | #define MH_DYLIB (0x6) |
| 43 | #define MH_PIE (0x200000) | 44 | #define MH_PIE (0x200000) |
| 44 | | 45 | |
| 45 | #define CPU_SUBTYPE_LIB64 (0x80000000) | 46 | #define CPU_SUBTYPE_LIB64 (0x80000000) |
| @@ -104,6 +105,7 @@ struct load_command { · 58 unmodified lines |
| 104 | #define LC_ID_DYLIB 0xd | 105 | #define LC_ID_DYLIB 0xd |
| 105 | #define LC_LOAD_DYLINKER 0xe | 106 | #define LC_LOAD_DYLINKER 0xe |
| 106 | #define LC_SEGMENT_64 0x19 | 107 | #define LC_SEGMENT_64 0x19 |
| | 108 | #define LC_RPATH (0x1c | LC_REQ_DYLD) |
| 107 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) | 109 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) |
| 108 | #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) | 110 | #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) |
| 109 | #define LC_MAIN (0x28|LC_REQ_DYLD) | 111 | #define LC_MAIN (0x28|LC_REQ_DYLD) |
| @@ -243,6 +245,12 @@ struct dylib_command { · 133 unmodified lines |
| 243 | uint32_t compatibility_version; /* library's compatibility vers number*/ | 245 | uint32_t compatibility_version; /* library's compatibility vers number*/ |
| 244 | }; | 246 | }; |
| 245 | | 247 | |
| | 248 | struct rpath_command { |
| | 249 | uint32_t cmd; /* LC_RPATH */ |
| | 250 | uint32_t cmdsize; /* includes string */ |
| | 251 | lc_str path; /* path to add to run path */ |
| | 252 | }; |
| | 253 | |
| 246 | struct dylinker_command { | 254 | struct dylinker_command { |
| 247 | uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or | 255 | uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or |
| 248 | LC_DYLD_ENVIRONMENT */ | 256 | LC_DYLD_ENVIRONMENT */ |
| @@ -327,6 +335,8 @@ struct dysymtab_command { · 78 unmodified lines |
| 327 | #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 | 335 | #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 |
| 328 | #define BIND_OPCODE_DO_BIND 0x90 | 336 | #define BIND_OPCODE_DO_BIND 0x90 |
| 329 | | 337 | |
| | 338 | #define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 |
| | 339 | |
| 330 | #define BIND_TYPE_POINTER 1 | 340 | #define BIND_TYPE_POINTER 1 |
| 331 | #define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 | 341 | #define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 |
| 332 | | 342 | |
| @@ -653,13 +663,12 @@ static void bind_rebase_add(struct macho *mo, int bind, int sh_info, · 320 unmodified lines |
| 653 | static void check_relocs(TCCState *s1, struct macho *mo) | 663 | static void check_relocs(TCCState *s1, struct macho *mo) |
| 654 | { | 664 | { |
| 655 | Section *s; | 665 | Section *s; |
| 656 | ElfW_Rel *rel; | 666 | ElfW_Rel *rel, save_rel; |
| 657 | ElfW(Sym) *sym; | 667 | ElfW(Sym) *sym; |
| 658 | int i, type, gotplt_entry, sym_index, for_code; | 668 | int i, type, gotplt_entry, sym_index, for_code; |
| 659 | uint32_t *pi, *goti; | 669 | uint32_t *pi, *goti; |
| 660 | struct sym_attr *attr; | 670 | struct sym_attr *attr; |
| 661 | | 671 | |
| 662 | mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | | |
| 663 | goti = NULL; | 672 | goti = NULL; |
| 664 | mo->nr_plt = mo->n_got = 0; | 673 | mo->nr_plt = mo->n_got = 0; |
| 665 | for (i = 1; i < s1->nb_sections; i++) { | 674 | for (i = 1; i < s1->nb_sections; i++) { |
| @@ -668,6 +677,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 2 unmodified lines |
| 668 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) | 677 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) |
| 669 | continue; | 678 | continue; |
| 670 | for_each_elem(s, 0, rel, ElfW_Rel) { | 679 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| | 680 | save_rel = *rel; |
| 671 | type = ELFW(R_TYPE)(rel->r_info); | 681 | type = ELFW(R_TYPE)(rel->r_info); |
| 672 | gotplt_entry = gotplt_entry_type(type); | 682 | gotplt_entry = gotplt_entry_type(type); |
| 673 | for_code = code_reloc(type); | 683 | for_code = code_reloc(type); |
| @@ -685,7 +695,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 11 unmodified lines |
| 685 | attr->dyn_index = 1; /* used as flag */ | 695 | attr->dyn_index = 1; /* used as flag */ |
| 686 | section_ptr_add(s1->got, PTR_SIZE); | 696 | section_ptr_add(s1->got, PTR_SIZE); |
| 687 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, | 697 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, |
| 688 | R_DATA_PTR, sym_index); | 698 | R_JMP_SLOT, sym_index); |
| 689 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); | 699 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); |
| 690 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { | 700 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { |
| 691 | if (sym->st_shndx == SHN_UNDEF) | 701 | if (sym->st_shndx == SHN_UNDEF) |
| @@ -701,7 +711,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 9 unmodified lines |
| 701 | && type == R_AARCH64_ADR_GOT_PAGE | 711 | && type == R_AARCH64_ADR_GOT_PAGE |
| 702 | #endif | 712 | #endif |
| 703 | ) { | 713 | ) { |
| 704 | bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr); | 714 | bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr); |
| 705 | attr->plt_offset = 0; // ignore next bind | 715 | attr->plt_offset = 0; // ignore next bind |
| 706 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); | 716 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); |
| 707 | } | 717 | } |
| @@ -740,7 +750,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 32 unmodified lines |
| 740 | write32le(jmp + 8, // br x16 | 750 | write32le(jmp + 8, // br x16 |
| 741 | 0xd61f0200); | 751 | 0xd61f0200); |
| 742 | #endif | 752 | #endif |
| 743 | bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr); | 753 | bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr); |
| 744 | pi = section_ptr_add(mo->indirsyms, sizeof(*pi)); | 754 | pi = section_ptr_add(mo->indirsyms, sizeof(*pi)); |
| 745 | *pi = mo->e2msym[sym_index]; | 755 | *pi = mo->e2msym[sym_index]; |
| 746 | mo->nr_plt++; | 756 | mo->nr_plt++; |
| @@ -749,9 +759,9 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 2 unmodified lines |
| 749 | rel->r_addend += attr->plt_offset; | 759 | rel->r_addend += attr->plt_offset; |
| 750 | } | 760 | } |
| 751 | } | 761 | } |
| 752 | if (type == R_DATA_PTR) | 762 | if (type == R_DATA_PTR || type == R_JMP_SLOT) |
| 753 | bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0, | 763 | bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0, |
| 754 | s->sh_info, rel, NULL); | 764 | s->sh_info, &save_rel, NULL); |
| 755 | } | 765 | } |
| 756 | } | 766 | } |
| 757 | pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); | 767 | pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); |
| @@ -765,15 +775,13 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 7 unmodified lines |
| 765 | { | 775 | { |
| 766 | uint8_t *jmp; | 776 | uint8_t *jmp; |
| 767 | Section *s; | 777 | Section *s; |
| 768 | ElfW_Rel *rel; | 778 | ElfW_Rel *rel, save_rel; |
| 769 | ElfW(Sym) *sym; | 779 | ElfW(Sym) *sym; |
| 770 | int i, type, gotplt_entry, sym_index, for_code; | 780 | int i, type, gotplt_entry, sym_index, for_code; |
| 771 | int bind_offset, la_symbol_offset; | 781 | int bind_offset, la_symbol_offset; |
| 772 | uint32_t *pi, *goti; | 782 | uint32_t *pi, *goti; |
| 773 | struct sym_attr *attr; | 783 | struct sym_attr *attr; |
| 774 | | 784 | |
| 775 | mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | | |
| 776 | | | |
| 777 | #ifdef TCC_TARGET_X86_64 | 785 | #ifdef TCC_TARGET_X86_64 |
| 778 | jmp = section_ptr_add(mo->stub_helper, 16); | 786 | jmp = section_ptr_add(mo->stub_helper, 16); |
| 779 | jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */ | 787 | jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */ |
| @@ -814,6 +822,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 34 unmodified lines |
| 814 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) | 822 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) |
| 815 | continue; | 823 | continue; |
| 816 | for_each_elem(s, 0, rel, ElfW_Rel) { | 824 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| | 825 | save_rel = *rel; |
| 817 | type = ELFW(R_TYPE)(rel->r_info); | 826 | type = ELFW(R_TYPE)(rel->r_info); |
| 818 | gotplt_entry = gotplt_entry_type(type); | 827 | gotplt_entry = gotplt_entry_type(type); |
| 819 | for_code = code_reloc(type); | 828 | for_code = code_reloc(type); |
| @@ -831,7 +840,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 11 unmodified lines |
| 831 | attr->dyn_index = 1; /* used as flag */ | 840 | attr->dyn_index = 1; /* used as flag */ |
| 832 | section_ptr_add(s1->got, PTR_SIZE); | 841 | section_ptr_add(s1->got, PTR_SIZE); |
| 833 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, | 842 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, |
| 834 | R_DATA_PTR, sym_index); | 843 | R_JMP_SLOT, sym_index); |
| 835 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); | 844 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); |
| 836 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { | 845 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { |
| 837 | if (sym->st_shndx == SHN_UNDEF) | 846 | if (sym->st_shndx == SHN_UNDEF) |
| @@ -852,7 +861,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 14 unmodified lines |
| 852 | (mo->n_bind + 1) * | 861 | (mo->n_bind + 1) * |
| 853 | sizeof(struct bind)); | 862 | sizeof(struct bind)); |
| 854 | mo->bind[mo->n_bind].section = s1->got->reloc->sh_info; | 863 | mo->bind[mo->n_bind].section = s1->got->reloc->sh_info; |
| 855 | mo->bind[mo->n_bind].rel = *rel; | 864 | mo->bind[mo->n_bind].rel = save_rel; |
| 856 | mo->bind[mo->n_bind].rel.r_offset = attr->got_offset; | 865 | mo->bind[mo->n_bind].rel.r_offset = attr->got_offset; |
| 857 | mo->n_bind++; | 866 | mo->n_bind++; |
| 858 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); | 867 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); |
| @@ -936,7 +945,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 77 unmodified lines |
| 936 | bind_offset; | 945 | bind_offset; |
| 937 | mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset = | 946 | mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset = |
| 938 | la_symbol_offset; | 947 | la_symbol_offset; |
| 939 | mo->s_lazy_bind[mo->n_lazy_bind].rel = *rel; | 948 | mo->s_lazy_bind[mo->n_lazy_bind].rel = save_rel; |
| 940 | mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset = | 949 | mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset = |
| 941 | attr->plt_offset; | 950 | attr->plt_offset; |
| 942 | mo->n_lazy_bind++; | 951 | mo->n_lazy_bind++; |
| @@ -948,13 +957,13 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 5 unmodified lines |
| 948 | rel->r_addend += attr->plt_offset; | 957 | rel->r_addend += attr->plt_offset; |
| 949 | } | 958 | } |
| 950 | } | 959 | } |
| 951 | if (type == R_DATA_PTR) { | 960 | if (type == R_DATA_PTR || type == R_JMP_SLOT) { |
| 952 | if (sym->st_shndx == SHN_UNDEF) { | 961 | if (sym->st_shndx == SHN_UNDEF) { |
| 953 | mo->bind = tcc_realloc(mo->bind, | 962 | mo->bind = tcc_realloc(mo->bind, |
| 954 | (mo->n_bind + 1) * | 963 | (mo->n_bind + 1) * |
| 955 | sizeof(struct bind)); | 964 | sizeof(struct bind)); |
| 956 | mo->bind[mo->n_bind].section = s->sh_info; | 965 | mo->bind[mo->n_bind].section = s->sh_info; |
| 957 | mo->bind[mo->n_bind].rel = *rel; | 966 | mo->bind[mo->n_bind].rel = save_rel; |
| 958 | mo->n_bind++; | 967 | mo->n_bind++; |
| 959 | } | 968 | } |
| 960 | else { | 969 | else { |
| @@ -962,7 +971,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 962 | tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * | 971 | tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * |
| 963 | sizeof(struct s_rebase)); | 972 | sizeof(struct s_rebase)); |
| 964 | mo->s_rebase[mo->n_rebase].section = s->sh_info; | 973 | mo->s_rebase[mo->n_rebase].section = s->sh_info; |
| 965 | mo->s_rebase[mo->n_rebase].rel = *rel; | 974 | mo->s_rebase[mo->n_rebase].rel = save_rel; |
| 966 | mo->n_rebase++; | 975 | mo->n_rebase++; |
| 967 | } | 976 | } |
| 968 | } | 977 | } |
| @@ -1008,6 +1017,7 @@ static int check_symbols(TCCState *s1, struct macho *mo) · 39 unmodified lines |
| 1008 | if (mo->iundef == -1) | 1017 | if (mo->iundef == -1) |
| 1009 | mo->iundef = sym_index - 1; | 1018 | mo->iundef = sym_index - 1; |
| 1010 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK | 1019 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK |
| | 1020 | || s1->output_type != TCC_OUTPUT_EXE |
| 1011 | || find_elf_sym(s1->dynsymtab_section, name)) { | 1021 | || find_elf_sym(s1->dynsymtab_section, name)) { |
| 1012 | /* Mark the symbol as coming from a dylib so that | 1022 | /* Mark the symbol as coming from a dylib so that |
| 1013 | relocate_syms doesn't complain. Normally bind_exe_dynsyms | 1023 | relocate_syms doesn't complain. Normally bind_exe_dynsyms |
| @@ -1170,6 +1180,7 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 156 unmodified lines |
| 1170 | mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 1180 | mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 1171 | #endif | 1181 | #endif |
| 1172 | mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 1182 | mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| | 1183 | mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 1173 | | 1184 | |
| 1174 | mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 1185 | mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 1175 | mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); | 1186 | mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| @@ -1182,6 +1193,7 @@ static void create_symtab(TCCState *s1, struct macho *mo) · 6 unmodified lines |
| 1182 | pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name); | 1193 | pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name); |
| 1183 | pn[sym_index - 1].n_value = sym_index; | 1194 | pn[sym_index - 1].n_value = sym_index; |
| 1184 | } | 1195 | } |
| | 1196 | section_ptr_add(mo->strtab, -mo->strtab->data_offset & (PTR_SIZE - 1)); |
| 1185 | tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1); | 1197 | tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1); |
| 1186 | mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym)); | 1198 | mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym)); |
| 1187 | mo->e2msym[0] = -1; | 1199 | mo->e2msym[0] = -1; |
| @@ -1250,7 +1262,7 @@ static void calc_fixup_size(TCCState *s1, struct macho *mo) · 62 unmodified lines |
| 1250 | | 1262 | |
| 1251 | size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8; | 1263 | size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8; |
| 1252 | size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8; | 1264 | size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8; |
| 1253 | for (i = 1; i < mo->nseg - 1; i++) { | 1265 | for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { |
| 1254 | int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE; | 1266 | int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE; |
| 1255 | size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8; | 1267 | size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8; |
| 1256 | } | 1268 | } |
| @@ -1269,14 +1281,14 @@ static void calc_fixup_size(TCCState *s1, struct macho *mo) · 12 unmodified lines |
| 1269 | | 1281 | |
| 1270 | #else | 1282 | #else |
| 1271 | | 1283 | |
| 1272 | static void set_segment_and_offset(struct macho *mo, addr_t addr, | 1284 | static void set_segment_and_offset(TCCState *s1, struct macho *mo, addr_t addr, |
| 1273 | uint8_t *ptr, int opcode, | 1285 | uint8_t *ptr, int opcode, |
| 1274 | Section *sec, addr_t offset) | 1286 | Section *sec, addr_t offset) |
| 1275 | { | 1287 | { |
| 1276 | int i; | 1288 | int i; |
| 1277 | struct segment_command_64 *seg = NULL; | 1289 | struct segment_command_64 *seg = NULL; |
| 1278 | | 1290 | |
| 1279 | for (i = 1; i < mo->nseg - 1; i++) { | 1291 | for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { |
| 1280 | seg = get_segment(mo, i); | 1292 | seg = get_segment(mo, i); |
| 1281 | if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize)) | 1293 | if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize)) |
| 1282 | break; | 1294 | break; |
| @@ -1301,7 +1313,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 18 unmodified lines |
| 1301 | mo->s_lazy_bind[i].bind_offset, | 1313 | mo->s_lazy_bind[i].bind_offset, |
| 1302 | mo->lazy_binding->data_offset); | 1314 | mo->lazy_binding->data_offset); |
| 1303 | ptr = section_ptr_add(mo->lazy_binding, 1); | 1315 | ptr = section_ptr_add(mo->lazy_binding, 1); |
| 1304 | set_segment_and_offset(mo, mo->la_symbol_ptr->sh_addr, ptr, | 1316 | set_segment_and_offset(s1, mo, mo->la_symbol_ptr->sh_addr, ptr, |
| 1305 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, | 1317 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1306 | mo->lazy_binding, | 1318 | mo->lazy_binding, |
| 1307 | mo->s_lazy_bind[i].la_symbol_offset + | 1319 | mo->s_lazy_bind[i].la_symbol_offset + |
| @@ -1320,7 +1332,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 12 unmodified lines |
| 1320 | | 1332 | |
| 1321 | ptr = section_ptr_add(mo->rebase, 2); | 1333 | ptr = section_ptr_add(mo->rebase, 2); |
| 1322 | *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; | 1334 | *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; |
| 1323 | set_segment_and_offset(mo, s->sh_addr, ptr, | 1335 | set_segment_and_offset(s1, mo, s->sh_addr, ptr, |
| 1324 | REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, | 1336 | REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1325 | mo->rebase, | 1337 | mo->rebase, |
| 1326 | mo->s_rebase[i].rel.r_offset + | 1338 | mo->s_rebase[i].rel.r_offset + |
| @@ -1337,14 +1349,18 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 10 unmodified lines |
| 1337 | name = (char *) symtab_section->link->data + sym->st_name; | 1349 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1338 | binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK | 1350 | binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK |
| 1339 | ? mo->weak_binding : mo->binding; | 1351 | ? mo->weak_binding : mo->binding; |
| 1340 | ptr = section_ptr_add(binding, 5 + strlen(name)); | 1352 | ptr = section_ptr_add(binding, 4 + (binding == mo->binding) + |
| 1341 | *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | | 1353 | strlen(name)); |
| 1342 | (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf); | 1354 | if (binding == mo->binding) |
| 1343 | *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0; | 1355 | *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | |
| | 1356 | (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf); |
| | 1357 | *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | |
| | 1358 | (binding == mo->weak_binding |
| | 1359 | ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0); |
| 1344 | strcpy((char *)ptr, name); | 1360 | strcpy((char *)ptr, name); |
| 1345 | ptr += strlen(name) + 1; | 1361 | ptr += strlen(name) + 1; |
| 1346 | *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER; | 1362 | *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER; |
| 1347 | set_segment_and_offset(mo, s->sh_addr, ptr, | 1363 | set_segment_and_offset(s1, mo, s->sh_addr, ptr, |
| 1348 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, | 1364 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1349 | binding, | 1365 | binding, |
| 1350 | mo->bind[i].rel.r_offset + s->sh_addr); | 1366 | mo->bind[i].rel.r_offset + s->sh_addr); |
| @@ -1488,7 +1504,12 @@ static int triecmp(const void *_a, const void *_b, void *arg) · 137 unmodified lines |
| 1488 | { | 1504 | { |
| 1489 | struct trie_info *a = (struct trie_info *) _a; | 1505 | struct trie_info *a = (struct trie_info *) _a; |
| 1490 | struct trie_info *b = (struct trie_info *) _b; | 1506 | struct trie_info *b = (struct trie_info *) _b; |
| | 1507 | int len_a = strlen(a->name); |
| | 1508 | int len_b = strlen(b->name); |
| 1491 | | 1509 | |
| | 1510 | /* strange sorting needed. Name 'xx' should be after 'xx1' */ |
| | 1511 | if (!strncmp(a->name, b->name, len_a < len_b ? len_a : len_b)) |
| | 1512 | return len_a < len_b ? 1 : (len_a > len_b ? -1 : 0); |
| 1492 | return strcmp(a->name, b->name); | 1513 | return strcmp(a->name, b->name); |
| 1493 | } | 1514 | } |
| 1494 | | 1515 | |
| @@ -1502,7 +1523,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 7 unmodified lines |
| 1502 | struct trie_info *trie = NULL, *p_trie; | 1523 | struct trie_info *trie = NULL, *p_trie; |
| 1503 | struct trie_node node, *p_node; | 1524 | struct trie_node node, *p_node; |
| 1504 | struct trie_seq *seq = NULL; | 1525 | struct trie_seq *seq = NULL; |
| 1505 | addr_t vm_addr = get_segment(mo, 1)->vmaddr; | 1526 | addr_t vm_addr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr; |
| 1506 | | 1527 | |
| 1507 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { | 1528 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { |
| 1508 | ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; | 1529 | ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; |
| @@ -1576,19 +1597,21 @@ static void export_trie(TCCState *s1, struct macho *mo) · 67 unmodified lines |
| 1576 | tcc_free(trie); | 1597 | tcc_free(trie); |
| 1577 | } | 1598 | } |
| 1578 | | 1599 | |
| 1579 | static void collect_sections(TCCState *s1, struct macho *mo) | 1600 | static void collect_sections(TCCState *s1, struct macho *mo, const char *filename) |
| 1580 | { | 1601 | { |
| 1581 | int i, sk, numsec; | 1602 | int i, sk, numsec; |
| 1582 | int used_segment[N_SEGMENT]; | 1603 | int used_segment[N_SEGMENT]; |
| 1583 | uint64_t curaddr, fileofs; | 1604 | uint64_t curaddr, fileofs; |
| 1584 | Section *s; | 1605 | Section *s; |
| 1585 | struct segment_command_64 *seg; | 1606 | struct segment_command_64 *seg; |
| | 1607 | struct dylib_command *dylib; |
| 1586 | #ifdef CONFIG_NEW_MACHO | 1608 | #ifdef CONFIG_NEW_MACHO |
| 1587 | struct linkedit_data_command *chained_fixups_lc; | 1609 | struct linkedit_data_command *chained_fixups_lc; |
| 1588 | struct linkedit_data_command *export_trie_lc; | 1610 | struct linkedit_data_command *export_trie_lc; |
| 1589 | #endif | 1611 | #endif |
| 1590 | struct build_version_command *dyldbv; | 1612 | struct build_version_command *dyldbv; |
| 1591 | struct source_version_command *dyldsv; | 1613 | struct source_version_command *dyldsv; |
| | 1614 | struct rpath_command *rpath; |
| 1592 | struct dylinker_command *dyldlc; | 1615 | struct dylinker_command *dyldlc; |
| 1593 | struct symtab_command *symlc; | 1616 | struct symtab_command *symlc; |
| 1594 | struct dysymtab_command *dysymlc; | 1617 | struct dysymtab_command *dysymlc; |
| @@ -1662,10 +1685,16 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 67 unmodified lines |
| 1662 | used_segment[skinfo[sk].seg_initial] = 1; | 1685 | used_segment[skinfo[sk].seg_initial] = 1; |
| 1663 | } | 1686 | } |
| 1664 | | 1687 | |
| | 1688 | if (s1->output_type != TCC_OUTPUT_EXE) |
| | 1689 | used_segment[0] = 0; |
| | 1690 | |
| 1665 | for (i = 0; i < N_SEGMENT; i++) | 1691 | for (i = 0; i < N_SEGMENT; i++) |
| 1666 | if (used_segment[i]) { | 1692 | if (used_segment[i]) { |
| 1667 | seg = add_segment(mo, all_segment[i].name); | 1693 | seg = add_segment(mo, all_segment[i].name); |
| 1668 | seg->vmaddr = all_segment[i].vmaddr; | 1694 | if (i == 1 && s1->output_type != TCC_OUTPUT_EXE) |
| | 1695 | seg->vmaddr = 0; |
| | 1696 | else |
| | 1697 | seg->vmaddr = all_segment[i].vmaddr; |
| 1669 | seg->vmsize = all_segment[i].vmsize; | 1698 | seg->vmsize = all_segment[i].vmsize; |
| 1670 | seg->maxprot = all_segment[i].maxprot; | 1699 | seg->maxprot = all_segment[i].maxprot; |
| 1671 | seg->initprot = all_segment[i].initprot; | 1700 | seg->initprot = all_segment[i].initprot; |
| @@ -1675,6 +1704,17 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 3 unmodified lines |
| 1675 | mo->segment[sk] = mo->nseg - 1; | 1704 | mo->segment[sk] = mo->nseg - 1; |
| 1676 | } | 1705 | } |
| 1677 | | 1706 | |
| | 1707 | if (s1->output_type != TCC_OUTPUT_EXE) { |
| | 1708 | i = (sizeof(*dylib) + strlen(filename) + 1 + 7) &-8; |
| | 1709 | dylib = add_lc(mo, LC_ID_DYLIB, i); |
| | 1710 | dylib->name = sizeof(*dylib); |
| | 1711 | dylib->timestamp = 1; |
| | 1712 | dylib->current_version = 1 << 16; |
| | 1713 | dylib->compatibility_version = 1 << 16; |
| | 1714 | str = (char*)dylib + dylib->name; |
| | 1715 | strcpy(str, filename); |
| | 1716 | } |
| | 1717 | |
| 1678 | #ifdef CONFIG_NEW_MACHO | 1718 | #ifdef CONFIG_NEW_MACHO |
| 1679 | chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, | 1719 | chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, |
| 1680 | sizeof(struct linkedit_data_command)); | 1720 | sizeof(struct linkedit_data_command)); |
| @@ -1687,11 +1727,13 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 6 unmodified lines |
| 1687 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); | 1727 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); |
| 1688 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); | 1728 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); |
| 1689 | | 1729 | |
| 1690 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; | 1730 | if (s1->output_type == TCC_OUTPUT_EXE) { |
| 1691 | dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); | 1731 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; |
| 1692 | dyldlc->name = sizeof(*dyldlc); | 1732 | dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); |
| 1693 | str = (char*)dyldlc + dyldlc->name; | 1733 | dyldlc->name = sizeof(*dyldlc); |
| 1694 | strcpy(str, "/usr/lib/dyld"); | 1734 | str = (char*)dyldlc + dyldlc->name; |
| | 1735 | strcpy(str, "/usr/lib/dyld"); |
| | 1736 | } |
| 1695 | | 1737 | |
| 1696 | dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); | 1738 | dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); |
| 1697 | dyldbv->platform = PLATFORM_MACOS; | 1739 | dyldbv->platform = PLATFORM_MACOS; |
| @@ -1702,8 +1744,10 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 4 unmodified lines |
| 1702 | dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); | 1744 | dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); |
| 1703 | dyldsv->version = 0; | 1745 | dyldsv->version = 0; |
| 1704 | | 1746 | |
| 1705 | mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); | 1747 | if (s1->output_type == TCC_OUTPUT_EXE) { |
| 1706 | mo->ep->entryoff = 4096; | 1748 | mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| | 1749 | mo->ep->entryoff = 4096; |
| | 1750 | } |
| 1707 | | 1751 | |
| 1708 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 1752 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 1709 | DLLReference *dllref = s1->loaded_dlls[i]; | 1753 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -1711,13 +1755,21 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 1711 | add_dylib(mo, dllref->name); | 1755 | add_dylib(mo, dllref->name); |
| 1712 | } | 1756 | } |
| 1713 | | 1757 | |
| | 1758 | if (s1->rpath) { |
| | 1759 | i = (sizeof(*rpath) + strlen(s1->rpath) + 1 + 7) &-8; |
| | 1760 | rpath = add_lc(mo, LC_RPATH, i); |
| | 1761 | rpath->path = sizeof(*rpath); |
| | 1762 | str = (char*)rpath + rpath->path; |
| | 1763 | strcpy(str, s1->rpath); |
| | 1764 | } |
| | 1765 | |
| 1714 | fileofs = 4096; /* leave space for mach-o headers */ | 1766 | fileofs = 4096; /* leave space for mach-o headers */ |
| 1715 | curaddr = get_segment(mo, 1)->vmaddr; | 1767 | curaddr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr; |
| 1716 | curaddr += 4096; | 1768 | curaddr += 4096; |
| 1717 | seg = NULL; | 1769 | seg = NULL; |
| 1718 | numsec = 0; | 1770 | numsec = 0; |
| 1719 | mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections); | 1771 | mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections); |
| 1720 | for (sk = sk_unknown; sk < sk_last; sk++) { | 1772 | for (sk = sk_text; sk < sk_last; sk++) { |
| 1721 | struct section_64 *sec = NULL; | 1773 | struct section_64 *sec = NULL; |
| 1722 | if (seg) { | 1774 | if (seg) { |
| 1723 | seg->vmsize = curaddr - seg->vmaddr; | 1775 | seg->vmsize = curaddr - seg->vmaddr; |
| @@ -1734,7 +1786,8 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 10 unmodified lines |
| 1734 | export_trie(s1, mo); | 1786 | export_trie(s1, mo); |
| 1735 | } | 1787 | } |
| 1736 | #endif | 1788 | #endif |
| 1737 | if (mo->segment[sk] && mo->sk_to_sect[sk].s) { | 1789 | if ((s1->output_type != TCC_OUTPUT_EXE || mo->segment[sk]) && |
| | 1790 | mo->sk_to_sect[sk].s) { |
| 1738 | uint64_t al = 0; | 1791 | uint64_t al = 0; |
| 1739 | int si; | 1792 | int si; |
| 1740 | seg = get_segment(mo, mo->segment[sk]); | 1793 | seg = get_segment(mo, mo->segment[sk]); |
| @@ -1889,8 +1942,14 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) · 148 unmodified lines |
| 1889 | mo->mh.mh.cputype = CPU_TYPE_ARM64; | 1942 | mo->mh.mh.cputype = CPU_TYPE_ARM64; |
| 1890 | mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL; | 1943 | mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL; |
| 1891 | #endif | 1944 | #endif |
| 1892 | mo->mh.mh.filetype = MH_EXECUTE; | 1945 | if (s1->output_type == TCC_OUTPUT_EXE) { |
| 1893 | mo->mh.mh.flags = MH_DYLDLINK | MH_PIE; | 1946 | mo->mh.mh.filetype = MH_EXECUTE; |
| | 1947 | mo->mh.mh.flags = MH_DYLDLINK | MH_PIE; |
| | 1948 | } |
| | 1949 | else { |
| | 1950 | mo->mh.mh.filetype = MH_DYLIB; |
| | 1951 | mo->mh.mh.flags = MH_DYLDLINK; |
| | 1952 | } |
| 1894 | mo->mh.mh.ncmds = mo->nlc; | 1953 | mo->mh.mh.ncmds = mo->nlc; |
| 1895 | mo->mh.mh.sizeofcmds = 0; | 1954 | mo->mh.mh.sizeofcmds = 0; |
| 1896 | for (i = 0; i < mo->nlc; i++) | 1955 | for (i = 0; i < mo->nlc; i++) |
| @@ -1905,7 +1964,8 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp) · 8 unmodified lines |
| 1905 | | 1964 | |
| 1906 | for (sk = sk_unknown; sk < sk_last; sk++) { | 1965 | for (sk = sk_unknown; sk < sk_last; sk++) { |
| 1907 | //struct segment_command_64 *seg; | 1966 | //struct segment_command_64 *seg; |
| 1908 | if (!mo->segment[sk] || !mo->sk_to_sect[sk].s) | 1967 | if ((s1->output_type == TCC_OUTPUT_EXE && !mo->segment[sk]) || |
| | 1968 | !mo->sk_to_sect[sk].s) |
| 1909 | continue; | 1969 | continue; |
| 1910 | /*seg =*/ get_segment(mo, mo->segment[sk]); | 1970 | /*seg =*/ get_segment(mo, mo->segment[sk]); |
| 1911 | for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { | 1971 | for (s = mo->sk_to_sect[sk].s; s; s = s->prev) { |
| @@ -1969,7 +2029,7 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 57 unmodified lines |
| 1969 | image = (struct dyld_chained_starts_in_image *) data; | 2029 | image = (struct dyld_chained_starts_in_image *) data; |
| 1970 | data += (size + 7) & -8; | 2030 | data += (size + 7) & -8; |
| 1971 | image->seg_count = mo->nseg; | 2031 | image->seg_count = mo->nseg; |
| 1972 | for (i = 1; i < mo->nseg - 1; i++) { | 2032 | for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) { |
| 1973 | image->seg_info_offset[i] = (data - mo->chained_fixups->data) - | 2033 | image->seg_info_offset[i] = (data - mo->chained_fixups->data) - |
| 1974 | header->starts_offset; | 2034 | header->starts_offset; |
| 1975 | seg = get_segment(mo, i); | 2035 | seg = get_segment(mo, i); |
| @@ -2117,10 +2177,11 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 141 unmodified lines |
| 2117 | check_relocs(s1, &mo); | 2177 | check_relocs(s1, &mo); |
| 2118 | ret = check_symbols(s1, &mo); | 2178 | ret = check_symbols(s1, &mo); |
| 2119 | if (!ret) { | 2179 | if (!ret) { |
| 2120 | collect_sections(s1, &mo); | 2180 | collect_sections(s1, &mo, filename); |
| 2121 | relocate_syms(s1, s1->symtab, 0); | 2181 | relocate_syms(s1, s1->symtab, 0); |
| 2122 | mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1) | 2182 | if (s1->output_type == TCC_OUTPUT_EXE) |
| 2123 | - get_segment(&mo, 1)->vmaddr; | 2183 | mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1) |
| | 2184 | - get_segment(&mo, 1)->vmaddr; |
| 2124 | if (s1->nb_errors) | 2185 | if (s1->nb_errors) |
| 2125 | goto do_ret; | 2186 | goto do_ret; |
| 2126 | relocate_sections(s1); | 2187 | relocate_sections(s1); |