mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-04 08:20:12 +08:00
macos: Support external functions
these are resolved non-lazy for now. We only need to generate the jump stub (using the GOT slot that will be initialized due to the non-lazy pointer marking, like with data symbols). On x86-64 we don't even need special marking of these stubs (with S_SYMBOL_STUBS and associated additional indirect symbol entries), as that's only used on i386 (where the stubs are self-modifying). So, this now works: extern int _printf(const char*, ...); int _start(void) { _printf("hello\n"); return 0; }
This commit is contained in:
parent
d82e64c163
commit
84c3fecf5e
36
tccmacho.c
36
tccmacho.c
@ -215,7 +215,8 @@ struct macho {
|
|||||||
} sk_to_sect[sk_last];
|
} sk_to_sect[sk_last];
|
||||||
int *elfsectomacho;
|
int *elfsectomacho;
|
||||||
int *e2msym;
|
int *e2msym;
|
||||||
Section *linkedit, *symtab, *strtab, *wdata, *indirsyms;
|
Section *linkedit, *symtab, *strtab, *wdata, *indirsyms, *stubs;
|
||||||
|
int stubsym;
|
||||||
uint32_t ilocal, iextdef, iundef;
|
uint32_t ilocal, iextdef, iundef;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -297,7 +298,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, type, gotplt_entry, sym_index;
|
int i, type, gotplt_entry, sym_index, for_code;
|
||||||
struct sym_attr *attr;
|
struct sym_attr *attr;
|
||||||
|
|
||||||
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
@ -309,6 +310,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
for_each_elem(s, 0, rel, ElfW_Rel) {
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
type = ELFW(R_TYPE)(rel->r_info);
|
type = ELFW(R_TYPE)(rel->r_info);
|
||||||
gotplt_entry = gotplt_entry_type(type);
|
gotplt_entry = gotplt_entry_type(type);
|
||||||
|
for_code = code_reloc(type);
|
||||||
/* We generate a non-lazy pointer for used undefined symbols
|
/* We generate a non-lazy pointer for used undefined symbols
|
||||||
and for defined symbols that must have a place for their
|
and for defined symbols that must have a place for their
|
||||||
address due to codegen (i.e. a reloc requiring a got slot). */
|
address due to codegen (i.e. a reloc requiring a got slot). */
|
||||||
@ -317,10 +319,11 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
if (sym->st_shndx == SHN_UNDEF
|
if (sym->st_shndx == SHN_UNDEF
|
||||||
|| gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
|
|| gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
|
||||||
attr = get_sym_attr(s1, sym_index, 1);
|
attr = get_sym_attr(s1, sym_index, 1);
|
||||||
if (!attr->plt_offset) {
|
if (!attr->dyn_index) {
|
||||||
uint32_t *pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
|
uint32_t *pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
|
||||||
attr->got_offset = s1->got->data_offset;
|
attr->got_offset = s1->got->data_offset;
|
||||||
attr->plt_offset = 1; /* used as flag */
|
attr->plt_offset = -1;
|
||||||
|
attr->dyn_index = 1; /* used as flag */
|
||||||
section_ptr_add(s1->got, PTR_SIZE);
|
section_ptr_add(s1->got, PTR_SIZE);
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
||||||
if (sym->st_shndx == SHN_UNDEF)
|
if (sym->st_shndx == SHN_UNDEF)
|
||||||
@ -329,11 +332,25 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
|||||||
/* The pointer slot we generated must point to the
|
/* The pointer slot we generated must point to the
|
||||||
symbol, whose address is only known after layout,
|
symbol, whose address is only known after layout,
|
||||||
so register a simply relocation for that. */
|
so register a simply relocation for that. */
|
||||||
put_elf_reloc (s1->symtab, s1->got, attr->got_offset,
|
put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
|
||||||
R_DATA_PTR, sym_index);
|
R_DATA_PTR, sym_index);
|
||||||
} else
|
} else
|
||||||
*pi = mo->e2msym[sym_index];
|
*pi = mo->e2msym[sym_index];
|
||||||
}
|
}
|
||||||
|
if (for_code) {
|
||||||
|
if (attr->plt_offset == -1) {
|
||||||
|
uint8_t *jmp;
|
||||||
|
attr->plt_offset = mo->stubs->data_offset;
|
||||||
|
jmp = section_ptr_add(mo->stubs, 6);
|
||||||
|
jmp[0] = 0xff; /* jmpq *ofs(%rip) */
|
||||||
|
jmp[1] = 0x25;
|
||||||
|
put_elf_reloc(s1->symtab, mo->stubs,
|
||||||
|
attr->plt_offset + 2,
|
||||||
|
R_X86_64_GOTPCREL, sym_index);
|
||||||
|
}
|
||||||
|
rel->r_info = ELFW(R_INFO)(mo->stubsym, type);
|
||||||
|
rel->r_addend += attr->plt_offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,6 +489,13 @@ static void create_symtab(TCCState *s1, struct macho *mo)
|
|||||||
int sym_index, sym_end;
|
int sym_index, sym_end;
|
||||||
struct nlist_64 *pn;
|
struct nlist_64 *pn;
|
||||||
|
|
||||||
|
/* Stub creation belongs to check_relocs, but we need to create
|
||||||
|
the symbol now, so its included in the sorting. */
|
||||||
|
mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
|
mo->stubsym = put_elf_sym(s1->symtab, 0, 0,
|
||||||
|
ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE), 0,
|
||||||
|
mo->stubs->sh_num, ".__stubs");
|
||||||
|
|
||||||
mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */
|
put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */
|
||||||
|
Loading…
Reference in New Issue
Block a user