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
744744 }
745745 }
746746 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);
748749 }
749750 }
750751 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
942943 }
943944 }
944945 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+ }
951962 }
952963 }
953964 }
@@ -1278,11 +1289,8 @@ static void bind_rebase(TCCState *s1, struct macho *mo) · 324 unmodified lines
12781289 *ptr = BIND_OPCODE_DONE;
12791290 }
12801291 for (i = 0; i < mo->n_rebase; i++) {
1281− int sym_index = ELFW(R_SYM)(mo->s_rebase[i].rel.r_info);
12821292 Section *s = s1->sections[mo->s_rebase[i].section];
12831293
1284− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1285− name = (char *) symtab_section->link->data + sym->st_name;
12861294 ptr = section_ptr_add(mo->rebase, 2);
12871295 *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
12881296 set_segment_and_offset(mo, s->sh_addr, ptr,
@@ -1412,30 +1420,30 @@ static void create_trie(struct trie_node *node, · 123 unmodified lines
14121420 }
14131421 }
14141422
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,
14161424 struct trie_node *node,
14171425 int n_trie, struct trie_info *trie)
14181426 {
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;
14211429 struct trie_node *p_nest;
14221430
14231431 for (i = 0; i < node->n_child; i++) {
14241432 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;
14311439 *offset += (i == 0 ? 1 + 1 : 0) +
14321440 p_nest->index_end - p_nest->index_start + 1 + 3;
14331441 }
14341442 for (i = 0; i < node->n_child; i++) {
14351443 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;
14391447 }
14401448 return retval;
14411449 }
@@ -1463,7 +1471,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 21 unmodified lines
14631471 uint8_t *ptr;
14641472 int sym_index;
14651473 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;
14671475 struct trie_info *trie = NULL, *p_trie;
14681476 struct trie_node node, *p_node;
14691477 struct trie_seq *seq = NULL;
@@ -1496,9 +1504,9 @@ static void export_trie(TCCState *s1, struct macho *mo) · 26 unmodified lines
14961504 tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL);
14971505 memset(&node, 0, sizeof(node));
14981506 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);
15001508 save_offset = offset;
1501− for (i = 0; i < n_head; i++) {
1509+ for (i = 0; i < n_seq; i++) {
15021510 p_node = seq[i].node;
15031511 if (p_node->n_child == 0) {
15041512 p_trie = &trie[p_node->start];
@@ -1506,11 +1514,12 @@ static void export_trie(TCCState *s1, struct macho *mo) · 1 unmodified line
15061514 offset += 1 + p_trie->term_size + 1;
15071515 }
15081516 }
1509− for (i = 0; i < n_head; i++) {
1517+ for (i = 0; i < n_seq; i++) {
15101518 p_node = seq[i].node;
15111519 p_trie = &trie[p_node->start];
15121520 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);
15141523 ptr = section_ptr_add(mo->exports, 2);
15151524 *ptr++ = 0;
15161525 *ptr = seq[i].n_child;
@@ -1522,7 +1531,7 @@ static void export_trie(TCCState *s1, struct macho *mo) · 5 unmodified lines
15221531 write_uleb128(mo->exports, seq[i].nest_offset);
15231532 }
15241533 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++) {
15261535 p_node = seq[i].node;
15271536 if (p_node->n_child == 0) {
15281537 p_trie = &trie[p_node->start];
@@ -1909,7 +1918,6 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 380 unmodified lines
19091918 {
19101919 int i, j, k, bind_index, size, page_count, sym_index;
19111920 const char *name;
1912− ElfW_Rel rel;
19131921 ElfW(Sym) *sym;
19141922 unsigned char *data = mo->chained_fixups->data;
19151923 struct segment_command_64 *seg;
@@ -1931,6 +1939,17 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 15 unmodified lines
19311939 mo->bind_rebase[i + 1].bind ? "bind" : "rebase",
19321940 s1->sections[mo->bind_rebase[i].section]->name, name);
19331941 }
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+ }
19341953 header = (struct dyld_chained_fixups_header *) data;
19351954 data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
19361955 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
19661985 segment->max_valid_pointer = 0;
19671986 segment->page_count = page_count;
19681987 // add bind/rebase
1988+ bind_index = 0;
1989+ k = 0;
19691990 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;
19721993 void *last;
19731994 addr_t last_o = 0;
1974− uint64_t cur_o, cur;
1995+ addr_t cur_o, cur;
19751996 struct dyld_chained_ptr_64_rebase *rebase;
19761997 struct dyld_chained_ptr_64_bind *bind;
1977− Section *s;
19781998
19791999 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) {
19922008 cur_o = addr - start;
19932009 if (mo->bind_rebase[k].bind) {
19942010 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
19982014 bind->next = (cur_o - last_o) / 4;
19992015 }
20002016 bind = (struct dyld_chained_ptr_64_bind *)
2001− (s->data + rel.r_offset);
2017+ (s->data + r_offset);
20022018 last = bind;
20032019 last_o = cur_o;
20042020 bind->ordinal = bind_index;
@@ -2015,10 +2031,10 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo) · 10 unmodified lines
20152031 rebase->next = (cur_o - last_o) / 4;
20162032 }
20172033 rebase = (struct dyld_chained_ptr_64_rebase *)
2018− (s->data + rel.r_offset);
2034+ (s->data + r_offset);
20192035 last = rebase;
20202036 last_o = cur_o;
2021− cur = (*(uint64_t *) (s->data + rel.r_offset)) -
2037+ cur = (*(uint64_t *) (s->data + r_offset)) -
20222038 PTR_64_OFFSET;
20232039 rebase->target = cur & PTR_64_MASK;
20242040 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
126126 #endif
127127 }
128128
129+struct {
130+ int (*print)(const char *format, ...);
131+} tst_indir = {
132+ printf
133+};
134+
135+void tst_indir_func(void)
136+{
137+ tst_indir.print("tst_indir_func %d\n", 10);
138+}
139+
129140 int
130141 main (void)
131142 {
@@ -144,4 +155,5 @@ main (void) · 12 unmodified lines
144155 tst_pack();
145156 tst_cast();
146157 tst_strtoll_strtoull();
158+ tst_indir_func();
147159 }
tests/tests2/119_random_stuff.expect+1−0
@@ -3,3 +3,4 @@ tst_adr 5 · 2 unmodified lines
33 tst_compare: ok
44 tst_pack: j.f = 5, i.f = 5
55 schar to ushort cast: ffff0033
6+tst_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