| @@ -744,7 +744,8 @@ static void check_relocs(TCCState *s1, struct macho *mo) · 743 unmodified lines |
| 744 | 744 | } |
| 745 | 745 | } |
| 746 | 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 | 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 | 945 | if (type == R_DATA_PTR) { |
| 945 | | − mo->s_rebase = |
| 946 | | − tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) * |
| 947 | | − sizeof(struct s_rebase)); |
| 948 | | − mo->s_rebase[mo->n_rebase].section = s->sh_info; |
| 949 | | − mo->s_rebase[mo->n_rebase].rel = *rel; |
| 950 | | − mo->n_rebase++; |
| 946 | + if (sym->st_shndx == SHN_UNDEF) { |
| 947 | + mo->bind = tcc_realloc(mo->bind, |
| 948 | + (mo->n_bind + 1) * |
| 949 | + sizeof(struct bind)); |
| 950 | + mo->bind[mo->n_bind].section = s->sh_info; |
| 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 | 1289 | *ptr = BIND_OPCODE_DONE; |
| 1279 | 1290 | } |
| 1280 | 1291 | for (i = 0; i < mo->n_rebase; i++) { |
| 1281 | | − int sym_index = ELFW(R_SYM)(mo->s_rebase[i].rel.r_info); |
| 1282 | 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 | 1294 | ptr = section_ptr_add(mo->rebase, 2); |
| 1287 | 1295 | *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER; |
| 1288 | 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 | 1424 | struct trie_node *node, |
| 1417 | 1425 | int n_trie, struct trie_info *trie) |
| 1418 | 1426 | { |
| 1419 | | − int i, nest_offset, last_head = *n_head, retval = *offset; |
| 1420 | | − struct trie_seq *p_head; |
| 1427 | + int i, nest_offset, last_seq = *n_seq, retval = *offset; |
| 1428 | + struct trie_seq *p_seq; |
| 1421 | 1429 | struct trie_node *p_nest; |
| 1422 | 1430 | |
| 1423 | 1431 | for (i = 0; i < node->n_child; i++) { |
| 1424 | 1432 | 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; |
| 1433 | + *seq = tcc_realloc(*seq, (*n_seq + 1) * sizeof(struct trie_seq)); |
| 1434 | + p_seq = &(*seq)[(*n_seq)++]; |
| 1435 | + p_seq->n_child = i == 0 ? node->n_child : -1; |
| 1436 | + p_seq->node = p_nest; |
| 1437 | + p_seq->offset = *offset; |
| 1438 | + p_seq->nest_offset = 0; |
| 1431 | 1439 | *offset += (i == 0 ? 1 + 1 : 0) + |
| 1432 | 1440 | p_nest->index_end - p_nest->index_start + 1 + 3; |
| 1433 | 1441 | } |
| 1434 | 1442 | for (i = 0; i < node->n_child; i++) { |
| 1435 | 1443 | 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; |
| 1444 | + create_seq(offset, n_seq, seq, &node->child[i], n_trie, trie); |
| 1445 | + p_seq = &(*seq)[last_seq + i]; |
| 1446 | + p_seq->nest_offset = nest_offset; |
| 1439 | 1447 | } |
| 1440 | 1448 | return retval; |
| 1441 | 1449 | } |
| @@ -1463,7 +1471,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 21 unmodified lines |
| 1463 | 1471 | uint8_t *ptr; |
| 1464 | 1472 | int sym_index; |
| 1465 | 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 | 1475 | struct trie_info *trie = NULL, *p_trie; |
| 1468 | 1476 | struct trie_node node, *p_node; |
| 1469 | 1477 | struct trie_seq *seq = NULL; |
| @@ -1496,9 +1504,9 @@ static void export_trie(TCCState *s1, struct macho *mo) · 26 unmodified lines |
| 1496 | 1504 | tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL); |
| 1497 | 1505 | memset(&node, 0, sizeof(node)); |
| 1498 | 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 | 1508 | save_offset = offset; |
| 1501 | | − for (i = 0; i < n_head; i++) { |
| 1509 | + for (i = 0; i < n_seq; i++) { |
| 1502 | 1510 | p_node = seq[i].node; |
| 1503 | 1511 | if (p_node->n_child == 0) { |
| 1504 | 1512 | p_trie = &trie[p_node->start]; |
| @@ -1506,11 +1514,12 @@ static void export_trie(TCCState *s1, struct macho *mo) · 1 unmodified line |
| 1506 | 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 | 1518 | p_node = seq[i].node; |
| 1511 | 1519 | p_trie = &trie[p_node->start]; |
| 1512 | 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 | 1523 | ptr = section_ptr_add(mo->exports, 2); |
| 1515 | 1524 | *ptr++ = 0; |
| 1516 | 1525 | *ptr = seq[i].n_child; |
| @@ -1522,7 +1531,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 5 unmodified lines |
| 1522 | 1531 | write_uleb128(mo->exports, seq[i].nest_offset); |
| 1523 | 1532 | } |
| 1524 | 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 | 1535 | p_node = seq[i].node; |
| 1527 | 1536 | if (p_node->n_child == 0) { |
| 1528 | 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 | 1919 | int i, j, k, bind_index, size, page_count, sym_index; |
| 1911 | 1920 | const char *name; |
| 1912 | | − ElfW_Rel rel; |
| 1913 | 1921 | ElfW(Sym) *sym; |
| 1914 | 1922 | unsigned char *data = mo->chained_fixups->data; |
| 1915 | 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 | 1939 | mo->bind_rebase[i + 1].bind ? "bind" : "rebase", |
| 1932 | 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 | 1953 | header = (struct dyld_chained_fixups_header *) data; |
| 1935 | 1954 | data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8; |
| 1936 | 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 | 1985 | segment->max_valid_pointer = 0; |
| 1967 | 1986 | segment->page_count = page_count; |
| 1968 | 1987 | // add bind/rebase |
| 1988 | + bind_index = 0; |
| 1989 | + k = 0; |
| 1969 | 1990 | for (j = 0; j < page_count; j++) { |
| 1970 | | − uint64_t start = seg->vmaddr + j * SEG_PAGE_SIZE; |
| 1971 | | − uint64_t end = start + SEG_PAGE_SIZE; |
| 1991 | + addr_t start = seg->vmaddr + j * SEG_PAGE_SIZE; |
| 1992 | + addr_t end = start + SEG_PAGE_SIZE; |
| 1972 | 1993 | void *last; |
| 1973 | 1994 | addr_t last_o = 0; |
| 1974 | | − uint64_t cur_o, cur; |
| 1995 | + addr_t cur_o, cur; |
| 1975 | 1996 | struct dyld_chained_ptr_64_rebase *rebase; |
| 1976 | 1997 | struct dyld_chained_ptr_64_bind *bind; |
| 1977 | | − Section *s; |
| 1978 | 1998 | |
| 1979 | 1999 | segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE; |
| 1980 | | − for (k = 0, bind_index = 0; k < mo->n_bind_rebase; k++) { |
| 1981 | | − uint64_t addr; |
| 1982 | | − |
| 1983 | | − s = s1->sections[mo->bind_rebase[k].section]; |
| 1984 | | − rel = mo->bind_rebase[k].rel; |
| 1985 | | − if ((rel.r_offset & 3) || |
| 1986 | | − (rel.r_offset & (SEG_PAGE_SIZE - 1)) > |
| 1987 | | − SEG_PAGE_SIZE - PTR_SIZE) |
| 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) { |
| 2000 | + for (; k < mo->n_bind_rebase; k++) { |
| 2001 | + Section *s = s1->sections[mo->bind_rebase[k].section]; |
| 2002 | + addr_t r_offset = mo->bind_rebase[k].rel.r_offset; |
| 2003 | + addr_t addr = s->sh_addr + r_offset; |
| 2004 | + |
| 2005 | + if (addr >= end) |
| 2006 | + break; |
| 2007 | + if (addr >= start) { |
| 1992 | 2008 | cur_o = addr - start; |
| 1993 | 2009 | if (mo->bind_rebase[k].bind) { |
| 1994 | 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 | 2014 | bind->next = (cur_o - last_o) / 4; |
| 1999 | 2015 | } |
| 2000 | 2016 | bind = (struct dyld_chained_ptr_64_bind *) |
| 2001 | | − (s->data + rel.r_offset); |
| 2017 | + (s->data + r_offset); |
| 2002 | 2018 | last = bind; |
| 2003 | 2019 | last_o = cur_o; |
| 2004 | 2020 | bind->ordinal = bind_index; |
| @@ -2015,10 +2031,10 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 10 unmodified lines |
| 2015 | 2031 | rebase->next = (cur_o - last_o) / 4; |
| 2016 | 2032 | } |
| 2017 | 2033 | rebase = (struct dyld_chained_ptr_64_rebase *) |
| 2018 | | − (s->data + rel.r_offset); |
| 2034 | + (s->data + r_offset); |
| 2019 | 2035 | last = rebase; |
| 2020 | 2036 | last_o = cur_o; |
| 2021 | | − cur = (*(uint64_t *) (s->data + rel.r_offset)) - |
| 2037 | + cur = (*(uint64_t *) (s->data + r_offset)) - |
| 2022 | 2038 | PTR_64_OFFSET; |
| 2023 | 2039 | rebase->target = cur & PTR_64_MASK; |
| 2024 | 2040 | rebase->high8 = cur >> (64 - 8); |