History

New update tccmacho.c

Fix for external functions as pointers in data section. See testcase 119 and tccmacho.c in check_relocs. Make bind/rebase code faster in bind_rebase_import. - Move reloc check out of loop - Because relocs are sorted we can do bind/rebase by page. Change name head into seq in trie code. Remove unused code in bind_rebase.

herman ten brugge committed 3 years ago

Commit 747ad401 parent 6b9fb933 files · +77 −48Browse files

Unified · Split

3 files
  1. tccmacho.c +64 −48
  2. tests/tests2/119_random_stuff.c +12 −0
  3. tests/tests2/119_random_stuff.expect +1 −0
tccmacho.c+64−48
@@ -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
1415static int create_seq(int *offset, int *n_head, struct trie_seq **seq,1423static 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/rebase1987 // 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);
tests/tests2/119_random_stuff.c+12−0
@@ -126,6 +126,17 @@ void tst_strtoll_strtoull(void) · 125 unmodified lines
126#endif126#endif
127}127}
128 128
129struct {
130 int (*print)(const char *format, ...);
131} tst_indir = {
132 printf
133};
134
135void tst_indir_func(void)
136{
137 tst_indir.print("tst_indir_func %d\n", 10);
138}
139
129int140int
130main (void)141main (void)
131{142{
@@ -144,4 +155,5 @@ main (void) · 12 unmodified lines
144 tst_pack();155 tst_pack();
145 tst_cast();156 tst_cast();
146 tst_strtoll_strtoull();157 tst_strtoll_strtoull();
158 tst_indir_func();
147}159}
tests/tests2/119_random_stuff.expect+1−0
@@ -3,3 +3,4 @@ tst_adr 5 · 2 unmodified lines
3tst_compare: ok3tst_compare: ok
4tst_pack: j.f = 5, i.f = 54tst_pack: j.f = 5, i.f = 5
5schar to ushort cast: ffff00335schar to ushort cast: ffff0033
6tst_indir_func 10

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