I removed the FIXME for generating trie code with working code. I also fixed a problem where: cc -g -c a.c; cc -o a a.o created a bind/rebase error because the second cc did not use -g and .debug sections where not checked correctly. I also removed the elfinterp printout in tcc.c when TCC_TARGET_MACHO is set.
Unified · Split
| @@ -207,7 +207,7 @@ static void print_search_dirs(TCCState *s) · 206 unmodified lines | |||
| 207 | print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); | 207 | print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths); |
| 208 | print_dirs("libraries", s->library_paths, s->nb_library_paths); | 208 | print_dirs("libraries", s->library_paths, s->nb_library_paths); |
| 209 | printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1); | 209 | printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1); |
| 210 | #ifndef TCC_TARGET_PE | 210 | #if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO |
| 211 | print_dirs("crt", s->crt_paths, s->nb_crt_paths); | 211 | print_dirs("crt", s->crt_paths, s->nb_crt_paths); |
| 212 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); | 212 | printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s)); |
| 213 | #endif | 213 | #endif |
| @@ -650,7 +650,6 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 649 unmodified lines | |||
| 650 | ElfW_Rel *rel; | 650 | ElfW_Rel *rel; |
| 651 | ElfW(Sym) *sym; | 651 | ElfW(Sym) *sym; |
| 652 | int i, type, gotplt_entry, sym_index, for_code; | 652 | int i, type, gotplt_entry, sym_index, for_code; |
| 653 | int sh_num, debug; | ||
| 654 | uint32_t *pi, *goti; | 653 | uint32_t *pi, *goti; |
| 655 | struct sym_attr *attr; | 654 | struct sym_attr *attr; |
| 656 | 655 | ||
| @@ -659,12 +658,9 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 2 unmodified lines | |||
| 659 | mo->nr_plt = mo->n_got = 0; | 658 | mo->nr_plt = mo->n_got = 0; |
| 660 | for (i = 1; i < s1->nb_sections; i++) { | 659 | for (i = 1; i < s1->nb_sections; i++) { |
| 661 | s = s1->sections[i]; | 660 | s = s1->sections[i]; |
| 662 | if (s->sh_type != SHT_RELX) | 661 | if (s->sh_type != SHT_RELX || |
| 662 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) | ||
| 663 | continue; | 663 | continue; |
| 664 | sh_num = s1->sections[s->sh_info]->sh_num; | ||
| 665 | debug = sh_num >= s1->dwlo && sh_num < s1->dwhi; | ||
| 666 | if (debug) | ||
| 667 | continue; | ||
| 668 | for_each_elem(s, 0, rel, ElfW_Rel) { | 664 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| 669 | type = ELFW(R_TYPE)(rel->r_info); | 665 | type = ELFW(R_TYPE)(rel->r_info); |
| 670 | gotplt_entry = gotplt_entry_type(type); | 666 | gotplt_entry = gotplt_entry_type(type); |
| @@ -765,7 +761,7 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 94 unmodified lines | |||
| 765 | ElfW_Rel *rel; | 761 | ElfW_Rel *rel; |
| 766 | ElfW(Sym) *sym; | 762 | ElfW(Sym) *sym; |
| 767 | int i, type, gotplt_entry, sym_index, for_code; | 763 | int i, type, gotplt_entry, sym_index, for_code; |
| 768 | int sh_num, debug, bind_offset, la_symbol_offset; | 764 | int bind_offset, la_symbol_offset; |
| 769 | uint32_t *pi, *goti; | 765 | uint32_t *pi, *goti; |
| 770 | struct sym_attr *attr; | 766 | struct sym_attr *attr; |
| 771 | 767 | ||
| @@ -807,10 +803,9 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 35 unmodified lines | |||
| 807 | mo->nr_plt = mo->n_got = 0; | 803 | mo->nr_plt = mo->n_got = 0; |
| 808 | for (i = 1; i < s1->nb_sections; i++) { | 804 | for (i = 1; i < s1->nb_sections; i++) { |
| 809 | s = s1->sections[i]; | 805 | s = s1->sections[i]; |
| 810 | if (s->sh_type != SHT_RELX) | 806 | if (s->sh_type != SHT_RELX || |
| 807 | !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7)) | ||
| 811 | continue; | 808 | continue; |
| 812 | sh_num = s1->sections[s->sh_info]->sh_num; | ||
| 813 | debug = sh_num >= s1->dwlo && sh_num < s1->dwhi; | ||
| 814 | for_each_elem(s, 0, rel, ElfW_Rel) { | 809 | for_each_elem(s, 0, rel, ElfW_Rel) { |
| 815 | type = ELFW(R_TYPE)(rel->r_info); | 810 | type = ELFW(R_TYPE)(rel->r_info); |
| 816 | gotplt_entry = gotplt_entry_type(type); | 811 | gotplt_entry = gotplt_entry_type(type); |
| @@ -820,9 +815,8 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 3 unmodified lines | |||
| 820 | address due to codegen (i.e. a reloc requiring a got slot). */ | 815 | address due to codegen (i.e. a reloc requiring a got slot). */ |
| 821 | sym_index = ELFW(R_SYM)(rel->r_info); | 816 | sym_index = ELFW(R_SYM)(rel->r_info); |
| 822 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | 817 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 823 | if (!debug && | 818 | if (sym->st_shndx == SHN_UNDEF |
| 824 | (sym->st_shndx == SHN_UNDEF | 819 | || gotplt_entry == ALWAYS_GOTPLT_ENTRY) { |
| 825 | || gotplt_entry == ALWAYS_GOTPLT_ENTRY)) { | ||
| 826 | attr = get_sym_attr(s1, sym_index, 1); | 820 | attr = get_sym_attr(s1, sym_index, 1); |
| 827 | if (!attr->dyn_index) { | 821 | if (!attr->dyn_index) { |
| 828 | attr->got_offset = s1->got->data_offset; | 822 | attr->got_offset = s1->got->data_offset; |
| @@ -1041,8 +1035,7 @@ static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn) · 212 unmodified lines | |||
| 1041 | else if (sym->st_shndx >= SHN_LORESERVE) | 1035 | else if (sym->st_shndx >= SHN_LORESERVE) |
| 1042 | tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name); | 1036 | tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name); |
| 1043 | else if (!mo->elfsectomacho[sym->st_shndx]) { | 1037 | else if (!mo->elfsectomacho[sym->st_shndx]) { |
| 1044 | int sh_num = s1->sections[sym->st_shndx]->sh_num; | 1038 | if (strncmp(s1->sections[sym->st_shndx]->name, ".debug_", 7)) |
| 1045 | if (sh_num < s1->dwlo || sh_num >= s1->dwhi) | ||
| 1046 | tcc_error("ELF section %d(%s) not mapped into Mach-O for symbol %s", | 1039 | tcc_error("ELF section %d(%s) not mapped into Mach-O for symbol %s", |
| 1047 | sym->st_shndx, s1->sections[sym->st_shndx]->name, name); | 1040 | sym->st_shndx, s1->sections[sym->st_shndx]->name, name); |
| 1048 | } | 1041 | } |
| @@ -1341,32 +1334,139 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 292 unmodified lines | |||
| 1341 | } | 1334 | } |
| 1342 | #endif | 1335 | #endif |
| 1343 | 1336 | ||
| 1344 | struct trie { | 1337 | struct trie_info { |
| 1345 | const char *name; | 1338 | const char *name; |
| 1346 | int flag; | 1339 | int flag; |
| 1347 | addr_t addr; | 1340 | addr_t addr; |
| 1348 | int offset_size; | ||
| 1349 | int str_size; | 1341 | int str_size; |
| 1350 | int term_size; | 1342 | int term_size; |
| 1351 | int term_offset; | ||
| 1352 | }; | 1343 | }; |
| 1353 | 1344 | ||
| 1345 | struct trie_node { | ||
| 1346 | int start; | ||
| 1347 | int end; | ||
| 1348 | int index_start; | ||
| 1349 | int index_end; | ||
| 1350 | int n_child; | ||
| 1351 | struct trie_node *child; | ||
| 1352 | }; | ||
| 1353 | |||
| 1354 | struct trie_seq { | ||
| 1355 | int n_child; | ||
| 1356 | struct trie_node *node; | ||
| 1357 | int offset; | ||
| 1358 | int nest_offset; | ||
| 1359 | }; | ||
| 1360 | |||
| 1361 | static void create_trie(struct trie_node *node, | ||
| 1362 | int from, int to, int index_start, | ||
| 1363 | int n_trie, struct trie_info *trie) | ||
| 1364 | { | ||
| 1365 | int i; | ||
| 1366 | int start, end, index_end; | ||
| 1367 | char cur; | ||
| 1368 | struct trie_node *child; | ||
| 1369 | |||
| 1370 | for (i = from; i < to; i = end) { | ||
| 1371 | cur = trie[i].name[index_start]; | ||
| 1372 | start = i++; | ||
| 1373 | for (; i < to; i++) | ||
| 1374 | if (cur != trie[i].name[index_start]) | ||
| 1375 | break; | ||
| 1376 | end = i; | ||
| 1377 | if (start == end - 1 || | ||
| 1378 | (trie[start].name[index_start] && | ||
| 1379 | trie[start].name[index_start + 1] == 0)) | ||
| 1380 | index_end = trie[start].str_size - 1; | ||
| 1381 | else { | ||
| 1382 | index_end = index_start + 1; | ||
| 1383 | for (;;) { | ||
| 1384 | cur = trie[start].name[index_end]; | ||
| 1385 | for (i = start + 1; i < end; i++) | ||
| 1386 | if (cur != trie[i].name[index_end]) | ||
| 1387 | break; | ||
| 1388 | if (trie[start].name[index_end] && | ||
| 1389 | trie[start].name[index_end + 1] == 0) { | ||
| 1390 | end = start + 1; | ||
| 1391 | index_end = trie[start].str_size - 1; | ||
| 1392 | break; | ||
| 1393 | } | ||
| 1394 | if (i != end) | ||
| 1395 | break; | ||
| 1396 | index_end++; | ||
| 1397 | } | ||
| 1398 | } | ||
| 1399 | node->child = tcc_realloc(node->child, | ||
| 1400 | (node->n_child + 1) * | ||
| 1401 | sizeof(struct trie_node)); | ||
| 1402 | child = &node->child[node->n_child]; | ||
| 1403 | child->start = start; | ||
| 1404 | child->end = end; | ||
| 1405 | child->index_start = index_start; | ||
| 1406 | child->index_end = index_end; | ||
| 1407 | child->n_child = 0; | ||
| 1408 | child->child = NULL; | ||
| 1409 | node->n_child++; | ||
| 1410 | if (start != end - 1) | ||
| 1411 | create_trie(child, start, end, index_end, n_trie, trie); | ||
| 1412 | } | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | static int create_seq(int *offset, int *n_head, struct trie_seq **seq, | ||
| 1416 | struct trie_node *node, | ||
| 1417 | int n_trie, struct trie_info *trie) | ||
| 1418 | { | ||
| 1419 | int i, nest_offset, last_head = *n_head, retval = *offset; | ||
| 1420 | struct trie_seq *p_head; | ||
| 1421 | struct trie_node *p_nest; | ||
| 1422 | |||
| 1423 | for (i = 0; i < node->n_child; i++) { | ||
| 1424 | p_nest = &node->child[i]; | ||
| 1425 | *seq = tcc_realloc(*seq, (*n_head + 1) * sizeof(struct trie_seq)); | ||
| 1426 | p_head = &(*seq)[(*n_head)++]; | ||
| 1427 | p_head->n_child = i == 0 ? node->n_child : -1; | ||
| 1428 | p_head->node = p_nest; | ||
| 1429 | p_head->offset = *offset; | ||
| 1430 | p_head->nest_offset = 0; | ||
| 1431 | *offset += (i == 0 ? 1 + 1 : 0) + | ||
| 1432 | p_nest->index_end - p_nest->index_start + 1 + 3; | ||
| 1433 | } | ||
| 1434 | for (i = 0; i < node->n_child; i++) { | ||
| 1435 | nest_offset = | ||
| 1436 | create_seq(offset, n_head, seq, &node->child[i], n_trie, trie); | ||
| 1437 | p_head = &(*seq)[last_head + i]; | ||
| 1438 | p_head->nest_offset = nest_offset; | ||
| 1439 | } | ||
| 1440 | return retval; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | static void node_free(struct trie_node *node) | ||
| 1444 | { | ||
| 1445 | int i; | ||
| 1446 | |||
| 1447 | for (i = 0; i < node->n_child; i++) | ||
| 1448 | node_free(&node->child[i]); | ||
| 1449 | tcc_free(node->child); | ||
| 1450 | } | ||
| 1451 | |||
| 1354 | static int triecmp(const void *_a, const void *_b, void *arg) | 1452 | static int triecmp(const void *_a, const void *_b, void *arg) |
| 1355 | { | 1453 | { |
| 1356 | struct trie *a = (struct trie *) _a; | 1454 | struct trie_info *a = (struct trie_info *) _a; |
| 1357 | struct trie *b = (struct trie *) _b; | 1455 | struct trie_info *b = (struct trie_info *) _b; |
| 1358 | 1456 | ||
| 1359 | return strcmp(a->name, b->name); | 1457 | return strcmp(a->name, b->name); |
| 1360 | } | 1458 | } |
| 1361 | 1459 | ||
| 1362 | static void export_trie(TCCState *s1, struct macho *mo) | 1460 | static void export_trie(TCCState *s1, struct macho *mo) |
| 1363 | { | 1461 | { |
| 1364 | int i, j, n, m, offset; | 1462 | int i, size, offset = 0, save_offset; |
| 1365 | uint8_t *ptr; | 1463 | uint8_t *ptr; |
| 1366 | int sym_index; | 1464 | int sym_index; |
| 1367 | int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); | 1465 | int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); |
| 1368 | int n_trie = 0; | 1466 | int n_trie = 0, n_head = 0; |
| 1369 | struct trie *trie = NULL; | 1467 | struct trie_info *trie = NULL, *p_trie; |
| 1468 | struct trie_node node, *p_node; | ||
| 1469 | struct trie_seq *seq = NULL; | ||
| 1370 | addr_t vm_addr = get_segment(mo, 1)->vmaddr; | 1470 | addr_t vm_addr = get_segment(mo, 1)->vmaddr; |
| 1371 | 1471 | ||
| 1372 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { | 1472 | for (sym_index = 1; sym_index < sym_end; ++sym_index) { |
| @@ -1383,59 +1483,59 @@ static void export_trie(TCCState *s1, struct macho *mo) · 10 unmodified lines | |||
| 1383 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) | 1483 | if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) |
| 1384 | flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; | 1484 | flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; |
| 1385 | dprintf ("%s %d %llx\n", name, flag, addr + vm_addr); | 1485 | dprintf ("%s %d %llx\n", name, flag, addr + vm_addr); |
| 1386 | trie = tcc_realloc(trie, (n_trie + 1) * sizeof(struct trie)); | 1486 | trie = tcc_realloc(trie, (n_trie + 1) * sizeof(struct trie_info)); |
| 1387 | trie[n_trie].name = name; | 1487 | trie[n_trie].name = name; |
| 1388 | trie[n_trie].flag = flag; | 1488 | trie[n_trie].flag = flag; |
| 1389 | trie[n_trie].addr = addr; | 1489 | trie[n_trie].addr = addr; |
| 1390 | trie[n_trie].offset_size = 1; | ||
| 1391 | trie[n_trie].str_size = strlen(name) + 1; | 1490 | trie[n_trie].str_size = strlen(name) + 1; |
| 1392 | trie[n_trie].term_size = uleb128_size(flag) + uleb128_size(addr); | 1491 | trie[n_trie].term_size = uleb128_size(flag) + uleb128_size(addr); |
| 1393 | trie[n_trie].term_offset = 0; | ||
| 1394 | n_trie++; | 1492 | n_trie++; |
| 1395 | } | 1493 | } |
| 1396 | } | 1494 | } |
| 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) { | 1495 | if (n_trie) { |
| 1403 | tcc_qsort(trie, n_trie, sizeof(struct trie), triecmp, NULL); | 1496 | tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL); |
| 1404 | offset = 1 + 1; | 1497 | memset(&node, 0, sizeof(node)); |
| 1405 | for (i = 0; i < n_trie; i++) | 1498 | create_trie(&node, 0, n_trie, 0, n_trie, trie); |
| 1406 | offset += trie[i].str_size + trie[i].offset_size; | 1499 | create_seq(&offset, &n_head, &seq, &node, n_trie, trie); |
| 1407 | for (i = 0; i < n_trie; i++) { | 1500 | save_offset = offset; |
| 1408 | n = uleb128_size(offset); | 1501 | for (i = 0; i < n_head; i++) { |
| 1409 | trie[i].term_offset = offset + n - 1; | 1502 | p_node = seq[i].node; |
| 1410 | trie[i].offset_size = n; | 1503 | if (p_node->n_child == 0) { |
| 1411 | offset += 1 + trie[i].term_size + 1 + n - 1; | 1504 | p_trie = &trie[p_node->start]; |
| 1412 | if (n > 1) | 1505 | seq[i].nest_offset = offset; |
| 1413 | for (j = i - 1; j >= 0; j--) { | 1506 | offset += 1 + p_trie->term_size + 1; |
| 1414 | trie[j].term_offset += n - 1; | 1507 | } |
| 1415 | m = uleb128_size(trie[j].term_offset); | 1508 | } |
| 1416 | if (m != trie[j].offset_size) { | 1509 | for (i = 0; i < n_head; i++) { |
| 1417 | n += m - trie[j].offset_size; | 1510 | p_node = seq[i].node; |
| 1418 | offset += m - trie[j].offset_size; | 1511 | p_trie = &trie[p_node->start]; |
| 1419 | trie[j].offset_size = m; | 1512 | if (seq[i].n_child >= 0) { |
| 1420 | } | 1513 | section_ptr_add(mo->exports, seq[i].offset - mo->exports->data_offset); |
| 1421 | } | 1514 | ptr = section_ptr_add(mo->exports, 2); |
| 1422 | } | 1515 | *ptr++ = 0; |
| 1423 | ptr = section_ptr_add(mo->exports, 2); | 1516 | *ptr = seq[i].n_child; |
| 1424 | *ptr++ = 0; | 1517 | } |
| 1425 | *ptr = n_trie; | 1518 | size = p_node->index_end - p_node->index_start; |
| 1426 | for (i = 0; i < n_trie; i++) { | 1519 | ptr = section_ptr_add(mo->exports, size + 1); |
| 1427 | ptr = section_ptr_add(mo->exports, trie[i].str_size); | 1520 | memcpy(ptr, &p_trie->name[p_node->index_start], size); |
| 1428 | memcpy(ptr, trie[i].name, trie[i].str_size); | 1521 | ptr[size] = 0; |
| 1429 | write_uleb128(mo->exports, trie[i].term_offset); | 1522 | write_uleb128(mo->exports, seq[i].nest_offset); |
| 1430 | } | 1523 | } |
| 1431 | for (i = 0; i < n_trie; i++) { | 1524 | section_ptr_add(mo->exports, save_offset - mo->exports->data_offset); |
| 1432 | write_uleb128(mo->exports, trie[i].term_size); | 1525 | for (i = 0; i < n_head; i++) { |
| 1433 | write_uleb128(mo->exports, trie[i].flag); | 1526 | p_node = seq[i].node; |
| 1434 | write_uleb128(mo->exports, trie[i].addr); | 1527 | if (p_node->n_child == 0) { |
| 1435 | ptr = section_ptr_add(mo->exports, 1); | 1528 | p_trie = &trie[p_node->start]; |
| 1436 | *ptr = 0; | 1529 | write_uleb128(mo->exports, p_trie->term_size); |
| 1437 | } | 1530 | write_uleb128(mo->exports, p_trie->flag); |
| 1438 | section_ptr_add(mo->exports, -mo->exports->data_offset & 7); | 1531 | write_uleb128(mo->exports, p_trie->addr); |
| 1532 | ptr = section_ptr_add(mo->exports, 1); | ||
| 1533 | *ptr = 0; | ||
| 1534 | } | ||
| 1535 | } | ||
| 1536 | section_ptr_add(mo->exports, -mo->exports->data_offset & 7); | ||
| 1537 | node_free(&node); | ||
| 1538 | tcc_free(seq); | ||
| 1439 | } | 1539 | } |
| 1440 | tcc_free(trie); | 1540 | tcc_free(trie); |
| 1441 | } | 1541 | } |