Add dll support for macho
Update configure and remove dll=no for Darwin. Also removed dwarf=$dwarf because this is not a config option. In tccelf.c only add __PAGEZERO if stabs and executable. In tccrun.c correct rt_printline_dwarf code for dll. In tests/Makefile disable dlltest with PIC for Darwin because object format of .o file is still in elf. In tccmacho.c add dll support and and rpath support. Corrected trie code. For some reason symbol 'xx' should be after 'xx1'. Corrected weak symbol support for old macho code. Used R_JMP_SLOT instead of R_DATA_PTR in check_relocs.
This commit is contained in:
parent
9cfc8f60ce
commit
8d3930bdb6
5 changed files with 117 additions and 52 deletions
2
configure
vendored
2
configure
vendored
|
@ -66,7 +66,7 @@ case $targetos in
|
||||||
Darwin)
|
Darwin)
|
||||||
darwin=yes
|
darwin=yes
|
||||||
dwarf=4
|
dwarf=4
|
||||||
confvars="$confvars OSX dll=no dwarf=$dwarf"
|
confvars="$confvars OSX"
|
||||||
cc=`which cc`
|
cc=`which cc`
|
||||||
cc=`readlink $cc || echo clang`
|
cc=`readlink $cc || echo clang`
|
||||||
tcc_usrinclude="`xcrun --show-sdk-path`/usr/include"
|
tcc_usrinclude="`xcrun --show-sdk-path`/usr/include"
|
||||||
|
|
5
tccelf.c
5
tccelf.c
|
@ -1580,8 +1580,9 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
|
||||||
put_ptr(s1, NULL, 0);
|
put_ptr(s1, NULL, 0);
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
/* adjust for __PAGEZERO */
|
/* adjust for __PAGEZERO */
|
||||||
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
|
if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
|
||||||
(uint64_t)1 << 32);
|
write64le(data_section->data + data_section->data_offset - PTR_SIZE,
|
||||||
|
(uint64_t)1 << 32);
|
||||||
#endif
|
#endif
|
||||||
n = 2 * PTR_SIZE;
|
n = 2 * PTR_SIZE;
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
|
|
153
tccmacho.c
153
tccmacho.c
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#define MH_EXECUTE (0x2)
|
#define MH_EXECUTE (0x2)
|
||||||
#define MH_DYLDLINK (0x4)
|
#define MH_DYLDLINK (0x4)
|
||||||
|
#define MH_DYLIB (0x6)
|
||||||
#define MH_PIE (0x200000)
|
#define MH_PIE (0x200000)
|
||||||
|
|
||||||
#define CPU_SUBTYPE_LIB64 (0x80000000)
|
#define CPU_SUBTYPE_LIB64 (0x80000000)
|
||||||
|
@ -104,6 +105,7 @@ struct load_command {
|
||||||
#define LC_ID_DYLIB 0xd
|
#define LC_ID_DYLIB 0xd
|
||||||
#define LC_LOAD_DYLINKER 0xe
|
#define LC_LOAD_DYLINKER 0xe
|
||||||
#define LC_SEGMENT_64 0x19
|
#define LC_SEGMENT_64 0x19
|
||||||
|
#define LC_RPATH (0x1c | LC_REQ_DYLD)
|
||||||
#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)
|
#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)
|
||||||
#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)
|
#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)
|
||||||
#define LC_MAIN (0x28|LC_REQ_DYLD)
|
#define LC_MAIN (0x28|LC_REQ_DYLD)
|
||||||
|
@ -243,6 +245,12 @@ struct dylib_command {
|
||||||
uint32_t compatibility_version; /* library's compatibility vers number*/
|
uint32_t compatibility_version; /* library's compatibility vers number*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rpath_command {
|
||||||
|
uint32_t cmd; /* LC_RPATH */
|
||||||
|
uint32_t cmdsize; /* includes string */
|
||||||
|
lc_str path; /* path to add to run path */
|
||||||
|
};
|
||||||
|
|
||||||
struct dylinker_command {
|
struct dylinker_command {
|
||||||
uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or
|
uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or
|
||||||
LC_DYLD_ENVIRONMENT */
|
LC_DYLD_ENVIRONMENT */
|
||||||
|
@ -327,6 +335,8 @@ struct dysymtab_command {
|
||||||
#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
|
#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
|
||||||
#define BIND_OPCODE_DO_BIND 0x90
|
#define BIND_OPCODE_DO_BIND 0x90
|
||||||
|
|
||||||
|
#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1
|
||||||
|
|
||||||
#define BIND_TYPE_POINTER 1
|
#define BIND_TYPE_POINTER 1
|
||||||
#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2
|
#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2
|
||||||
|
|
||||||
|
@ -653,13 +663,12 @@ static void bind_rebase_add(struct macho *mo, int bind, int sh_info,
|
||||||
static void check_relocs(TCCState *s1, struct macho *mo)
|
static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel, save_rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, type, gotplt_entry, sym_index, for_code;
|
int i, type, gotplt_entry, sym_index, for_code;
|
||||||
uint32_t *pi, *goti;
|
uint32_t *pi, *goti;
|
||||||
struct sym_attr *attr;
|
struct sym_attr *attr;
|
||||||
|
|
||||||
mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
|
||||||
goti = NULL;
|
goti = NULL;
|
||||||
mo->nr_plt = mo->n_got = 0;
|
mo->nr_plt = mo->n_got = 0;
|
||||||
for (i = 1; i < s1->nb_sections; i++) {
|
for (i = 1; i < s1->nb_sections; i++) {
|
||||||
|
@ -668,6 +677,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
!strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
|
!strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
|
||||||
continue;
|
continue;
|
||||||
for_each_elem(s, 0, rel, ElfW_Rel) {
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
|
save_rel = *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);
|
for_code = code_reloc(type);
|
||||||
|
@ -685,7 +695,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
attr->dyn_index = 1; /* used as flag */
|
attr->dyn_index = 1; /* used as flag */
|
||||||
section_ptr_add(s1->got, PTR_SIZE);
|
section_ptr_add(s1->got, PTR_SIZE);
|
||||||
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_JMP_SLOT, sym_index);
|
||||||
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
||||||
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)
|
||||||
|
@ -701,7 +711,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
&& type == R_AARCH64_ADR_GOT_PAGE
|
&& type == R_AARCH64_ADR_GOT_PAGE
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr);
|
bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr);
|
||||||
attr->plt_offset = 0; // ignore next bind
|
attr->plt_offset = 0; // ignore next bind
|
||||||
s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
|
s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
|
||||||
}
|
}
|
||||||
|
@ -740,7 +750,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
write32le(jmp + 8, // br x16
|
write32le(jmp + 8, // br x16
|
||||||
0xd61f0200);
|
0xd61f0200);
|
||||||
#endif
|
#endif
|
||||||
bind_rebase_add(mo, 1, s1->got->reloc->sh_info, rel, attr);
|
bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr);
|
||||||
pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
|
pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
|
||||||
*pi = mo->e2msym[sym_index];
|
*pi = mo->e2msym[sym_index];
|
||||||
mo->nr_plt++;
|
mo->nr_plt++;
|
||||||
|
@ -749,9 +759,9 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
rel->r_addend += attr->plt_offset;
|
rel->r_addend += attr->plt_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == R_DATA_PTR)
|
if (type == R_DATA_PTR || type == R_JMP_SLOT)
|
||||||
bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0,
|
bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0,
|
||||||
s->sh_info, rel, NULL);
|
s->sh_info, &save_rel, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
|
pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
|
||||||
|
@ -765,15 +775,13 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
{
|
{
|
||||||
uint8_t *jmp;
|
uint8_t *jmp;
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel, save_rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, type, gotplt_entry, sym_index, for_code;
|
int i, type, gotplt_entry, sym_index, for_code;
|
||||||
int bind_offset, la_symbol_offset;
|
int bind_offset, la_symbol_offset;
|
||||||
uint32_t *pi, *goti;
|
uint32_t *pi, *goti;
|
||||||
struct sym_attr *attr;
|
struct sym_attr *attr;
|
||||||
|
|
||||||
mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
|
||||||
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
jmp = section_ptr_add(mo->stub_helper, 16);
|
jmp = section_ptr_add(mo->stub_helper, 16);
|
||||||
jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */
|
jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */
|
||||||
|
@ -814,6 +822,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
!strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
|
!strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
|
||||||
continue;
|
continue;
|
||||||
for_each_elem(s, 0, rel, ElfW_Rel) {
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
|
save_rel = *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);
|
for_code = code_reloc(type);
|
||||||
|
@ -831,7 +840,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
attr->dyn_index = 1; /* used as flag */
|
attr->dyn_index = 1; /* used as flag */
|
||||||
section_ptr_add(s1->got, PTR_SIZE);
|
section_ptr_add(s1->got, PTR_SIZE);
|
||||||
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_JMP_SLOT, sym_index);
|
||||||
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
|
||||||
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)
|
||||||
|
@ -852,7 +861,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
(mo->n_bind + 1) *
|
(mo->n_bind + 1) *
|
||||||
sizeof(struct bind));
|
sizeof(struct bind));
|
||||||
mo->bind[mo->n_bind].section = s1->got->reloc->sh_info;
|
mo->bind[mo->n_bind].section = s1->got->reloc->sh_info;
|
||||||
mo->bind[mo->n_bind].rel = *rel;
|
mo->bind[mo->n_bind].rel = save_rel;
|
||||||
mo->bind[mo->n_bind].rel.r_offset = attr->got_offset;
|
mo->bind[mo->n_bind].rel.r_offset = attr->got_offset;
|
||||||
mo->n_bind++;
|
mo->n_bind++;
|
||||||
s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
|
s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
|
||||||
|
@ -936,7 +945,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
bind_offset;
|
bind_offset;
|
||||||
mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset =
|
mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset =
|
||||||
la_symbol_offset;
|
la_symbol_offset;
|
||||||
mo->s_lazy_bind[mo->n_lazy_bind].rel = *rel;
|
mo->s_lazy_bind[mo->n_lazy_bind].rel = save_rel;
|
||||||
mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset =
|
mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset =
|
||||||
attr->plt_offset;
|
attr->plt_offset;
|
||||||
mo->n_lazy_bind++;
|
mo->n_lazy_bind++;
|
||||||
|
@ -948,13 +957,13 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
rel->r_addend += attr->plt_offset;
|
rel->r_addend += attr->plt_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type == R_DATA_PTR) {
|
if (type == R_DATA_PTR || type == R_JMP_SLOT) {
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
mo->bind = tcc_realloc(mo->bind,
|
mo->bind = tcc_realloc(mo->bind,
|
||||||
(mo->n_bind + 1) *
|
(mo->n_bind + 1) *
|
||||||
sizeof(struct bind));
|
sizeof(struct bind));
|
||||||
mo->bind[mo->n_bind].section = s->sh_info;
|
mo->bind[mo->n_bind].section = s->sh_info;
|
||||||
mo->bind[mo->n_bind].rel = *rel;
|
mo->bind[mo->n_bind].rel = save_rel;
|
||||||
mo->n_bind++;
|
mo->n_bind++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -962,7 +971,7 @@ static void check_relocs(TCCState *s1, struct macho *mo)
|
||||||
tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
|
tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
|
||||||
sizeof(struct s_rebase));
|
sizeof(struct s_rebase));
|
||||||
mo->s_rebase[mo->n_rebase].section = s->sh_info;
|
mo->s_rebase[mo->n_rebase].section = s->sh_info;
|
||||||
mo->s_rebase[mo->n_rebase].rel = *rel;
|
mo->s_rebase[mo->n_rebase].rel = save_rel;
|
||||||
mo->n_rebase++;
|
mo->n_rebase++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1008,6 +1017,7 @@ static int check_symbols(TCCState *s1, struct macho *mo)
|
||||||
if (mo->iundef == -1)
|
if (mo->iundef == -1)
|
||||||
mo->iundef = sym_index - 1;
|
mo->iundef = sym_index - 1;
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
||||||
|
|| s1->output_type != TCC_OUTPUT_EXE
|
||||||
|| find_elf_sym(s1->dynsymtab_section, name)) {
|
|| find_elf_sym(s1->dynsymtab_section, name)) {
|
||||||
/* Mark the symbol as coming from a dylib so that
|
/* Mark the symbol as coming from a dylib so that
|
||||||
relocate_syms doesn't complain. Normally bind_exe_dynsyms
|
relocate_syms doesn't complain. Normally bind_exe_dynsyms
|
||||||
|
@ -1170,6 +1180,7 @@ static void create_symtab(TCCState *s1, struct macho *mo)
|
||||||
mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
#endif
|
#endif
|
||||||
mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
|
mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1182,6 +1193,7 @@ static void create_symtab(TCCState *s1, struct macho *mo)
|
||||||
pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
|
pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
|
||||||
pn[sym_index - 1].n_value = sym_index;
|
pn[sym_index - 1].n_value = sym_index;
|
||||||
}
|
}
|
||||||
|
section_ptr_add(mo->strtab, -mo->strtab->data_offset & (PTR_SIZE - 1));
|
||||||
tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1);
|
tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1);
|
||||||
mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym));
|
mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym));
|
||||||
mo->e2msym[0] = -1;
|
mo->e2msym[0] = -1;
|
||||||
|
@ -1250,7 +1262,7 @@ static void calc_fixup_size(TCCState *s1, struct macho *mo)
|
||||||
|
|
||||||
size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
|
size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
|
||||||
size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8;
|
size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8;
|
||||||
for (i = 1; i < mo->nseg - 1; i++) {
|
for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
|
||||||
int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
|
int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
|
||||||
size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8;
|
size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8;
|
||||||
}
|
}
|
||||||
|
@ -1269,14 +1281,14 @@ static void calc_fixup_size(TCCState *s1, struct macho *mo)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static void set_segment_and_offset(struct macho *mo, addr_t addr,
|
static void set_segment_and_offset(TCCState *s1, struct macho *mo, addr_t addr,
|
||||||
uint8_t *ptr, int opcode,
|
uint8_t *ptr, int opcode,
|
||||||
Section *sec, addr_t offset)
|
Section *sec, addr_t offset)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct segment_command_64 *seg = NULL;
|
struct segment_command_64 *seg = NULL;
|
||||||
|
|
||||||
for (i = 1; i < mo->nseg - 1; i++) {
|
for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
|
||||||
seg = get_segment(mo, i);
|
seg = get_segment(mo, i);
|
||||||
if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize))
|
if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize))
|
||||||
break;
|
break;
|
||||||
|
@ -1301,7 +1313,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
||||||
mo->s_lazy_bind[i].bind_offset,
|
mo->s_lazy_bind[i].bind_offset,
|
||||||
mo->lazy_binding->data_offset);
|
mo->lazy_binding->data_offset);
|
||||||
ptr = section_ptr_add(mo->lazy_binding, 1);
|
ptr = section_ptr_add(mo->lazy_binding, 1);
|
||||||
set_segment_and_offset(mo, mo->la_symbol_ptr->sh_addr, ptr,
|
set_segment_and_offset(s1, mo, mo->la_symbol_ptr->sh_addr, ptr,
|
||||||
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
||||||
mo->lazy_binding,
|
mo->lazy_binding,
|
||||||
mo->s_lazy_bind[i].la_symbol_offset +
|
mo->s_lazy_bind[i].la_symbol_offset +
|
||||||
|
@ -1320,7 +1332,7 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
||||||
|
|
||||||
ptr = section_ptr_add(mo->rebase, 2);
|
ptr = section_ptr_add(mo->rebase, 2);
|
||||||
*ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
|
*ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
|
||||||
set_segment_and_offset(mo, s->sh_addr, ptr,
|
set_segment_and_offset(s1, mo, s->sh_addr, ptr,
|
||||||
REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
||||||
mo->rebase,
|
mo->rebase,
|
||||||
mo->s_rebase[i].rel.r_offset +
|
mo->s_rebase[i].rel.r_offset +
|
||||||
|
@ -1337,14 +1349,18 @@ static void bind_rebase(TCCState *s1, struct macho *mo)
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|
||||||
? mo->weak_binding : mo->binding;
|
? mo->weak_binding : mo->binding;
|
||||||
ptr = section_ptr_add(binding, 5 + strlen(name));
|
ptr = section_ptr_add(binding, 4 + (binding == mo->binding) +
|
||||||
*ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
|
strlen(name));
|
||||||
(BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
|
if (binding == mo->binding)
|
||||||
*ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;
|
*ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
|
||||||
|
(BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
|
||||||
|
*ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM |
|
||||||
|
(binding == mo->weak_binding
|
||||||
|
? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
|
||||||
strcpy((char *)ptr, name);
|
strcpy((char *)ptr, name);
|
||||||
ptr += strlen(name) + 1;
|
ptr += strlen(name) + 1;
|
||||||
*ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;
|
*ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;
|
||||||
set_segment_and_offset(mo, s->sh_addr, ptr,
|
set_segment_and_offset(s1, mo, s->sh_addr, ptr,
|
||||||
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
||||||
binding,
|
binding,
|
||||||
mo->bind[i].rel.r_offset + s->sh_addr);
|
mo->bind[i].rel.r_offset + s->sh_addr);
|
||||||
|
@ -1488,7 +1504,12 @@ static int triecmp(const void *_a, const void *_b, void *arg)
|
||||||
{
|
{
|
||||||
struct trie_info *a = (struct trie_info *) _a;
|
struct trie_info *a = (struct trie_info *) _a;
|
||||||
struct trie_info *b = (struct trie_info *) _b;
|
struct trie_info *b = (struct trie_info *) _b;
|
||||||
|
int len_a = strlen(a->name);
|
||||||
|
int len_b = strlen(b->name);
|
||||||
|
|
||||||
|
/* strange sorting needed. Name 'xx' should be after 'xx1' */
|
||||||
|
if (!strncmp(a->name, b->name, len_a < len_b ? len_a : len_b))
|
||||||
|
return len_a < len_b ? 1 : (len_a > len_b ? -1 : 0);
|
||||||
return strcmp(a->name, b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1502,7 +1523,7 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
||||||
struct trie_info *trie = NULL, *p_trie;
|
struct trie_info *trie = NULL, *p_trie;
|
||||||
struct trie_node node, *p_node;
|
struct trie_node node, *p_node;
|
||||||
struct trie_seq *seq = NULL;
|
struct trie_seq *seq = NULL;
|
||||||
addr_t vm_addr = get_segment(mo, 1)->vmaddr;
|
addr_t vm_addr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr;
|
||||||
|
|
||||||
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
|
||||||
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
||||||
|
@ -1576,19 +1597,21 @@ static void export_trie(TCCState *s1, struct macho *mo)
|
||||||
tcc_free(trie);
|
tcc_free(trie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_sections(TCCState *s1, struct macho *mo)
|
static void collect_sections(TCCState *s1, struct macho *mo, const char *filename)
|
||||||
{
|
{
|
||||||
int i, sk, numsec;
|
int i, sk, numsec;
|
||||||
int used_segment[N_SEGMENT];
|
int used_segment[N_SEGMENT];
|
||||||
uint64_t curaddr, fileofs;
|
uint64_t curaddr, fileofs;
|
||||||
Section *s;
|
Section *s;
|
||||||
struct segment_command_64 *seg;
|
struct segment_command_64 *seg;
|
||||||
|
struct dylib_command *dylib;
|
||||||
#ifdef CONFIG_NEW_MACHO
|
#ifdef CONFIG_NEW_MACHO
|
||||||
struct linkedit_data_command *chained_fixups_lc;
|
struct linkedit_data_command *chained_fixups_lc;
|
||||||
struct linkedit_data_command *export_trie_lc;
|
struct linkedit_data_command *export_trie_lc;
|
||||||
#endif
|
#endif
|
||||||
struct build_version_command *dyldbv;
|
struct build_version_command *dyldbv;
|
||||||
struct source_version_command *dyldsv;
|
struct source_version_command *dyldsv;
|
||||||
|
struct rpath_command *rpath;
|
||||||
struct dylinker_command *dyldlc;
|
struct dylinker_command *dyldlc;
|
||||||
struct symtab_command *symlc;
|
struct symtab_command *symlc;
|
||||||
struct dysymtab_command *dysymlc;
|
struct dysymtab_command *dysymlc;
|
||||||
|
@ -1662,10 +1685,16 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
used_segment[skinfo[sk].seg_initial] = 1;
|
used_segment[skinfo[sk].seg_initial] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->output_type != TCC_OUTPUT_EXE)
|
||||||
|
used_segment[0] = 0;
|
||||||
|
|
||||||
for (i = 0; i < N_SEGMENT; i++)
|
for (i = 0; i < N_SEGMENT; i++)
|
||||||
if (used_segment[i]) {
|
if (used_segment[i]) {
|
||||||
seg = add_segment(mo, all_segment[i].name);
|
seg = add_segment(mo, all_segment[i].name);
|
||||||
seg->vmaddr = all_segment[i].vmaddr;
|
if (i == 1 && s1->output_type != TCC_OUTPUT_EXE)
|
||||||
|
seg->vmaddr = 0;
|
||||||
|
else
|
||||||
|
seg->vmaddr = all_segment[i].vmaddr;
|
||||||
seg->vmsize = all_segment[i].vmsize;
|
seg->vmsize = all_segment[i].vmsize;
|
||||||
seg->maxprot = all_segment[i].maxprot;
|
seg->maxprot = all_segment[i].maxprot;
|
||||||
seg->initprot = all_segment[i].initprot;
|
seg->initprot = all_segment[i].initprot;
|
||||||
|
@ -1675,6 +1704,17 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
mo->segment[sk] = mo->nseg - 1;
|
mo->segment[sk] = mo->nseg - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->output_type != TCC_OUTPUT_EXE) {
|
||||||
|
i = (sizeof(*dylib) + strlen(filename) + 1 + 7) &-8;
|
||||||
|
dylib = add_lc(mo, LC_ID_DYLIB, i);
|
||||||
|
dylib->name = sizeof(*dylib);
|
||||||
|
dylib->timestamp = 1;
|
||||||
|
dylib->current_version = 1 << 16;
|
||||||
|
dylib->compatibility_version = 1 << 16;
|
||||||
|
str = (char*)dylib + dylib->name;
|
||||||
|
strcpy(str, filename);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NEW_MACHO
|
#ifdef CONFIG_NEW_MACHO
|
||||||
chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
|
chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
|
||||||
sizeof(struct linkedit_data_command));
|
sizeof(struct linkedit_data_command));
|
||||||
|
@ -1687,11 +1727,13 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
|
symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
|
||||||
dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
|
dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
|
||||||
|
|
||||||
i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
|
if (s1->output_type == TCC_OUTPUT_EXE) {
|
||||||
dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i);
|
i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
|
||||||
dyldlc->name = sizeof(*dyldlc);
|
dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i);
|
||||||
str = (char*)dyldlc + dyldlc->name;
|
dyldlc->name = sizeof(*dyldlc);
|
||||||
strcpy(str, "/usr/lib/dyld");
|
str = (char*)dyldlc + dyldlc->name;
|
||||||
|
strcpy(str, "/usr/lib/dyld");
|
||||||
|
}
|
||||||
|
|
||||||
dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv));
|
dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv));
|
||||||
dyldbv->platform = PLATFORM_MACOS;
|
dyldbv->platform = PLATFORM_MACOS;
|
||||||
|
@ -1702,8 +1744,10 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv));
|
dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv));
|
||||||
dyldsv->version = 0;
|
dyldsv->version = 0;
|
||||||
|
|
||||||
mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
|
if (s1->output_type == TCC_OUTPUT_EXE) {
|
||||||
mo->ep->entryoff = 4096;
|
mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
|
||||||
|
mo->ep->entryoff = 4096;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||||
DLLReference *dllref = s1->loaded_dlls[i];
|
DLLReference *dllref = s1->loaded_dlls[i];
|
||||||
|
@ -1711,13 +1755,21 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
add_dylib(mo, dllref->name);
|
add_dylib(mo, dllref->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s1->rpath) {
|
||||||
|
i = (sizeof(*rpath) + strlen(s1->rpath) + 1 + 7) &-8;
|
||||||
|
rpath = add_lc(mo, LC_RPATH, i);
|
||||||
|
rpath->path = sizeof(*rpath);
|
||||||
|
str = (char*)rpath + rpath->path;
|
||||||
|
strcpy(str, s1->rpath);
|
||||||
|
}
|
||||||
|
|
||||||
fileofs = 4096; /* leave space for mach-o headers */
|
fileofs = 4096; /* leave space for mach-o headers */
|
||||||
curaddr = get_segment(mo, 1)->vmaddr;
|
curaddr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr;
|
||||||
curaddr += 4096;
|
curaddr += 4096;
|
||||||
seg = NULL;
|
seg = NULL;
|
||||||
numsec = 0;
|
numsec = 0;
|
||||||
mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
|
mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
|
||||||
for (sk = sk_unknown; sk < sk_last; sk++) {
|
for (sk = sk_text; sk < sk_last; sk++) {
|
||||||
struct section_64 *sec = NULL;
|
struct section_64 *sec = NULL;
|
||||||
if (seg) {
|
if (seg) {
|
||||||
seg->vmsize = curaddr - seg->vmaddr;
|
seg->vmsize = curaddr - seg->vmaddr;
|
||||||
|
@ -1734,7 +1786,8 @@ static void collect_sections(TCCState *s1, struct macho *mo)
|
||||||
export_trie(s1, mo);
|
export_trie(s1, mo);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (mo->segment[sk] && mo->sk_to_sect[sk].s) {
|
if ((s1->output_type != TCC_OUTPUT_EXE || mo->segment[sk]) &&
|
||||||
|
mo->sk_to_sect[sk].s) {
|
||||||
uint64_t al = 0;
|
uint64_t al = 0;
|
||||||
int si;
|
int si;
|
||||||
seg = get_segment(mo, mo->segment[sk]);
|
seg = get_segment(mo, mo->segment[sk]);
|
||||||
|
@ -1889,8 +1942,14 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
|
||||||
mo->mh.mh.cputype = CPU_TYPE_ARM64;
|
mo->mh.mh.cputype = CPU_TYPE_ARM64;
|
||||||
mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL;
|
mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL;
|
||||||
#endif
|
#endif
|
||||||
mo->mh.mh.filetype = MH_EXECUTE;
|
if (s1->output_type == TCC_OUTPUT_EXE) {
|
||||||
mo->mh.mh.flags = MH_DYLDLINK | MH_PIE;
|
mo->mh.mh.filetype = MH_EXECUTE;
|
||||||
|
mo->mh.mh.flags = MH_DYLDLINK | MH_PIE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mo->mh.mh.filetype = MH_DYLIB;
|
||||||
|
mo->mh.mh.flags = MH_DYLDLINK;
|
||||||
|
}
|
||||||
mo->mh.mh.ncmds = mo->nlc;
|
mo->mh.mh.ncmds = mo->nlc;
|
||||||
mo->mh.mh.sizeofcmds = 0;
|
mo->mh.mh.sizeofcmds = 0;
|
||||||
for (i = 0; i < mo->nlc; i++)
|
for (i = 0; i < mo->nlc; i++)
|
||||||
|
@ -1905,7 +1964,8 @@ static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
|
||||||
|
|
||||||
for (sk = sk_unknown; sk < sk_last; sk++) {
|
for (sk = sk_unknown; sk < sk_last; sk++) {
|
||||||
//struct segment_command_64 *seg;
|
//struct segment_command_64 *seg;
|
||||||
if (!mo->segment[sk] || !mo->sk_to_sect[sk].s)
|
if ((s1->output_type == TCC_OUTPUT_EXE && !mo->segment[sk]) ||
|
||||||
|
!mo->sk_to_sect[sk].s)
|
||||||
continue;
|
continue;
|
||||||
/*seg =*/ get_segment(mo, mo->segment[sk]);
|
/*seg =*/ get_segment(mo, mo->segment[sk]);
|
||||||
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
|
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
|
||||||
|
@ -1969,7 +2029,7 @@ ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
|
||||||
image = (struct dyld_chained_starts_in_image *) data;
|
image = (struct dyld_chained_starts_in_image *) data;
|
||||||
data += (size + 7) & -8;
|
data += (size + 7) & -8;
|
||||||
image->seg_count = mo->nseg;
|
image->seg_count = mo->nseg;
|
||||||
for (i = 1; i < mo->nseg - 1; i++) {
|
for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
|
||||||
image->seg_info_offset[i] = (data - mo->chained_fixups->data) -
|
image->seg_info_offset[i] = (data - mo->chained_fixups->data) -
|
||||||
header->starts_offset;
|
header->starts_offset;
|
||||||
seg = get_segment(mo, i);
|
seg = get_segment(mo, i);
|
||||||
|
@ -2117,10 +2177,11 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
||||||
check_relocs(s1, &mo);
|
check_relocs(s1, &mo);
|
||||||
ret = check_symbols(s1, &mo);
|
ret = check_symbols(s1, &mo);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
collect_sections(s1, &mo);
|
collect_sections(s1, &mo, filename);
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
relocate_syms(s1, s1->symtab, 0);
|
||||||
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
|
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||||
- get_segment(&mo, 1)->vmaddr;
|
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
|
||||||
|
- get_segment(&mo, 1)->vmaddr;
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
goto do_ret;
|
goto do_ret;
|
||||||
relocate_sections(s1);
|
relocate_sections(s1);
|
||||||
|
|
7
tccrun.c
7
tccrun.c
|
@ -772,7 +772,7 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||||
addr_t last_pc;
|
addr_t last_pc;
|
||||||
addr_t pc;
|
addr_t pc;
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
addr_t first_pc = 0;
|
addr_t first_pc;
|
||||||
#endif
|
#endif
|
||||||
addr_t func_addr;
|
addr_t func_addr;
|
||||||
int line;
|
int line;
|
||||||
|
@ -782,6 +782,9 @@ static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
|
||||||
next:
|
next:
|
||||||
ln = rc->dwarf_line;
|
ln = rc->dwarf_line;
|
||||||
while (ln < rc->dwarf_line_end) {
|
while (ln < rc->dwarf_line_end) {
|
||||||
|
#if defined TCC_TARGET_MACHO
|
||||||
|
first_pc = 0;
|
||||||
|
#endif
|
||||||
dir_size = 0;
|
dir_size = 0;
|
||||||
filename_size = 0;
|
filename_size = 0;
|
||||||
last_pc = 0;
|
last_pc = 0;
|
||||||
|
@ -935,7 +938,7 @@ check_pc:
|
||||||
#endif
|
#endif
|
||||||
#if defined TCC_TARGET_MACHO
|
#if defined TCC_TARGET_MACHO
|
||||||
if (first_pc == 0 && rc->prog_base != (addr_t) -1)
|
if (first_pc == 0 && rc->prog_base != (addr_t) -1)
|
||||||
first_pc += rc->prog_base - ((uint64_t)1 << 32);
|
first_pc += rc->prog_base;
|
||||||
pc += first_pc;
|
pc += first_pc;
|
||||||
#endif
|
#endif
|
||||||
opindex = 0;
|
opindex = 0;
|
||||||
|
|
|
@ -158,7 +158,7 @@ dlltest:
|
||||||
$(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF)
|
$(TCC) $(NATIVE_DEFINES) -DLIBTCC_AS_DLL $(TOPSRC)/libtcc.c $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||||
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
$(TCC) $(NATIVE_DEFINES) -DONE_SOURCE=0 $(TOPSRC)/tcc.c libtcc2$(DLLSUF) $(LIBS) -Wl,-rpath=. -o tcc2$(EXESUF)
|
||||||
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
./tcc2$(EXESUF) $(TCCFLAGS) $(RUN_TCC) -run $(TOPSRC)/examples/ex1.c
|
||||||
ifndef CONFIG_WIN32
|
ifeq (,$(filter Darwin WIN32,$(TARGETOS)))
|
||||||
@echo ------------ $@ with PIC ------------
|
@echo ------------ $@ with PIC ------------
|
||||||
$(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c
|
$(CC) $(CFLAGS) -fPIC $(NATIVE_DEFINES) -DLIBTCC_AS_DLL -c $(TOPSRC)/libtcc.c
|
||||||
$(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF)
|
$(TCC) libtcc.o $(LIBS) -shared -o libtcc2$(DLLSUF)
|
||||||
|
|
Loading…
Reference in a new issue