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.
This commit is contained in:
parent
6b9fb93cd1
commit
747ad409ac
3 changed files with 76 additions and 47 deletions
110
tccmacho.c
110
tccmacho.c
|
@ -744,7 +744,8 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||
}
|
||||
}
|
||||
if (type == R_DATA_PTR)
|
||||
bind_rebase_add(mo, 0, s->sh_info, rel, NULL);
|
||||
bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0,
|
||||
s->sh_info, rel, NULL);
|
||||
}
|
||||
}
|
||||
pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
|
||||
|
@ -942,12 +943,22 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||
}
|
||||
}
|
||||
if (type == R_DATA_PTR) {
|
||||
mo->s_rebase =
|
||||
tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
|
||||
sizeof(struct s_rebase));
|
||||
mo->s_rebase[mo->n_rebase].section = s->sh_info;
|
||||
mo->s_rebase[mo->n_rebase].rel = *rel;
|
||||
mo->n_rebase++;
|
||||
if (sym->st_shndx == SHN_UNDEF) {
|
||||
mo->bind = tcc_realloc(mo->bind,
|
||||
(mo->n_bind + 1) *
|
||||
sizeof(struct bind));
|
||||
mo->bind[mo->n_bind].section = s->sh_info;
|
||||
mo->bind[mo->n_bind].rel = *rel;
|
||||
mo->n_bind++;
|
||||
}
|
||||
else {
|
||||
mo->s_rebase =
|
||||
tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
|
||||
sizeof(struct s_rebase));
|
||||
mo->s_rebase[mo->n_rebase].section = s->sh_info;
|
||||
mo->s_rebase[mo->n_rebase].rel = *rel;
|
||||
mo->n_rebase++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1278,11 +1289,8 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
|||
*ptr = BIND_OPCODE_DONE;
|
||||
}
|
||||
for (i = 0; i < mo->n_rebase; i++) {
|
||||
int sym_index = ELFW(R_SYM)(mo->s_rebase[i].rel.r_info);
|
||||
Section *s = s1->sections[mo->s_rebase[i].section];
|
||||
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
name = (char *) symtab_section->link->data + sym->st_name;
|
||||
ptr = section_ptr_add(mo->rebase, 2);
|
||||
*ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
|
||||
set_segment_and_offset(mo, s->sh_addr, ptr,
|
||||
|
@ -1412,30 +1420,30 @@ static void create_trie(struct trie_node *node,
|
|||
}
|
||||
}
|
||||
|
||||
static int create_seq(int *offset, int *n_head, struct trie_seq **seq,
|
||||
static int create_seq(int *offset, int *n_seq, struct trie_seq **seq,
|
||||
struct trie_node *node,
|
||||
int n_trie, struct trie_info *trie)
|
||||
{
|
||||
int i, nest_offset, last_head = *n_head, retval = *offset;
|
||||
struct trie_seq *p_head;
|
||||
int i, nest_offset, last_seq = *n_seq, retval = *offset;
|
||||
struct trie_seq *p_seq;
|
||||
struct trie_node *p_nest;
|
||||
|
||||
for (i = 0; i < node->n_child; i++) {
|
||||
p_nest = &node->child[i];
|
||||
*seq = tcc_realloc(*seq, (*n_head + 1) * sizeof(struct trie_seq));
|
||||
p_head = &(*seq)[(*n_head)++];
|
||||
p_head->n_child = i == 0 ? node->n_child : -1;
|
||||
p_head->node = p_nest;
|
||||
p_head->offset = *offset;
|
||||
p_head->nest_offset = 0;
|
||||
*seq = tcc_realloc(*seq, (*n_seq + 1) * sizeof(struct trie_seq));
|
||||
p_seq = &(*seq)[(*n_seq)++];
|
||||
p_seq->n_child = i == 0 ? node->n_child : -1;
|
||||
p_seq->node = p_nest;
|
||||
p_seq->offset = *offset;
|
||||
p_seq->nest_offset = 0;
|
||||
*offset += (i == 0 ? 1 + 1 : 0) +
|
||||
p_nest->index_end - p_nest->index_start + 1 + 3;
|
||||
}
|
||||
for (i = 0; i < node->n_child; i++) {
|
||||
nest_offset =
|
||||
create_seq(offset, n_head, seq, &node->child[i], n_trie, trie);
|
||||
p_head = &(*seq)[last_head + i];
|
||||
p_head->nest_offset = nest_offset;
|
||||
create_seq(offset, n_seq, seq, &node->child[i], n_trie, trie);
|
||||
p_seq = &(*seq)[last_seq + i];
|
||||
p_seq->nest_offset = nest_offset;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
@ -1463,7 +1471,7 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
|||
uint8_t *ptr;
|
||||
int sym_index;
|
||||
int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
|
||||
int n_trie = 0, n_head = 0;
|
||||
int n_trie = 0, n_seq = 0;
|
||||
struct trie_info *trie = NULL, *p_trie;
|
||||
struct trie_node node, *p_node;
|
||||
struct trie_seq *seq = NULL;
|
||||
|
@ -1496,9 +1504,9 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
|||
tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL);
|
||||
memset(&node, 0, sizeof(node));
|
||||
create_trie(&node, 0, n_trie, 0, n_trie, trie);
|
||||
create_seq(&offset, &n_head, &seq, &node, n_trie, trie);
|
||||
create_seq(&offset, &n_seq, &seq, &node, n_trie, trie);
|
||||
save_offset = offset;
|
||||
for (i = 0; i < n_head; i++) {
|
||||
for (i = 0; i < n_seq; i++) {
|
||||
p_node = seq[i].node;
|
||||
if (p_node->n_child == 0) {
|
||||
p_trie = &trie[p_node->start];
|
||||
|
@ -1506,11 +1514,12 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
|||
offset += 1 + p_trie->term_size + 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n_head; i++) {
|
||||
for (i = 0; i < n_seq; i++) {
|
||||
p_node = seq[i].node;
|
||||
p_trie = &trie[p_node->start];
|
||||
if (seq[i].n_child >= 0) {
|
||||
section_ptr_add(mo->exports, seq[i].offset - mo->exports->data_offset);
|
||||
section_ptr_add(mo->exports,
|
||||
seq[i].offset - mo->exports->data_offset);
|
||||
ptr = section_ptr_add(mo->exports, 2);
|
||||
*ptr++ = 0;
|
||||
*ptr = seq[i].n_child;
|
||||
|
@ -1522,7 +1531,7 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
|||
write_uleb128(mo->exports, seq[i].nest_offset);
|
||||
}
|
||||
section_ptr_add(mo->exports, save_offset - mo->exports->data_offset);
|
||||
for (i = 0; i < n_head; i++) {
|
||||
for (i = 0; i < n_seq; i++) {
|
||||
p_node = seq[i].node;
|
||||
if (p_node->n_child == 0) {
|
||||
p_trie = &trie[p_node->start];
|
||||
|
@ -1909,7 +1918,6 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
|
|||
{
|
||||
int i, j, k, bind_index, size, page_count, sym_index;
|
||||
const char *name;
|
||||
ElfW_Rel rel;
|
||||
ElfW(Sym) *sym;
|
||||
unsigned char *data = mo->chained_fixups->data;
|
||||
struct segment_command_64 *seg;
|
||||
|
@ -1931,6 +1939,17 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
|
|||
mo->bind_rebase[i + 1].bind ? "bind" : "rebase",
|
||||
s1->sections[mo->bind_rebase[i].section]->name, name);
|
||||
}
|
||||
for (i = 0; i < mo->n_bind_rebase; i++) {
|
||||
addr_t r_offset = mo->bind_rebase[i].rel.r_offset;
|
||||
if ((r_offset & 3) ||
|
||||
(r_offset & (SEG_PAGE_SIZE - 1)) >
|
||||
SEG_PAGE_SIZE - PTR_SIZE) {
|
||||
Section *s = s1->sections[mo->bind_rebase[i].section];
|
||||
|
||||
tcc_error("Illegal rel_offset %s %lld",
|
||||
s->name, (long long)r_offset);
|
||||
}
|
||||
}
|
||||
header = (struct dyld_chained_fixups_header *) data;
|
||||
data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
|
||||
header->starts_offset = data - mo->chained_fixups->data;
|
||||
|
@ -1966,29 +1985,26 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
|
|||
segment->max_valid_pointer = 0;
|
||||
segment->page_count = page_count;
|
||||
// add bind/rebase
|
||||
bind_index = 0;
|
||||
k = 0;
|
||||
for (j = 0; j < page_count; j++) {
|
||||
uint64_t start = seg->vmaddr + j * SEG_PAGE_SIZE;
|
||||
uint64_t end = start + SEG_PAGE_SIZE;
|
||||
addr_t start = seg->vmaddr + j * SEG_PAGE_SIZE;
|
||||
addr_t end = start + SEG_PAGE_SIZE;
|
||||
void *last;
|
||||
addr_t last_o = 0;
|
||||
uint64_t cur_o, cur;
|
||||
addr_t cur_o, cur;
|
||||
struct dyld_chained_ptr_64_rebase *rebase;
|
||||
struct dyld_chained_ptr_64_bind *bind;
|
||||
Section *s;
|
||||
|
||||
segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE;
|
||||
for (k = 0, bind_index = 0; k < mo->n_bind_rebase; k++) {
|
||||
uint64_t addr;
|
||||
for (; k < mo->n_bind_rebase; k++) {
|
||||
Section *s = s1->sections[mo->bind_rebase[k].section];
|
||||
addr_t r_offset = mo->bind_rebase[k].rel.r_offset;
|
||||
addr_t addr = s->sh_addr + r_offset;
|
||||
|
||||
s = s1->sections[mo->bind_rebase[k].section];
|
||||
rel = mo->bind_rebase[k].rel;
|
||||
if ((rel.r_offset & 3) ||
|
||||
(rel.r_offset & (SEG_PAGE_SIZE - 1)) >
|
||||
SEG_PAGE_SIZE - PTR_SIZE)
|
||||
tcc_error("Illegal rel_offset %s %lld",
|
||||
s->name, (long long)rel.r_offset);
|
||||
addr = s->sh_addr + rel.r_offset;
|
||||
if (addr >= start && addr < end) {
|
||||
if (addr >= end)
|
||||
break;
|
||||
if (addr >= start) {
|
||||
cur_o = addr - start;
|
||||
if (mo->bind_rebase[k].bind) {
|
||||
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)
|
|||
bind->next = (cur_o - last_o) / 4;
|
||||
}
|
||||
bind = (struct dyld_chained_ptr_64_bind *)
|
||||
(s->data + rel.r_offset);
|
||||
(s->data + r_offset);
|
||||
last = bind;
|
||||
last_o = cur_o;
|
||||
bind->ordinal = bind_index;
|
||||
|
@ -2015,10 +2031,10 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
|
|||
rebase->next = (cur_o - last_o) / 4;
|
||||
}
|
||||
rebase = (struct dyld_chained_ptr_64_rebase *)
|
||||
(s->data + rel.r_offset);
|
||||
(s->data + r_offset);
|
||||
last = rebase;
|
||||
last_o = cur_o;
|
||||
cur = (*(uint64_t *) (s->data + rel.r_offset)) -
|
||||
cur = (*(uint64_t *) (s->data + r_offset)) -
|
||||
PTR_64_OFFSET;
|
||||
rebase->target = cur & PTR_64_MASK;
|
||||
rebase->high8 = cur >> (64 - 8);
|
||||
|
|
|
@ -126,6 +126,17 @@ void tst_strtoll_strtoull(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
struct {
|
||||
int (*print)(const char *format, ...);
|
||||
} tst_indir = {
|
||||
printf
|
||||
};
|
||||
|
||||
void tst_indir_func(void)
|
||||
{
|
||||
tst_indir.print("tst_indir_func %d\n", 10);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
@ -144,4 +155,5 @@ main (void)
|
|||
tst_pack();
|
||||
tst_cast();
|
||||
tst_strtoll_strtoull();
|
||||
tst_indir_func();
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@ tst_adr 5
|
|||
tst_compare: ok
|
||||
tst_pack: j.f = 5, i.f = 5
|
||||
schar to ushort cast: ffff0033
|
||||
tst_indir_func 10
|
||||
|
|
Loading…
Reference in a new issue