| @@ -107,6 +107,8 @@ struct load_command { · 106 unmodified lines |
| 107 | 107 | #define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) |
| 108 | 108 | #define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) |
| 109 | 109 | #define LC_MAIN (0x28|LC_REQ_DYLD) |
| 110 | +#define LC_SOURCE_VERSION 0x2A |
| 111 | +#define LC_BUILD_VERSION 0x32 |
| 110 | 112 | #define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) |
| 111 | 113 | #define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) |
| 112 | 114 | |
| @@ -256,6 +258,24 @@ struct linkedit_data_command { · 143 unmodified lines |
| 256 | 258 | uint32_t datasize; /* file size of data in __LINKEDIT segment */ |
| 257 | 259 | }; |
| 258 | 260 | |
| 261 | +#define PLATFORM_MACOS 1 |
| 262 | + |
| 263 | +struct build_version_command { |
| 264 | + uint32_t cmd; /* LC_BUILD_VERSION */ |
| 265 | + uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ |
| 266 | + /* ntools * sizeof(struct build_tool_version) */ |
| 267 | + uint32_t platform; /* platform */ |
| 268 | + uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ |
| 269 | + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ |
| 270 | + uint32_t ntools; /* number of tool entries following this */ |
| 271 | +}; |
| 272 | + |
| 273 | +struct source_version_command { |
| 274 | + uint32_t cmd; /* LC_SOURCE_VERSION */ |
| 275 | + uint32_t cmdsize; /* 16 */ |
| 276 | + uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ |
| 277 | +}; |
| 278 | + |
| 259 | 279 | struct symtab_command { |
| 260 | 280 | uint32_t cmd; /* LC_SYMTAB */ |
| 261 | 281 | uint32_t cmdsize; /* sizeof(struct symtab_command) */ |
| @@ -492,7 +512,17 @@ static void * add_dylib(struct macho *mo, char *name) · 230 unmodified lines |
| 492 | 512 | return lc; |
| 493 | 513 | } |
| 494 | 514 | |
| 495 | | −#ifndef CONFIG_NEW_MACHO |
| 515 | +static int uleb128_size (unsigned long long value) |
| 516 | +{ |
| 517 | + int size = 0; |
| 518 | + |
| 519 | + do { |
| 520 | + value >>= 7; |
| 521 | + size++; |
| 522 | + } while (value != 0); |
| 523 | + return size; |
| 524 | +} |
| 525 | + |
| 496 | 526 | static void write_uleb128(Section *section, uint64_t value) |
| 497 | 527 | { |
| 498 | 528 | do { |
| @@ -503,7 +533,6 @@ static void write_uleb128(Section *section, uint64_t value) · 4 unmodified lines |
| 503 | 533 | *ptr = byte | (value ? 0x80 : 0); |
| 504 | 534 | } while (value != 0); |
| 505 | 535 | } |
| 506 | | −#endif |
| 507 | 536 | |
| 508 | 537 | static void tcc_macho_add_destructor(TCCState *s1) |
| 509 | 538 | { |
| @@ -512,15 +541,15 @@ static void tcc_macho_add_destructor(TCCState *s1) · 2 unmodified lines |
| 512 | 541 | ElfW_Rel *rel; |
| 513 | 542 | uint8_t *ptr; |
| 514 | 543 | |
| 544 | + mh_execute_header = put_elf_sym(s1->symtab, -4096, 0, |
| 545 | + ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 0, |
| 546 | + text_section->sh_num, "__mh_execute_header"); |
| 515 | 547 | s = find_section(s1, ".fini_array"); |
| 516 | 548 | if (s->data_offset == 0) |
| 517 | 549 | return; |
| 518 | 550 | init_sym = put_elf_sym(s1->symtab, text_section->data_offset, 0, |
| 519 | 551 | ELFW(ST_INFO)(STB_LOCAL, STT_FUNC), 0, |
| 520 | 552 | text_section->sh_num, "___GLOBAL_init_65535"); |
| 521 | | − mh_execute_header = put_elf_sym(s1->symtab, 0x100000000ll, 0, |
| 522 | | − ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT), 0, |
| 523 | | − SHN_ABS, "__mh_execute_header"); |
| 524 | 553 | at_exit_sym = put_elf_sym(s1->symtab, 0, 0, |
| 525 | 554 | ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, |
| 526 | 555 | SHN_UNDEF, "___cxa_atexit"); |
| @@ -674,11 +703,11 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 147 unmodified lines |
| 674 | 703 | attr->plt_offset = 0; // ignore next bind |
| 675 | 704 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); |
| 676 | 705 | } |
| 677 | | − if (for_code) |
| 706 | + if (for_code && sym->st_shndx == SHN_UNDEF) |
| 678 | 707 | s1->got->reloc->data_offset -= sizeof (ElfW_Rel); |
| 679 | 708 | } |
| 680 | 709 | } |
| 681 | | − if (for_code) { |
| 710 | + if (for_code && sym->st_shndx == SHN_UNDEF) { |
| 682 | 711 | if (attr->plt_offset == -1) { |
| 683 | 712 | uint8_t *jmp; |
| 684 | 713 | |
| @@ -1312,27 +1341,103 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 627 unmodified lines |
| 1312 | 1341 | } |
| 1313 | 1342 | #endif |
| 1314 | 1343 | |
| 1315 | | −/* FIXME */ |
| 1344 | +struct trie { |
| 1345 | + const char *name; |
| 1346 | + int flag; |
| 1347 | + addr_t addr; |
| 1348 | + int offset_size; |
| 1349 | + int str_size; |
| 1350 | + int term_size; |
| 1351 | + int term_offset; |
| 1352 | +}; |
| 1353 | + |
| 1354 | +static int triecmp(const void *_a, const void *_b, void *arg) |
| 1355 | +{ |
| 1356 | + struct trie *a = (struct trie *) _a; |
| 1357 | + struct trie *b = (struct trie *) _b; |
| 1358 | + |
| 1359 | + return strcmp(a->name, b->name); |
| 1360 | +} |
| 1361 | + |
| 1316 | 1362 | static void export_trie(TCCState *s1, struct macho *mo) |
| 1317 | 1363 | { |
| 1364 | + int i, j, n, m, offset; |
| 1365 | + uint8_t *ptr; |
| 1318 | 1366 | int sym_index; |
| 1319 | | − int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));; |
| 1367 | + int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); |
| 1368 | + int n_trie = 0; |
| 1369 | + struct trie *trie = NULL; |
| 1370 | + addr_t vm_addr = get_segment(mo, 1)->vmaddr; |
| 1320 | 1371 | |
| 1321 | 1372 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { |
| 1322 | 1373 | ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index; |
| 1323 | 1374 | const char *name = (char*)symtab_section->link->data + sym->st_name; |
| 1324 | 1375 | |
| 1325 | | − if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE && |
| 1326 | | − ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL) { |
| 1376 | + if (sym->st_shndx == text_section->sh_num && |
| 1377 | + (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL || |
| 1378 | + ELFW(ST_BIND)(sym->st_info) == STB_WEAK)) { |
| 1327 | 1379 | int flag = EXPORT_SYMBOL_FLAGS_KIND_REGULAR; |
| 1380 | + addr_t addr = |
| 1381 | + sym->st_value + s1->sections[sym->st_shndx]->sh_addr - vm_addr; |
| 1328 | 1382 | |
| 1329 | | − if (sym->st_shndx == SHN_ABS) |
| 1330 | | − flag = EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE; |
| 1331 | 1383 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) |
| 1332 | 1384 | flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; |
| 1333 | | − dprintf ("%s %d %llx\n", name, flag, sym->st_value + s1->sections[sym->st_shndx]->sh_addr); |
| 1385 | + dprintf ("%s %d %llx\n", name, flag, addr + vm_addr); |
| 1386 | + trie = tcc_realloc(trie, (n_trie + 1) * sizeof(struct trie)); |
| 1387 | + trie[n_trie].name = name; |
| 1388 | + trie[n_trie].flag = flag; |
| 1389 | + trie[n_trie].addr = addr; |
| 1390 | + trie[n_trie].offset_size = 1; |
| 1391 | + trie[n_trie].str_size = strlen(name) + 1; |
| 1392 | + trie[n_trie].term_size = uleb128_size(flag) + uleb128_size(addr); |
| 1393 | + trie[n_trie].term_offset = 0; |
| 1394 | + n_trie++; |
| 1334 | 1395 | } |
| 1335 | 1396 | } |
| 1397 | + /* FIXME: generate tree */ |
| 1398 | + if (n_trie > 255) { |
| 1399 | + tcc_warning("Fix trie code. n_trie(%d) > 255", n_trie); |
| 1400 | + n_trie = 255; |
| 1401 | + } |
| 1402 | + if (n_trie) { |
| 1403 | + tcc_qsort(trie, n_trie, sizeof(struct trie), triecmp, NULL); |
| 1404 | + offset = 1 + 1; |
| 1405 | + for (i = 0; i < n_trie; i++) |
| 1406 | + offset += trie[i].str_size + trie[i].offset_size; |
| 1407 | + for (i = 0; i < n_trie; i++) { |
| 1408 | + n = uleb128_size(offset); |
| 1409 | + trie[i].term_offset = offset + n - 1; |
| 1410 | + trie[i].offset_size = n; |
| 1411 | + offset += 1 + trie[i].term_size + 1 + n - 1; |
| 1412 | + if (n > 1) |
| 1413 | + for (j = i - 1; j >= 0; j--) { |
| 1414 | + trie[j].term_offset += n - 1; |
| 1415 | + m = uleb128_size(trie[j].term_offset); |
| 1416 | + if (m != trie[j].offset_size) { |
| 1417 | + n += m - trie[j].offset_size; |
| 1418 | + offset += m - trie[j].offset_size; |
| 1419 | + trie[j].offset_size = m; |
| 1420 | + } |
| 1421 | + } |
| 1422 | + } |
| 1423 | + ptr = section_ptr_add(mo->exports, 2); |
| 1424 | + *ptr++ = 0; |
| 1425 | + *ptr = n_trie; |
| 1426 | + for (i = 0; i < n_trie; i++) { |
| 1427 | + ptr = section_ptr_add(mo->exports, trie[i].str_size); |
| 1428 | + memcpy(ptr, trie[i].name, trie[i].str_size); |
| 1429 | + write_uleb128(mo->exports, trie[i].term_offset); |
| 1430 | + } |
| 1431 | + for (i = 0; i < n_trie; i++) { |
| 1432 | + write_uleb128(mo->exports, trie[i].term_size); |
| 1433 | + write_uleb128(mo->exports, trie[i].flag); |
| 1434 | + write_uleb128(mo->exports, trie[i].addr); |
| 1435 | + ptr = section_ptr_add(mo->exports, 1); |
| 1436 | + *ptr = 0; |
| 1437 | + } |
| 1438 | + section_ptr_add(mo->exports, -mo->exports->data_offset & 7); |
| 1439 | + } |
| 1440 | + tcc_free(trie); |
| 1336 | 1441 | } |
| 1337 | 1442 | |
| 1338 | 1443 | static void collect_sections(TCCState *s1, struct macho *mo) |
| @@ -1345,6 +1450,8 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 6 unmodified lines |
| 1345 | 1450 | struct linkedit_data_command *chained_fixups_lc; |
| 1346 | 1451 | struct linkedit_data_command *export_trie_lc; |
| 1347 | 1452 | #endif |
| 1453 | + struct build_version_command *dyldbv; |
| 1454 | + struct source_version_command *dyldsv; |
| 1348 | 1455 | struct dylinker_command *dyldlc; |
| 1349 | 1456 | struct symtab_command *symlc; |
| 1350 | 1457 | struct dysymtab_command *dysymlc; |
| @@ -1377,8 +1484,8 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 26 unmodified lines |
| 1377 | 1484 | mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo)); |
| 1378 | 1485 | #endif |
| 1379 | 1486 | |
| 1380 | | − mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| 1381 | | − mo->ep->entryoff = 4096; |
| 1487 | + symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); |
| 1488 | + dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); |
| 1382 | 1489 | |
| 1383 | 1490 | i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8; |
| 1384 | 1491 | dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i); |
| @@ -1386,8 +1493,17 @@ static void collect_sections(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 1386 | 1493 | str = (char*)dyldlc + dyldlc->name; |
| 1387 | 1494 | strcpy(str, "/usr/lib/dyld"); |
| 1388 | 1495 | |
| 1389 | | − symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc)); |
| 1390 | | − dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc)); |
| 1496 | + dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv)); |
| 1497 | + dyldbv->platform = PLATFORM_MACOS; |
| 1498 | + dyldbv->minos = (10 << 16) + (6 << 8); |
| 1499 | + dyldbv->sdk = (10 << 16) + (6 << 8); |
| 1500 | + dyldbv->ntools = 0; |
| 1501 | + |
| 1502 | + dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv)); |
| 1503 | + dyldsv->version = 0; |
| 1504 | + |
| 1505 | + mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep)); |
| 1506 | + mo->ep->entryoff = 4096; |
| 1391 | 1507 | |
| 1392 | 1508 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 1393 | 1509 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -1710,7 +1826,9 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 316 unmodified lines |
| 1710 | 1826 | sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info); |
| 1711 | 1827 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1712 | 1828 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1713 | | − tcc_error("Overlap bind/rebase %s:%s", |
| 1829 | + tcc_error("Overlap %s/%s %s:%s", |
| 1830 | + mo->bind_rebase[i].bind ? "bind" : "rebase", |
| 1831 | + mo->bind_rebase[i + 1].bind ? "bind" : "rebase", |
| 1714 | 1832 | s1->sections[mo->bind_rebase[i].section]->name, name); |
| 1715 | 1833 | } |
| 1716 | 1834 | header = (struct dyld_chained_fixups_header *) data; |
| @@ -1832,7 +1950,7 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 115 unmodified lines |
| 1832 | 1950 | import[bind_index].weak_import = |
| 1833 | 1951 | ELFW(ST_BIND)(sym->st_info) == STB_WEAK; |
| 1834 | 1952 | name = (char *) symtab_section->link->data + sym->st_name; |
| 1835 | | − strcpy(data, name); |
| 1953 | + strcpy((char *) data, name); |
| 1836 | 1954 | data += strlen(name) + 1; |
| 1837 | 1955 | bind_index++; |
| 1838 | 1956 | } |
| @@ -1893,6 +2011,17 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename) · 54 unmodified lines |
| 1893 | 2011 | tcc_free(mo.e2msym); |
| 1894 | 2012 | |
| 1895 | 2013 | fclose(fp); |
| 2014 | +#ifdef CONFIG_CODESIGN |
| 2015 | + { |
| 2016 | + char command[1024]; |
| 2017 | + int retval; |
| 2018 | + |
| 2019 | + snprintf(command, sizeof(command), "codesign -f -s - %s", filename); |
| 2020 | + retval = system (command); |
| 2021 | + if (retval == -1 || !(WIFEXITED(retval) && WEXITSTATUS(retval) == 0)) |
| 2022 | + tcc_error ("command failed '%s'", command); |
| 2023 | + } |
| 2024 | +#endif |
| 1896 | 2025 | return ret; |
| 1897 | 2026 | } |
| 1898 | 2027 | |