| @@ -744,7 +744,8 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 743 unmodified lines |
| 744 | } | 744 | } |
| 745 | } | 745 | } |
| 746 | if (type == R_DATA_PTR) | 746 | if (type == R_DATA_PTR) |
| 747 | bind_rebase_add(mo, 0, s->sh_info, rel, NULL); | 747 | bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0, |
| | 748 | s->sh_info, rel, NULL); |
| 748 | } | 749 | } |
| 749 | } | 750 | } |
| 750 | pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); | 751 | pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi)); |
| @@ -942,12 +943,22 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 191 unmodified lines |
| 942 | } | 943 | } |
| 943 | } | 944 | } |
| 944 | if (type == R_DATA_PTR) { | 945 | if (type == R_DATA_PTR) { |
| 945 | mo->s_rebase = | 946 | if (sym->st_shndx == SHN_UNDEF) { |
| 946 | tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * | 947 | mo->bind = tcc_realloc(mo->bind, |
| 947 | sizeof(struct s_rebase)); | 948 | (mo->n_bind + 1) * |
| 948 | mo->s_rebase[mo->n_rebase].section = s->sh_info; | 949 | sizeof(struct bind)); |
| 949 | mo->s_rebase[mo->n_rebase].rel = *rel; | 950 | mo->bind[mo->n_bind].section = s->sh_info; |
| 950 | mo->n_rebase++; | 951 | mo->bind[mo->n_bind].rel = *rel; |
| | 952 | mo->n_bind++; |
| | 953 | } |
| | 954 | else { |
| | 955 | mo->s_rebase = |
| | 956 | tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * |
| | 957 | sizeof(struct s_rebase)); |
| | 958 | mo->s_rebase[mo->n_rebase].section = s->sh_info; |
| | 959 | mo->s_rebase[mo->n_rebase].rel = *rel; |
| | 960 | mo->n_rebase++; |
| | 961 | } |
| 951 | } | 962 | } |
| 952 | } | 963 | } |
| 953 | } | 964 | } |
| @@ -1278,11 +1289,8 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 324 unmodified lines |
| 1278 | *ptr = BIND_OPCODE_DONE; | 1289 | *ptr = BIND_OPCODE_DONE; |
| 1279 | } | 1290 | } |
| 1280 | for (i = 0; i < mo->n_rebase; i++) { | 1291 | for (i = 0; i < mo->n_rebase; i++) { |
| 1281 | int sym_index = ELFW(R_SYM)(mo->s_rebase[i].rel.r_info); | | |
| 1282 | Section *s = s1->sections[mo->s_rebase[i].section]; | 1292 | Section *s = s1->sections[mo->s_rebase[i].section]; |
| 1283 | | 1293 | |
| 1284 | sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | | |
| 1285 | name = (char *) symtab_section->link->data + sym->st_name; | | |
| 1286 | ptr = section_ptr_add(mo->rebase, 2); | 1294 | ptr = section_ptr_add(mo->rebase, 2); |
| 1287 | *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; | 1295 | *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; |
| 1288 | set_segment_and_offset(mo, s->sh_addr, ptr, | 1296 | set_segment_and_offset(mo, s->sh_addr, ptr, |
| @@ -1412,30 +1420,30 @@ static void create_trie(struct trie_node *node, · 123 unmodified lines |
| 1412 | } | 1420 | } |
| 1413 | } | 1421 | } |
| 1414 | | 1422 | |
| 1415 | static int create_seq(int *offset, int *n_head, struct trie_seq **seq, | 1423 | static int create_seq(int *offset, int *n_seq, struct trie_seq **seq, |
| 1416 | struct trie_node *node, | 1424 | struct trie_node *node, |
| 1417 | int n_trie, struct trie_info *trie) | 1425 | int n_trie, struct trie_info *trie) |
| 1418 | { | 1426 | { |
| 1419 | int i, nest_offset, last_head = *n_head, retval = *offset; | 1427 | int i, nest_offset, last_seq = *n_seq, retval = *offset; |
| 1420 | struct trie_seq *p_head; | 1428 | struct trie_seq *p_seq; |
| 1421 | struct trie_node *p_nest; | 1429 | struct trie_node *p_nest; |
| 1422 | | 1430 | |
| 1423 | for (i = 0; i < node->n_child; i++) { | 1431 | for (i = 0; i < node->n_child; i++) { |
| 1424 | p_nest = &node->child[i]; | 1432 | p_nest = &node->child[i]; |
| 1425 | *seq = tcc_realloc(*seq, (*n_head + 1) * sizeof(struct trie_seq)); | 1433 | *seq = tcc_realloc(*seq, (*n_seq + 1) * sizeof(struct trie_seq)); |
| 1426 | p_head = &(*seq)[(*n_head)++]; | 1434 | p_seq = &(*seq)[(*n_seq)++]; |
| 1427 | p_head->n_child = i == 0 ? node->n_child : -1; | 1435 | p_seq->n_child = i == 0 ? node->n_child : -1; |
| 1428 | p_head->node = p_nest; | 1436 | p_seq->node = p_nest; |
| 1429 | p_head->offset = *offset; | 1437 | p_seq->offset = *offset; |
| 1430 | p_head->nest_offset = 0; | 1438 | p_seq->nest_offset = 0; |
| 1431 | *offset += (i == 0 ? 1 + 1 : 0) + | 1439 | *offset += (i == 0 ? 1 + 1 : 0) + |
| 1432 | p_nest->index_end - p_nest->index_start + 1 + 3; | 1440 | p_nest->index_end - p_nest->index_start + 1 + 3; |
| 1433 | } | 1441 | } |
| 1434 | for (i = 0; i < node->n_child; i++) { | 1442 | for (i = 0; i < node->n_child; i++) { |
| 1435 | nest_offset = | 1443 | nest_offset = |
| 1436 | create_seq(offset, n_head, seq, &node->child[i], n_trie, trie); | 1444 | create_seq(offset, n_seq, seq, &node->child[i], n_trie, trie); |
| 1437 | p_head = &(*seq)[last_head + i]; | 1445 | p_seq = &(*seq)[last_seq + i]; |
| 1438 | p_head->nest_offset = nest_offset; | 1446 | p_seq->nest_offset = nest_offset; |
| 1439 | } | 1447 | } |
| 1440 | return retval; | 1448 | return retval; |
| 1441 | } | 1449 | } |
| @@ -1463,7 +1471,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 21 unmodified lines |
| 1463 | uint8_t *ptr; | 1471 | uint8_t *ptr; |
| 1464 | int sym_index; | 1472 | int sym_index; |
| 1465 | int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); | 1473 | int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym)); |
| 1466 | int n_trie = 0, n_head = 0; | 1474 | int n_trie = 0, n_seq = 0; |
| 1467 | struct trie_info *trie = NULL, *p_trie; | 1475 | struct trie_info *trie = NULL, *p_trie; |
| 1468 | struct trie_node node, *p_node; | 1476 | struct trie_node node, *p_node; |
| 1469 | struct trie_seq *seq = NULL; | 1477 | struct trie_seq *seq = NULL; |
| @@ -1496,9 +1504,9 @@ static void export_trie(TCCState *s1, struct macho *mo) · 26 unmodified lines |
| 1496 | tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL); | 1504 | tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL); |
| 1497 | memset(&node, 0, sizeof(node)); | 1505 | memset(&node, 0, sizeof(node)); |
| 1498 | create_trie(&node, 0, n_trie, 0, n_trie, trie); | 1506 | create_trie(&node, 0, n_trie, 0, n_trie, trie); |
| 1499 | create_seq(&offset, &n_head, &seq, &node, n_trie, trie); | 1507 | create_seq(&offset, &n_seq, &seq, &node, n_trie, trie); |
| 1500 | save_offset = offset; | 1508 | save_offset = offset; |
| 1501 | for (i = 0; i < n_head; i++) { | 1509 | for (i = 0; i < n_seq; i++) { |
| 1502 | p_node = seq[i].node; | 1510 | p_node = seq[i].node; |
| 1503 | if (p_node->n_child == 0) { | 1511 | if (p_node->n_child == 0) { |
| 1504 | p_trie = &trie[p_node->start]; | 1512 | p_trie = &trie[p_node->start]; |
| @@ -1506,11 +1514,12 @@ static void export_trie(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 1506 | offset += 1 + p_trie->term_size + 1; | 1514 | offset += 1 + p_trie->term_size + 1; |
| 1507 | } | 1515 | } |
| 1508 | } | 1516 | } |
| 1509 | for (i = 0; i < n_head; i++) { | 1517 | for (i = 0; i < n_seq; i++) { |
| 1510 | p_node = seq[i].node; | 1518 | p_node = seq[i].node; |
| 1511 | p_trie = &trie[p_node->start]; | 1519 | p_trie = &trie[p_node->start]; |
| 1512 | if (seq[i].n_child >= 0) { | 1520 | if (seq[i].n_child >= 0) { |
| 1513 | section_ptr_add(mo->exports, seq[i].offset - mo->exports->data_offset); | 1521 | section_ptr_add(mo->exports, |
| | 1522 | seq[i].offset - mo->exports->data_offset); |
| 1514 | ptr = section_ptr_add(mo->exports, 2); | 1523 | ptr = section_ptr_add(mo->exports, 2); |
| 1515 | *ptr++ = 0; | 1524 | *ptr++ = 0; |
| 1516 | *ptr = seq[i].n_child; | 1525 | *ptr = seq[i].n_child; |
| @@ -1522,7 +1531,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 5 unmodified lines |
| 1522 | write_uleb128(mo->exports, seq[i].nest_offset); | 1531 | write_uleb128(mo->exports, seq[i].nest_offset); |
| 1523 | } | 1532 | } |
| 1524 | section_ptr_add(mo->exports, save_offset - mo->exports->data_offset); | 1533 | section_ptr_add(mo->exports, save_offset - mo->exports->data_offset); |
| 1525 | for (i = 0; i < n_head; i++) { | 1534 | for (i = 0; i < n_seq; i++) { |
| 1526 | p_node = seq[i].node; | 1535 | p_node = seq[i].node; |
| 1527 | if (p_node->n_child == 0) { | 1536 | if (p_node->n_child == 0) { |
| 1528 | p_trie = &trie[p_node->start]; | 1537 | p_trie = &trie[p_node->start]; |
| @@ -1909,7 +1918,6 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 380 unmodified lines |
| 1909 | { | 1918 | { |
| 1910 | int i, j, k, bind_index, size, page_count, sym_index; | 1919 | int i, j, k, bind_index, size, page_count, sym_index; |
| 1911 | const char *name; | 1920 | const char *name; |
| 1912 | ElfW_Rel rel; | | |
| 1913 | ElfW(Sym) *sym; | 1921 | ElfW(Sym) *sym; |
| 1914 | unsigned char *data = mo->chained_fixups->data; | 1922 | unsigned char *data = mo->chained_fixups->data; |
| 1915 | struct segment_command_64 *seg; | 1923 | struct segment_command_64 *seg; |
| @@ -1931,6 +1939,17 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 15 unmodified lines |
| 1931 | mo->bind_rebase[i + 1].bind ? "bind" : "rebase", | 1939 | mo->bind_rebase[i + 1].bind ? "bind" : "rebase", |
| 1932 | s1->sections[mo->bind_rebase[i].section]->name, name); | 1940 | s1->sections[mo->bind_rebase[i].section]->name, name); |
| 1933 | } | 1941 | } |
| | 1942 | for (i = 0; i < mo->n_bind_rebase; i++) { |
| | 1943 | addr_t r_offset = mo->bind_rebase[i].rel.r_offset; |
| | 1944 | if ((r_offset & 3) || |
| | 1945 | (r_offset & (SEG_PAGE_SIZE - 1)) > |
| | 1946 | SEG_PAGE_SIZE - PTR_SIZE) { |
| | 1947 | Section *s = s1->sections[mo->bind_rebase[i].section]; |
| | 1948 | |
| | 1949 | tcc_error("Illegal rel_offset %s %lld", |
| | 1950 | s->name, (long long)r_offset); |
| | 1951 | } |
| | 1952 | } |
| 1934 | header = (struct dyld_chained_fixups_header *) data; | 1953 | header = (struct dyld_chained_fixups_header *) data; |
| 1935 | data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8; | 1954 | data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8; |
| 1936 | header->starts_offset = data - mo->chained_fixups->data; | 1955 | header->starts_offset = data - mo->chained_fixups->data; |
| @@ -1966,29 +1985,26 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 29 unmodified lines |
| 1966 | segment->max_valid_pointer = 0; | 1985 | segment->max_valid_pointer = 0; |
| 1967 | segment->page_count = page_count; | 1986 | segment->page_count = page_count; |
| 1968 | // add bind/rebase | 1987 | // add bind/rebase |
| | 1988 | bind_index = 0; |
| | 1989 | k = 0; |
| 1969 | for (j = 0; j < page_count; j++) { | 1990 | for (j = 0; j < page_count; j++) { |
| 1970 | uint64_t start = seg->vmaddr + j * SEG_PAGE_SIZE; | 1991 | addr_t start = seg->vmaddr + j * SEG_PAGE_SIZE; |
| 1971 | uint64_t end = start + SEG_PAGE_SIZE; | 1992 | addr_t end = start + SEG_PAGE_SIZE; |
| 1972 | void *last; | 1993 | void *last; |
| 1973 | addr_t last_o = 0; | 1994 | addr_t last_o = 0; |
| 1974 | uint64_t cur_o, cur; | 1995 | addr_t cur_o, cur; |
| 1975 | struct dyld_chained_ptr_64_rebase *rebase; | 1996 | struct dyld_chained_ptr_64_rebase *rebase; |
| 1976 | struct dyld_chained_ptr_64_bind *bind; | 1997 | struct dyld_chained_ptr_64_bind *bind; |
| 1977 | Section *s; | | |
| 1978 | | 1998 | |
| 1979 | segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE; | 1999 | segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE; |
| 1980 | for (k = 0, bind_index = 0; k < mo->n_bind_rebase; k++) { | 2000 | for (; k < mo->n_bind_rebase; k++) { |
| 1981 | uint64_t addr; | 2001 | Section *s = s1->sections[mo->bind_rebase[k].section]; |
| 1982 | | 2002 | addr_t r_offset = mo->bind_rebase[k].rel.r_offset; |
| 1983 | s = s1->sections[mo->bind_rebase[k].section]; | 2003 | addr_t addr = s->sh_addr + r_offset; |
| 1984 | rel = mo->bind_rebase[k].rel; | 2004 | |
| 1985 | if ((rel.r_offset & 3) || | 2005 | if (addr >= end) |
| 1986 | (rel.r_offset & (SEG_PAGE_SIZE - 1)) > | 2006 | break; |
| 1987 | SEG_PAGE_SIZE - PTR_SIZE) | 2007 | if (addr >= start) { |
| 1988 | tcc_error("Illegal rel_offset %s %lld", | | |
| 1989 | s->name, (long long)rel.r_offset); | | |
| 1990 | addr = s->sh_addr + rel.r_offset; | | |
| 1991 | if (addr >= start && addr < end) { | | |
| 1992 | cur_o = addr - start; | 2008 | cur_o = addr - start; |
| 1993 | if (mo->bind_rebase[k].bind) { | 2009 | if (mo->bind_rebase[k].bind) { |
| 1994 | if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE) | 2010 | if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE) |
| @@ -1998,7 +2014,7 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 3 unmodified lines |
| 1998 | bind->next = (cur_o - last_o) / 4; | 2014 | bind->next = (cur_o - last_o) / 4; |
| 1999 | } | 2015 | } |
| 2000 | bind = (struct dyld_chained_ptr_64_bind *) | 2016 | bind = (struct dyld_chained_ptr_64_bind *) |
| 2001 | (s->data + rel.r_offset); | 2017 | (s->data + r_offset); |
| 2002 | last = bind; | 2018 | last = bind; |
| 2003 | last_o = cur_o; | 2019 | last_o = cur_o; |
| 2004 | bind->ordinal = bind_index; | 2020 | bind->ordinal = bind_index; |
| @@ -2015,10 +2031,10 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 10 unmodified lines |
| 2015 | rebase->next = (cur_o - last_o) / 4; | 2031 | rebase->next = (cur_o - last_o) / 4; |
| 2016 | } | 2032 | } |
| 2017 | rebase = (struct dyld_chained_ptr_64_rebase *) | 2033 | rebase = (struct dyld_chained_ptr_64_rebase *) |
| 2018 | (s->data + rel.r_offset); | 2034 | (s->data + r_offset); |
| 2019 | last = rebase; | 2035 | last = rebase; |
| 2020 | last_o = cur_o; | 2036 | last_o = cur_o; |
| 2021 | cur = (*(uint64_t *) (s->data + rel.r_offset)) - | 2037 | cur = (*(uint64_t *) (s->data + r_offset)) - |
| 2022 | PTR_64_OFFSET; | 2038 | PTR_64_OFFSET; |
| 2023 | rebase->target = cur & PTR_64_MASK; | 2039 | rebase->target = cur & PTR_64_MASK; |
| 2024 | rebase->high8 = cur >> (64 - 8); | 2040 | rebase->high8 = cur >> (64 - 8); |