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 | 410 | struct macho { |
| 411 | 411 | struct mach_header_64 mh; |
| 412 | − int seg2lc[6], nseg; | |
| 412 | + int *seg2lc, nseg; | |
| 413 | 413 | struct load_command **lc; |
| 414 | 414 | struct entry_point_command *ep; |
| 415 | 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 | 475 | struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc)); |
| 476 | 476 | strncpy(sc->segname, name, 16); |
| 477 | + mo->seg2lc = tcc_realloc(mo->seg2lc, sizeof(*mo->seg2lc) * (mo->nseg + 1)); | |
| 477 | 478 | mo->seg2lc[mo->nseg++] = mo->nlc - 1; |
| 478 | 479 | return sc; |
| 479 | 480 | } |
| @@ -1221,6 +1222,27 @@ const struct { · 741 unmodified lines | ||
| 1221 | 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 | 1246 | #ifdef CONFIG_NEW_MACHO |
| 1225 | 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 | 1579 | static void collect_sections(TCCState *s1, struct macho *mo) |
| 1558 | 1580 | { |
| 1559 | 1581 | int i, sk, numsec; |
| 1582 | + int used_segment[N_SEGMENT]; | |
| 1560 | 1583 | uint64_t curaddr, fileofs; |
| 1561 | 1584 | Section *s; |
| 1562 | − struct segment_command_64 *seg = NULL; | |
| 1585 | + struct segment_command_64 *seg; | |
| 1563 | 1586 | #ifdef CONFIG_NEW_MACHO |
| 1564 | 1587 | struct linkedit_data_command *chained_fixups_lc; |
| 1565 | 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 | 1594 | struct dysymtab_command *dysymlc; |
| 1572 | 1595 | char *str; |
| 1573 | 1596 | |
| 1574 | − for (sk = sk_unknown; sk < sk_last; sk++) | |
| 1575 | − mo->segment[sk] = skinfo[sk].seg_initial; | |
| 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 | − } | |
| 1597 | + for (i = 0; i < N_SEGMENT; i++) | |
| 1598 | + used_segment[i] = all_segment[i].used; | |
| 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 | 1600 | memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect)); |
| 1652 | 1601 | for (i = s1->nb_sections; i-- > 1;) { |
| 1653 | 1602 | int type, flags; |
| @@ -1710,7 +1659,58 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 56 unmodified lines | ||
| 1710 | 1659 | sk = sk_discard; |
| 1711 | 1660 | s->prev = mo->sk_to_sect[sk].s; |
| 1712 | 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 | 1714 | fileofs = 4096; /* leave space for mach-o headers */ |
| 1715 | 1715 | curaddr = get_segment(mo, 1)->vmaddr; |
| 1716 | 1716 | curaddr += 4096; |
| @@ -2134,6 +2134,7 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 417 unmodified lines | ||
| 2134 | 2134 | do_ret: |
| 2135 | 2135 | for (i = 0; i < mo.nlc; i++) |
| 2136 | 2136 | tcc_free(mo.lc[i]); |
| 2137 | + tcc_free(mo.seg2lc); | |
| 2137 | 2138 | tcc_free(mo.lc); |
| 2138 | 2139 | tcc_free(mo.elfsectomacho); |
| 2139 | 2140 | tcc_free(mo.e2msym); |