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
409409
410410 struct macho {
411411 struct mach_header_64 mh;
412− int seg2lc[6], nseg;
412+ int *seg2lc, nseg;
413413 struct load_command **lc;
414414 struct entry_point_command *ep;
415415 int nlc;
@@ -474,6 +474,7 @@ static struct segment_command_64 * add_segment(struct macho *mo, const char *nam · 58 unmodified lines
474474 {
475475 struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc));
476476 strncpy(sc->segname, name, 16);
477+ mo->seg2lc = tcc_realloc(mo->seg2lc, sizeof(*mo->seg2lc) * (mo->nseg + 1));
477478 mo->seg2lc[mo->nseg++] = mo->nlc - 1;
478479 return sc;
479480 }
@@ -1221,6 +1222,27 @@ const struct { · 741 unmodified lines
12211222 /*[sk_linkedit] =*/ { 5, S_REGULAR, NULL },
12221223 };
12231224
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+
12241246 #ifdef CONFIG_NEW_MACHO
12251247 static void calc_fixup_size(TCCState *s1, struct macho *mo)
12261248 {
@@ -1557,9 +1579,10 @@ static void export_trie(TCCState *s1, struct macho *mo) · 330 unmodified lines
15571579 static void collect_sections(TCCState *s1, struct macho *mo)
15581580 {
15591581 int i, sk, numsec;
1582+ int used_segment[N_SEGMENT];
15601583 uint64_t curaddr, fileofs;
15611584 Section *s;
1562− struct segment_command_64 *seg = NULL;
1585+ struct segment_command_64 *seg;
15631586 #ifdef CONFIG_NEW_MACHO
15641587 struct linkedit_data_command *chained_fixups_lc;
15651588 struct linkedit_data_command *export_trie_lc;
@@ -1571,83 +1594,9 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 5 unmodified lines
15711594 struct dysymtab_command *dysymlc;
15721595 char *str;
15731596
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;
16471599
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);
16511600 memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect));
16521601 for (i = s1->nb_sections; i-- > 1;) {
16531602 int type, flags;
@@ -1710,7 +1659,58 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 56 unmodified lines
17101659 sk = sk_discard;
17111660 s->prev = mo->sk_to_sect[sk].s;
17121661 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);
17131712 }
1713+
17141714 fileofs = 4096; /* leave space for mach-o headers */
17151715 curaddr = get_segment(mo, 1)->vmaddr;
17161716 curaddr += 4096;
@@ -2134,6 +2134,7 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 417 unmodified lines
21342134 do_ret:
21352135 for (i = 0; i < mo.nlc; i++)
21362136 tcc_free(mo.lc[i]);
2137+ tcc_free(mo.seg2lc);
21372138 tcc_free(mo.lc);
21382139 tcc_free(mo.elfsectomacho);
21392140 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