| @@ -40,6 +40,7 @@ · 39 unmodified lines |
| 40 | 40 | |
| 41 | 41 | #define MH_EXECUTE (0x2) |
| 42 | 42 | #define MH_DYLDLINK (0x4) |
| 43 | +#define MH_DYLIB (0x6) |
| 43 | 44 | #define MH_PIE (0x200000) |
| 44 | 45 | |
| 45 | 46 | #define CPU_SUBTYPE_LIB64 (0x80000000) |
| @@ -104,6 +105,7 @@ struct load_command { · 58 unmodified lines |
| 104 | 105 | #define LC_ID_DYLIB 0xd |
| 105 | 106 | #define LC_LOAD_DYLINKER 0xe |
| 106 | 107 | #define LC_SEGMENT_64 0x19 |
| 108 | +#define LC_RPATH (0x1c | LC_REQ_DYLD) |
| 107 | 109 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) |
| 108 | 110 | #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) |
| 109 | 111 | #define LC_MAIN (0x28|LC_REQ_DYLD) |
| @@ -243,6 +245,12 @@ struct dylib_command { · 133 unmodified lines |
| 243 | 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 | 254 | struct dylinker_command { |
| 247 | 255 | uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or |
| 248 | 256 | LC_DYLD_ENVIRONMENT */ |
| @@ -327,6 +335,8 @@ struct dysymtab_command { · 78 unmodified lines |
| 327 | 335 | #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 |
| 328 | 336 | #define BIND_OPCODE_DO_BIND 0x90 |
| 329 | 337 | |
| 338 | +#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 |
| 339 | + |
| 330 | 340 | #define BIND_TYPE_POINTER 1 |
| 331 | 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 | 663 | static void check_relocs(TCCState *s1, struct macho *mo) |
| 654 | 664 | { |
| 655 | 665 | Section *s; |
| 656 | | − ElfW_Rel *rel; |
| 666 | + ElfW_Rel *rel, save_rel; |
| 657 | 667 | ElfW(Sym) *sym; |
| 658 | 668 | int i, type, gotplt_entry, sym_index, for_code; |
| 659 | 669 | uint32_t *pi, *goti; |
| 660 | 670 | struct sym_attr *attr; |
| 661 | 671 | |
| 662 | | − mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 663 | 672 | goti = NULL; |
| 664 | 673 | mo->nr_plt = mo->n_got = 0; |
| 665 | 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 | 677 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) |
| 669 | 678 | continue; |
| 670 | 679 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| 680 | + save_rel = *rel; |
| 671 | 681 | type = ELFW(R_TYPE)(rel->r_info); |
| 672 | 682 | gotplt_entry = gotplt_entry_type(type); |
| 673 | 683 | for_code = code_reloc(type); |
| @@ -685,7 +695,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 11 unmodified lines |
| 685 | 695 | attr->dyn_index = 1; /* used as flag */ |
| 686 | 696 | section_ptr_add(s1->got, PTR_SIZE); |
| 687 | 697 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, |
| 688 | | − R_DATA_PTR, sym_index); |
| 698 | + R_JMP_SLOT, sym_index); |
| 689 | 699 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); |
| 690 | 700 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { |
| 691 | 701 | if (sym->st_shndx == SHN_UNDEF) |
| @@ -701,7 +711,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 9 unmodified lines |
| 701 | 711 | && type == R_AARCH64_ADR_GOT_PAGE |
| 702 | 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 | 715 | attr->plt_offset = 0; // ignore next bind |
| 706 | 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 | 750 | write32le(jmp + 8, // br x16 |
| 741 | 751 | 0xd61f0200); |
| 742 | 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 | 754 | pi = section_ptr_add(mo->indirsyms, sizeof(*pi)); |
| 745 | 755 | *pi = mo->e2msym[sym_index]; |
| 746 | 756 | mo->nr_plt++; |
| @@ -749,9 +759,9 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 2 unmodified lines |
| 749 | 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 | 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 | 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 | 776 | uint8_t *jmp; |
| 767 | 777 | Section *s; |
| 768 | | − ElfW_Rel *rel; |
| 778 | + ElfW_Rel *rel, save_rel; |
| 769 | 779 | ElfW(Sym) *sym; |
| 770 | 780 | int i, type, gotplt_entry, sym_index, for_code; |
| 771 | 781 | int bind_offset, la_symbol_offset; |
| 772 | 782 | uint32_t *pi, *goti; |
| 773 | 783 | struct sym_attr *attr; |
| 774 | 784 | |
| 775 | | − mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 776 | | − |
| 777 | 785 | #ifdef TCC_TARGET_X86_64 |
| 778 | 786 | jmp = section_ptr_add(mo->stub_helper, 16); |
| 779 | 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 | 822 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) |
| 815 | 823 | continue; |
| 816 | 824 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| 825 | + save_rel = *rel; |
| 817 | 826 | type = ELFW(R_TYPE)(rel->r_info); |
| 818 | 827 | gotplt_entry = gotplt_entry_type(type); |
| 819 | 828 | for_code = code_reloc(type); |
| @@ -831,7 +840,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 11 unmodified lines |
| 831 | 840 | attr->dyn_index = 1; /* used as flag */ |
| 832 | 841 | section_ptr_add(s1->got, PTR_SIZE); |
| 833 | 842 | put_elf_reloc(s1->symtab, s1->got, attr->got_offset, |
| 834 | | − R_DATA_PTR, sym_index); |
| 843 | + R_JMP_SLOT, sym_index); |
| 835 | 844 | goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti)); |
| 836 | 845 | if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) { |
| 837 | 846 | if (sym->st_shndx == SHN_UNDEF) |
| @@ -852,7 +861,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 14 unmodified lines |
| 852 | 861 | (mo->n_bind + 1) * |
| 853 | 862 | sizeof(struct bind)); |
| 854 | 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 | 865 | mo->bind[mo->n_bind].rel.r_offset = attr->got_offset; |
| 857 | 866 | mo->n_bind++; |
| 858 | 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 | 945 | bind_offset; |
| 937 | 946 | mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset = |
| 938 | 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 | 949 | mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset = |
| 941 | 950 | attr->plt_offset; |
| 942 | 951 | mo->n_lazy_bind++; |
| @@ -948,13 +957,13 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 5 unmodified lines |
| 948 | 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 | 961 | if (sym->st_shndx == SHN_UNDEF) { |
| 953 | 962 | mo->bind = tcc_realloc(mo->bind, |
| 954 | 963 | (mo->n_bind + 1) * |
| 955 | 964 | sizeof(struct bind)); |
| 956 | 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 | 967 | mo->n_bind++; |
| 959 | 968 | } |
| 960 | 969 | else { |
| @@ -962,7 +971,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 962 | 971 | tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * |
| 963 | 972 | sizeof(struct s_rebase)); |
| 964 | 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 | 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 | 1017 | if (mo->iundef == -1) |
| 1009 | 1018 | mo->iundef = sym_index - 1; |
| 1010 | 1019 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK |
| 1020 | + || s1->output_type != TCC_OUTPUT_EXE |
| 1011 | 1021 | || find_elf_sym(s1->dynsymtab_section, name)) { |
| 1012 | 1022 | /* Mark the symbol as coming from a dylib so that |
| 1013 | 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 | 1180 | mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 1171 | 1181 | #endif |
| 1172 | 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 | 1185 | mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE); |
| 1175 | 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 | 1193 | pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name); |
| 1183 | 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 | 1197 | tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1); |
| 1186 | 1198 | mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym)); |
| 1187 | 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 | 1263 | size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8; |
| 1252 | 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 | 1266 | int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE; |
| 1255 | 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 | 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 | 1285 | uint8_t *ptr, int opcode, |
| 1274 | 1286 | Section *sec, addr_t offset) |
| 1275 | 1287 | { |
| 1276 | 1288 | int i; |
| 1277 | 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 | 1292 | seg = get_segment(mo, i); |
| 1281 | 1293 | if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize)) |
| 1282 | 1294 | break; |
| @@ -1301,7 +1313,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 18 unmodified lines |
| 1301 | 1313 | mo->s_lazy_bind[i].bind_offset, |
| 1302 | 1314 | mo->lazy_binding->data_offset); |
| 1303 | 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 | 1317 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1306 | 1318 | mo->lazy_binding, |
| 1307 | 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 | 1333 | ptr = section_ptr_add(mo->rebase, 2); |
| 1322 | 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 | 1336 | REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1325 | 1337 | mo->rebase, |
| 1326 | 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 | 1349 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1338 | 1350 | binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK |
| 1339 | 1351 | ? mo->weak_binding : mo->binding; |
| 1340 | | − ptr = section_ptr_add(binding, 5 + strlen(name)); |
| 1341 | | − *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | |
| 1342 | | − (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf); |
| 1343 | | − *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0; |
| 1352 | + ptr = section_ptr_add(binding, 4 + (binding == mo->binding) + |
| 1353 | + strlen(name)); |
| 1354 | + if (binding == mo->binding) |
| 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 | 1360 | strcpy((char *)ptr, name); |
| 1345 | 1361 | ptr += strlen(name) + 1; |
| 1346 | 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 | 1364 | BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB, |
| 1349 | 1365 | binding, |
| 1350 | 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 | 1505 | struct trie_info *a = (struct trie_info *) _a; |
| 1490 | 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 | 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 | 1523 | struct trie_info *trie = NULL, *p_trie; |
| 1503 | 1524 | struct trie_node node, *p_node; |
| 1504 | 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 | 1528 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { |
| 1508 | 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 | 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 | 1602 | int i, sk, numsec; |
| 1582 | 1603 | int used_segment[N_SEGMENT]; |
| 1583 | 1604 | uint64_t curaddr, fileofs; |
| 1584 | 1605 | Section *s; |
| 1585 | 1606 | struct segment_command_64 *seg; |
| 1607 | + struct dylib_command *dylib; |
| 1586 | 1608 | #ifdef CONFIG_NEW_MACHO |
| 1587 | 1609 | struct linkedit_data_command *chained_fixups_lc; |
| 1588 | 1610 | struct linkedit_data_command *export_trie_lc; |
| 1589 | 1611 | #endif |
| 1590 | 1612 | struct build_version_command *dyldbv; |
| 1591 | 1613 | struct source_version_command *dyldsv; |
| 1614 | + struct rpath_command *rpath; |
| 1592 | 1615 | struct dylinker_command *dyldlc; |
| 1593 | 1616 | struct symtab_command *symlc; |
| 1594 | 1617 | struct dysymtab_command *dysymlc; |
| @@ -1662,10 +1685,16 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 67 unmodified lines |
| 1662 | 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 | 1691 | for (i = 0; i < N_SEGMENT; i++) |
| 1666 | 1692 | if (used_segment[i]) { |
| 1667 | 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 | 1698 | seg->vmsize = all_segment[i].vmsize; |
| 1670 | 1699 | seg->maxprot = all_segment[i].maxprot; |
| 1671 | 1700 | seg->initprot = all_segment[i].initprot; |
| @@ -1675,6 +1704,17 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 3 unmodified lines |
| 1675 | 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 | 1718 | #ifdef CONFIG_NEW_MACHO |
| 1679 | 1719 | chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, |
| 1680 | 1720 | sizeof(struct linkedit_data_command)); |
| @@ -1687,11 +1727,13 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 6 unmodified lines |
| 1687 | 1727 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); |
| 1688 | 1728 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); |
| 1689 | 1729 | |
| 1690 | | − i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; |
| 1691 | | − dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); |
| 1692 | | − dyldlc->name = sizeof(*dyldlc); |
| 1693 | | − str = (char*)dyldlc + dyldlc->name; |
| 1694 | | − strcpy(str, "/usr/lib/dyld"); |
| 1730 | + if (s1->output_type == TCC_OUTPUT_EXE) { |
| 1731 | + i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; |
| 1732 | + dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); |
| 1733 | + dyldlc->name = sizeof(*dyldlc); |
| 1734 | + str = (char*)dyldlc + dyldlc->name; |
| 1735 | + strcpy(str, "/usr/lib/dyld"); |
| 1736 | + } |
| 1695 | 1737 | |
| 1696 | 1738 | dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); |
| 1697 | 1739 | dyldbv->platform = PLATFORM_MACOS; |
| @@ -1702,8 +1744,10 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 4 unmodified lines |
| 1702 | 1744 | dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); |
| 1703 | 1745 | dyldsv->version = 0; |
| 1704 | 1746 | |
| 1705 | | − mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| 1706 | | − mo->ep->entryoff = 4096; |
| 1747 | + if (s1->output_type == TCC_OUTPUT_EXE) { |
| 1748 | + mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| 1749 | + mo->ep->entryoff = 4096; |
| 1750 | + } |
| 1707 | 1751 | |
| 1708 | 1752 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 1709 | 1753 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -1711,13 +1755,21 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 1711 | 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 | 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 | 1768 | curaddr += 4096; |
| 1717 | 1769 | seg = NULL; |
| 1718 | 1770 | numsec = 0; |
| 1719 | 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 | 1773 | struct section_64 *sec = NULL; |
| 1722 | 1774 | if (seg) { |
| 1723 | 1775 | seg->vmsize = curaddr - seg->vmaddr; |
| @@ -1734,7 +1786,8 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 10 unmodified lines |
| 1734 | 1786 | export_trie(s1, mo); |
| 1735 | 1787 | } |
| 1736 | 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 | 1791 | uint64_t al = 0; |
| 1739 | 1792 | int si; |
| 1740 | 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 | 1942 | mo->mh.mh.cputype = CPU_TYPE_ARM64; |
| 1890 | 1943 | mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL; |
| 1891 | 1944 | #endif |
| 1892 | | − mo->mh.mh.filetype = MH_EXECUTE; |
| 1893 | | − mo->mh.mh.flags = MH_DYLDLINK | MH_PIE; |
| 1945 | + if (s1->output_type == TCC_OUTPUT_EXE) { |
| 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 | 1953 | mo->mh.mh.ncmds = mo->nlc; |
| 1895 | 1954 | mo->mh.mh.sizeofcmds = 0; |
| 1896 | 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 | 1965 | for (sk = sk_unknown; sk < sk_last; sk++) { |
| 1907 | 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 | 1969 | continue; |
| 1910 | 1970 | /*seg =*/ get_segment(mo, mo->segment[sk]); |
| 1911 | 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 | 2029 | image = (struct dyld_chained_starts_in_image *) data; |
| 1970 | 2030 | data += (size + 7) & -8; |
| 1971 | 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 | 2033 | image->seg_info_offset[i] = (data - mo->chained_fixups->data) - |
| 1974 | 2034 | header->starts_offset; |
| 1975 | 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 | 2177 | check_relocs(s1, &mo); |
| 2118 | 2178 | ret = check_symbols(s1, &mo); |
| 2119 | 2179 | if (!ret) { |
| 2120 | | − collect_sections(s1, &mo); |
| 2180 | + collect_sections(s1, &mo, filename); |
| 2121 | 2181 | relocate_syms(s1, s1->symtab, 0); |
| 2122 | | − mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1) |
| 2123 | | − - get_segment(&mo, 1)->vmaddr; |
| 2182 | + if (s1->output_type == TCC_OUTPUT_EXE) |
| 2183 | + mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1) |
| 2184 | + - get_segment(&mo, 1)->vmaddr; |
| 2124 | 2185 | if (s1->nb_errors) |
| 2125 | 2186 | goto do_ret; |
| 2126 | 2187 | relocate_sections(s1); |