History

Update load segment code for macho

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.

herman ten brugge committed 3 years ago

Commit e2db3a51 parent 7cc1cc31 file · +79 −78Browse files

Unified · Split

tccmacho.c+79−78
@@ -409,7 +409,7 @@ struct nlist_64 { · 408 unmodified lines
409 409
410struct macho {410struct 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
1227const 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_MACHO1246#ifdef CONFIG_NEW_MACHO
1225static void calc_fixup_size(TCCState *s1, struct macho *mo)1247static 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
1557static void collect_sections(TCCState *s1, struct macho *mo)1579static 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_MACHO1586#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);

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