Add an array with segement to load instead of code. Dynamically check if segment is used or not. This fixes the strange __DWARF code segment handling.
Unified · Split
| @@ -409,7 +409,7 @@ struct nlist_64 { · 408 unmodified lines | |||
| 409 | 409 | ||
| 410 | struct macho { | 410 | struct macho { |
| 411 | struct mach_header_64 mh; | 411 | struct mach_header_64 mh; |
| 412 | int seg2lc[6], nseg; | 412 | int *seg2lc, nseg; |
| 413 | struct load_command **lc; | 413 | struct load_command **lc; |
| 414 | struct entry_point_command *ep; | 414 | struct entry_point_command *ep; |
| 415 | int nlc; | 415 | int nlc; |
| @@ -474,6 +474,7 @@ static struct segment_command_64 * add_segment(struct macho *mo, const char *nam · 58 unmodified lines | |||
| 474 | { | 474 | { |
| 475 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); | 475 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); |
| 476 | strncpy(sc->segname, name, 16); | 476 | strncpy(sc->segname, name, 16); |
| 477 | mo->seg2lc = tcc_realloc(mo->seg2lc, sizeof(*mo->seg2lc) * (mo->nseg + 1)); | ||
| 477 | mo->seg2lc[mo->nseg++] = mo->nlc - 1; | 478 | mo->seg2lc[mo->nseg++] = mo->nlc - 1; |
| 478 | return sc; | 479 | return sc; |
| 479 | } | 480 | } |
| @@ -1221,6 +1222,27 @@ const struct { · 741 unmodified lines | |||
| 1221 | /*[sk_linkedit] =*/ { 5, S_REGULAR, NULL }, | 1222 | /*[sk_linkedit] =*/ { 5, S_REGULAR, NULL }, |
| 1222 | }; | 1223 | }; |
| 1223 | 1224 | ||
| 1225 | #define START ((uint64_t)1 << 32) | ||
| 1226 | |||
| 1227 | const struct { | ||
| 1228 | int used; | ||
| 1229 | const char *name; | ||
| 1230 | uint64_t vmaddr; | ||
| 1231 | uint64_t vmsize; | ||
| 1232 | vm_prot_t maxprot; | ||
| 1233 | vm_prot_t initprot; | ||
| 1234 | uint32_t flags; | ||
| 1235 | } all_segment[] = { | ||
| 1236 | { 1, "__PAGEZERO", 0, START, 0, 0, 0 }, | ||
| 1237 | { 0, "__TEXT", START, 0, 5, 5, 0 }, | ||
| 1238 | { 0, "__DATA_CONST", -1, 0, 3, 3, SG_READ_ONLY }, | ||
| 1239 | { 0, "__DWARF", -1, 0, 7, 3, 0 }, | ||
| 1240 | { 0, "__DATA", -1, 0, 3, 3, 0 }, | ||
| 1241 | { 1, "__LINKEDIT", -1, 0, 1, 1, 0 }, | ||
| 1242 | }; | ||
| 1243 | |||
| 1244 | #define N_SEGMENT (sizeof(all_segment)/sizeof(all_segment[0])) | ||
| 1245 | |||
| 1224 | #ifdef CONFIG_NEW_MACHO | 1246 | #ifdef CONFIG_NEW_MACHO |
| 1225 | static void calc_fixup_size(TCCState *s1, struct macho *mo) | 1247 | static void calc_fixup_size(TCCState *s1, struct macho *mo) |
| 1226 | { | 1248 | { |
| @@ -1557,9 +1579,10 @@ static void export_trie(TCCState *s1, struct macho *mo) · 330 unmodified lines | |||
| 1557 | static void collect_sections(TCCState *s1, struct macho *mo) | 1579 | static void collect_sections(TCCState *s1, struct macho *mo) |
| 1558 | { | 1580 | { |
| 1559 | int i, sk, numsec; | 1581 | int i, sk, numsec; |
| 1582 | int used_segment[N_SEGMENT]; | ||
| 1560 | uint64_t curaddr, fileofs; | 1583 | uint64_t curaddr, fileofs; |
| 1561 | Section *s; | 1584 | Section *s; |
| 1562 | struct segment_command_64 *seg = NULL; | 1585 | struct segment_command_64 *seg; |
| 1563 | #ifdef CONFIG_NEW_MACHO | 1586 | #ifdef CONFIG_NEW_MACHO |
| 1564 | struct linkedit_data_command *chained_fixups_lc; | 1587 | struct linkedit_data_command *chained_fixups_lc; |
| 1565 | struct linkedit_data_command *export_trie_lc; | 1588 | struct linkedit_data_command *export_trie_lc; |
| @@ -1571,83 +1594,9 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 5 unmodified lines | |||
| 1571 | struct dysymtab_command *dysymlc; | 1594 | struct dysymtab_command *dysymlc; |
| 1572 | char *str; | 1595 | char *str; |
| 1573 | 1596 | ||
| 1574 | for (sk = sk_unknown; sk < sk_last; sk++) | 1597 | for (i = 0; i < N_SEGMENT; i++) |
| 1575 | mo->segment[sk] = skinfo[sk].seg_initial; | 1598 | used_segment[i] = all_segment[i].used; |
| 1576 | |||
| 1577 | seg = add_segment(mo, "__PAGEZERO"); | ||
| 1578 | seg->vmsize = (uint64_t)1 << 32; | ||
| 1579 | |||
| 1580 | seg = add_segment(mo, "__TEXT"); | ||
| 1581 | seg->vmaddr = (uint64_t)1 << 32; | ||
| 1582 | seg->maxprot = 5; // r-x | ||
| 1583 | seg->initprot = 5; // r-x | ||
| 1584 | |||
| 1585 | seg = add_segment(mo, "__DATA_CONST"); | ||
| 1586 | seg->vmaddr = -1; | ||
| 1587 | seg->maxprot = 3; // rw- | ||
| 1588 | seg->initprot = 3; // rw- | ||
| 1589 | seg->flags = SG_READ_ONLY; | ||
| 1590 | |||
| 1591 | if (dwarf_info_section) { | ||
| 1592 | seg = add_segment(mo, "__DWARF"); | ||
| 1593 | seg->vmaddr = -1; | ||
| 1594 | seg->maxprot = 7; // rwx | ||
| 1595 | seg->initprot = 3; // rw- | ||
| 1596 | } | ||
| 1597 | else | ||
| 1598 | for (sk = sk_unknown; sk < sk_last; sk++) | ||
| 1599 | if (mo->segment[sk] >= 4) | ||
| 1600 | mo->segment[sk]--; | ||
| 1601 | |||
| 1602 | seg = add_segment(mo, "__DATA"); | ||
| 1603 | seg->vmaddr = -1; | ||
| 1604 | seg->maxprot = 3; // rw- | ||
| 1605 | seg->initprot = 3; // rw- | ||
| 1606 | |||
| 1607 | seg = add_segment(mo, "__LINKEDIT"); | ||
| 1608 | seg->vmaddr = -1; | ||
| 1609 | seg->maxprot = 1; // r-- | ||
| 1610 | seg->initprot = 1; // r-- | ||
| 1611 | |||
| 1612 | #ifdef CONFIG_NEW_MACHO | ||
| 1613 | chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, | ||
| 1614 | sizeof(struct linkedit_data_command)); | ||
| 1615 | export_trie_lc = add_lc(mo, LC_DYLD_EXPORTS_TRIE, | ||
| 1616 | sizeof(struct linkedit_data_command)); | ||
| 1617 | #else | ||
| 1618 | mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo)); | ||
| 1619 | #endif | ||
| 1620 | |||
| 1621 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); | ||
| 1622 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); | ||
| 1623 | |||
| 1624 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; | ||
| 1625 | dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); | ||
| 1626 | dyldlc->name = sizeof(*dyldlc); | ||
| 1627 | str = (char*)dyldlc + dyldlc->name; | ||
| 1628 | strcpy(str, "/usr/lib/dyld"); | ||
| 1629 | |||
| 1630 | dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); | ||
| 1631 | dyldbv->platform = PLATFORM_MACOS; | ||
| 1632 | dyldbv->minos = (10 << 16) + (6 << 8); | ||
| 1633 | dyldbv->sdk = (10 << 16) + (6 << 8); | ||
| 1634 | dyldbv->ntools = 0; | ||
| 1635 | |||
| 1636 | dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); | ||
| 1637 | dyldsv->version = 0; | ||
| 1638 | |||
| 1639 | mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); | ||
| 1640 | mo->ep->entryoff = 4096; | ||
| 1641 | |||
| 1642 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | ||
| 1643 | DLLReference *dllref = s1->loaded_dlls[i]; | ||
| 1644 | if (dllref->level == 0) | ||
| 1645 | add_dylib(mo, dllref->name); | ||
| 1646 | } | ||
| 1647 | 1599 | ||
| 1648 | /* dyld requires a writable segment with classic Mach-O, but it ignores | ||
| 1649 | zero-sized segments for this, so force to have some data. */ | ||
| 1650 | section_ptr_add(data_section, 1); | ||
| 1651 | memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); | 1600 | memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); |
| 1652 | for (i = s1->nb_sections; i-- > 1;) { | 1601 | for (i = s1->nb_sections; i-- > 1;) { |
| 1653 | int type, flags; | 1602 | int type, flags; |
| @@ -1710,7 +1659,58 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 56 unmodified lines | |||
| 1710 | sk = sk_discard; | 1659 | sk = sk_discard; |
| 1711 | s->prev = mo->sk_to_sect[sk].s; | 1660 | s->prev = mo->sk_to_sect[sk].s; |
| 1712 | mo->sk_to_sect[sk].s = s; | 1661 | mo->sk_to_sect[sk].s = s; |
| 1662 | used_segment[skinfo[sk].seg_initial] = 1; | ||
| 1663 | } | ||
| 1664 | |||
| 1665 | for (i = 0; i < N_SEGMENT; i++) | ||
| 1666 | if (used_segment[i]) { | ||
| 1667 | seg = add_segment(mo, all_segment[i].name); | ||
| 1668 | seg->vmaddr = all_segment[i].vmaddr; | ||
| 1669 | seg->vmsize = all_segment[i].vmsize; | ||
| 1670 | seg->maxprot = all_segment[i].maxprot; | ||
| 1671 | seg->initprot = all_segment[i].initprot; | ||
| 1672 | seg->flags = all_segment[i].flags; | ||
| 1673 | for (sk = sk_unknown; sk < sk_last; sk++) | ||
| 1674 | if (skinfo[sk].seg_initial == i) | ||
| 1675 | mo->segment[sk] = mo->nseg - 1; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | #ifdef CONFIG_NEW_MACHO | ||
| 1679 | chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS, | ||
| 1680 | sizeof(struct linkedit_data_command)); | ||
| 1681 | export_trie_lc = add_lc(mo, LC_DYLD_EXPORTS_TRIE, | ||
| 1682 | sizeof(struct linkedit_data_command)); | ||
| 1683 | #else | ||
| 1684 | mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo)); | ||
| 1685 | #endif | ||
| 1686 | |||
| 1687 | symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); | ||
| 1688 | dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); | ||
| 1689 | |||
| 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"); | ||
| 1695 | |||
| 1696 | dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); | ||
| 1697 | dyldbv->platform = PLATFORM_MACOS; | ||
| 1698 | dyldbv->minos = (10 << 16) + (6 << 8); | ||
| 1699 | dyldbv->sdk = (10 << 16) + (6 << 8); | ||
| 1700 | dyldbv->ntools = 0; | ||
| 1701 | |||
| 1702 | dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); | ||
| 1703 | dyldsv->version = 0; | ||
| 1704 | |||
| 1705 | mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); | ||
| 1706 | mo->ep->entryoff = 4096; | ||
| 1707 | |||
| 1708 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | ||
| 1709 | DLLReference *dllref = s1->loaded_dlls[i]; | ||
| 1710 | if (dllref->level == 0) | ||
| 1711 | add_dylib(mo, dllref->name); | ||
| 1713 | } | 1712 | } |
| 1713 | |||
| 1714 | fileofs = 4096; /* leave space for mach-o headers */ | 1714 | fileofs = 4096; /* leave space for mach-o headers */ |
| 1715 | curaddr = get_segment(mo, 1)->vmaddr; | 1715 | curaddr = get_segment(mo, 1)->vmaddr; |
| 1716 | curaddr += 4096; | 1716 | curaddr += 4096; |
| @@ -2134,6 +2134,7 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 417 unmodified lines | |||
| 2134 | do_ret: | 2134 | do_ret: |
| 2135 | for (i = 0; i < mo.nlc; i++) | 2135 | for (i = 0; i < mo.nlc; i++) |
| 2136 | tcc_free(mo.lc[i]); | 2136 | tcc_free(mo.lc[i]); |
| 2137 | tcc_free(mo.seg2lc); | ||
| 2137 | tcc_free(mo.lc); | 2138 | tcc_free(mo.lc); |
| 2138 | tcc_free(mo.elfsectomacho); | 2139 | tcc_free(mo.elfsectomacho); |
| 2139 | tcc_free(mo.e2msym); | 2140 | tcc_free(mo.e2msym); |