mirror of
https://github.com/frida/tinycc
synced 2024-11-27 10:09:42 +03:00
final update for 0.9.27
tccgen.c: - fix ldouble asm hack - fix a VLA problem on Win64 (also x86_64-gen.c) - patch_type(): make sure that no symbol ever changes from global to static tcc.c: - tcc -vv: print libtcc1.a path also on win32 tccpe.c, tcctools.c: - use unix LF mode to for .def output files (that is for creating reproducible output trees) Makefile: - suppress some warnings when makeinfo is missing - call 'which install' only on win32 tests/Makefile: - change PATH only on WINNT systems (i.e. not if cross-compiling on linux for win32) - asm-c-connect.test: slim output and do diff tccrun.c tccpe.c *-link.c: - integrate former 'pe_relocate_rva()' into normal relocation This also fixes linkage of the unwind data on WIN64 for -run (reported by Janus Lynggaard Thorborg) tccasm.c, tests/tcctest.c: - fix dot (sym_index of -1 crashed in put_elf_reloc) - massage .set a bit (see test) other: - #define SECTION_ABS removed - ST_DATA Section *strtab_section: removed - put_extern_sym2(): take int section number Conflicts: tccelf.c tccpe.c Conflicts: tccelf.c
This commit is contained in:
parent
1a4d4b76e8
commit
d348a9a51d
5
.gitignore
vendored
5
.gitignore
vendored
@ -41,16 +41,17 @@ win32/include/stddef.h
|
||||
win32/include/varargs.h
|
||||
win32/include/tcclib.h
|
||||
|
||||
tests/test.out*
|
||||
tests/test*.out
|
||||
tests/tcctest[1234]
|
||||
tests/tcctest.gcc
|
||||
tests/*.out*
|
||||
tests/*.ref
|
||||
tests/*.txt
|
||||
tests/*.gcc
|
||||
tests/*-cc*
|
||||
tests/*-tcc*
|
||||
tests/libtcc_test
|
||||
tests/asm-c-connect
|
||||
tests/asm-c-connect-sep
|
||||
tests/vla_test
|
||||
tests/hello
|
||||
tests/tests2/fred.txt
|
||||
|
15
Makefile
15
Makefile
@ -239,14 +239,15 @@ FORCE:
|
||||
# --------------------------------------------------------------------------
|
||||
# documentation and man page
|
||||
tcc-doc.html: tcc-doc.texi
|
||||
-makeinfo --no-split --html --number-sections -o $@ $<
|
||||
makeinfo --no-split --html --number-sections -o $@ $< || true
|
||||
|
||||
tcc.1: tcc-doc.texi
|
||||
-$(TOPSRC)/texi2pod.pl $< tcc.pod
|
||||
-pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod > $@
|
||||
$(TOPSRC)/texi2pod.pl $< tcc.pod \
|
||||
&& pod2man --section=1 --center="Tiny C Compiler" --release="$(VERSION)" tcc.pod >tmp.1 \
|
||||
&& mv tmp.1 $@ || rm -f tmp.1
|
||||
|
||||
tcc-doc.info: tcc-doc.texi
|
||||
-makeinfo $<
|
||||
makeinfo $< || true
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# install
|
||||
@ -304,7 +305,7 @@ ifneq "$(wildcard $(LIBTCC1_U))" ""
|
||||
endif
|
||||
|
||||
# the msys-git shell works to configure && make except it does not have install
|
||||
ifeq ($(CONFIG_WIN32)-$(shell which install >/dev/null 2>&1 || echo no),yes-no)
|
||||
ifeq "$(and $(CONFIG_WIN32),$(shell which install >/dev/null 2>&1 || echo no))" "no"
|
||||
install-win : INSTALL = cp
|
||||
install-win : INSTALLBIN = cp
|
||||
endif
|
||||
@ -349,10 +350,10 @@ tests2.%:
|
||||
$(MAKE) -C tests/tests2 $@
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) $(PROGS_CROSS) tcc_p$(EXESUF) tcc.pod
|
||||
rm -f tcc$(EXESUF) tcc_p$(EXESUF) *-tcc$(EXESUF) tcc.pod
|
||||
rm -f *~ *.o *.a *.so* *.out *.log lib*.def *.exe *.dll a.out tags TAGS
|
||||
@$(MAKE) -C tests $@
|
||||
@$(MAKE) -C lib $@
|
||||
@$(MAKE) -C tests $@
|
||||
|
||||
distclean: clean
|
||||
rm -f config.h config.mak config.texi tcc.1 tcc-doc.info tcc-doc.html
|
||||
|
@ -382,6 +382,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||
/* Nothing to do. Normally used to indicate a dependency
|
||||
on a certain symbol (like for exception handling under EABI). */
|
||||
return;
|
||||
case R_ARM_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
|
@ -240,6 +240,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||
#endif
|
||||
write64le(ptr, val - rel->r_addend);
|
||||
return;
|
||||
case R_AARCH64_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
default:
|
||||
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
|
||||
type, (unsigned)addr, ptr, (unsigned)val);
|
||||
|
@ -226,6 +226,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||
write16le(ptr, read16le(ptr) + val - addr);
|
||||
return;
|
||||
case R_386_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
return;
|
||||
case R_386_COPY:
|
||||
|
2
tcc.c
2
tcc.c
@ -182,9 +182,9 @@ static void print_search_dirs(TCCState *s)
|
||||
/* print_dirs("programs", NULL, 0); */
|
||||
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
||||
#ifndef TCC_TARGET_PE
|
||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
|
||||
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
|
||||
#endif
|
||||
}
|
||||
|
19
tcc.h
19
tcc.h
@ -489,14 +489,6 @@ typedef struct Sym {
|
||||
} Sym;
|
||||
|
||||
/* section definition */
|
||||
/* XXX: use directly ELF structure for parameters ? */
|
||||
/* special flag to indicate that the section should not be linked to
|
||||
the other ones */
|
||||
#define SHF_PRIVATE 0x80000000
|
||||
|
||||
/* special flag, too */
|
||||
#define SECTION_ABS ((void *)1)
|
||||
|
||||
typedef struct Section {
|
||||
unsigned long data_offset; /* current data offset */
|
||||
unsigned char *data; /* section data */
|
||||
@ -795,15 +787,13 @@ struct TCCState {
|
||||
struct sym_attr *sym_attrs;
|
||||
int nb_sym_attrs;
|
||||
|
||||
/* tiny assembler state */
|
||||
ElfSym esym_dot;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* PE info */
|
||||
int pe_subsystem;
|
||||
unsigned pe_characteristics;
|
||||
unsigned pe_file_align;
|
||||
unsigned pe_stack_size;
|
||||
addr_t pe_imagebase;
|
||||
# ifdef TCC_TARGET_X86_64
|
||||
Section *uw_pdata;
|
||||
int uw_sym;
|
||||
@ -1390,7 +1380,7 @@ ST_DATA Section *lbounds_section; /* contains local data bound description */
|
||||
ST_FUNC void tccelf_bounds_new(TCCState *s);
|
||||
#endif
|
||||
/* symbol sections */
|
||||
ST_DATA Section *symtab_section, *strtab_section;
|
||||
ST_DATA Section *symtab_section;
|
||||
/* debug sections */
|
||||
ST_DATA Section *stab_section, *stabstr_section;
|
||||
|
||||
@ -1408,7 +1398,7 @@ ST_FUNC void section_reserve(Section *sec, unsigned long size);
|
||||
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
||||
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
|
||||
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, Section *section, addr_t value, unsigned long size, int can_add_underscore);
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||
ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||
#if PTR_SIZE == 4
|
||||
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
||||
@ -1551,6 +1541,9 @@ ST_FUNC void gen_bounded_ptr_deref(void);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
|
||||
ST_FUNC void gen_opl(int op);
|
||||
#ifdef TCC_TARGET_PE
|
||||
ST_FUNC void gen_vla_result(int addr);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* ------------ arm-gen.c ------------ */
|
||||
|
40
tccasm.c
40
tccasm.c
@ -32,7 +32,8 @@ ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
|
||||
}
|
||||
|
||||
static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
|
||||
static Sym sym_dot;
|
||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local);
|
||||
static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
|
||||
|
||||
static Sym *asm_label_find(int v)
|
||||
{
|
||||
@ -73,6 +74,16 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
|
||||
return sym;
|
||||
}
|
||||
|
||||
static Sym* asm_section_sym(TCCState *s1, Section *sec)
|
||||
{
|
||||
char buf[100];
|
||||
int label = tok_alloc(buf,
|
||||
snprintf(buf, sizeof buf, "L.%s", sec->name)
|
||||
)->tok;
|
||||
Sym *sym = asm_label_find(label);
|
||||
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
||||
}
|
||||
|
||||
/* We do not use the C expression parser to handle symbols. Maybe the
|
||||
C expression parser could be tweaked to do so. */
|
||||
|
||||
@ -145,13 +156,9 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
||||
skip(')');
|
||||
break;
|
||||
case '.':
|
||||
pe->v = 0;
|
||||
pe->sym = &sym_dot;
|
||||
pe->pcrel = 0;
|
||||
sym_dot.type.t = VT_ASM | VT_STATIC;
|
||||
sym_dot.c = -1;
|
||||
tcc_state->esym_dot.st_shndx = cur_text_section->sh_num;
|
||||
tcc_state->esym_dot.st_value = ind;
|
||||
pe->v = ind;
|
||||
pe->sym = asm_section_sym(s1, cur_text_section);
|
||||
pe->pcrel = 0;
|
||||
next();
|
||||
break;
|
||||
default:
|
||||
@ -368,29 +375,26 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
||||
/* A VT_EXTERN symbol, even if it has a section is considered
|
||||
overridable. This is how we "define" .set targets. Real
|
||||
definitions won't have VT_EXTERN set. */
|
||||
if (esym && esym->st_shndx != SHN_UNDEF && !(sym->type.t & VT_EXTERN)) {
|
||||
if (esym && esym->st_shndx != SHN_UNDEF) {
|
||||
/* the label is already defined */
|
||||
if (is_local != 1) {
|
||||
tcc_error("assembler label '%s' already defined",
|
||||
get_tok_str(label, NULL));
|
||||
} else {
|
||||
/* redefinition of local labels is possible */
|
||||
if (IS_ASM_SYM(sym)
|
||||
&& (is_local == 1 || (sym->type.t & VT_EXTERN)))
|
||||
goto new_label;
|
||||
}
|
||||
if (!(sym->type.t & VT_EXTERN))
|
||||
tcc_error("assembler label '%s' already defined",
|
||||
get_tok_str(label, NULL));
|
||||
}
|
||||
} else {
|
||||
new_label:
|
||||
sym = asm_label_push(label);
|
||||
}
|
||||
if (!sym->c)
|
||||
put_extern_sym2(sym, NULL, 0, 0, 0);
|
||||
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 0);
|
||||
esym = elfsym(sym);
|
||||
esym->st_shndx = sh_num;
|
||||
esym->st_value = value;
|
||||
|
||||
if (is_local != 2)
|
||||
sym->type.t &= ~VT_EXTERN;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
16
tccelf.c
16
tccelf.c
@ -38,13 +38,18 @@ ST_DATA Section *bounds_section; /* contains global data bound description */
|
||||
ST_DATA Section *lbounds_section; /* contains local data bound description */
|
||||
#endif
|
||||
/* symbol sections */
|
||||
ST_DATA Section *symtab_section, *strtab_section;
|
||||
ST_DATA Section *symtab_section;
|
||||
/* debug sections */
|
||||
ST_DATA Section *stab_section, *stabstr_section;
|
||||
|
||||
/* XXX: avoid static variable */
|
||||
static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
|
||||
|
||||
/* special flag to indicate that the section should not be linked to the other ones */
|
||||
#define SHF_PRIVATE 0x80000000
|
||||
/* section is dynsymtab_section */
|
||||
#define SHF_DYNSYM 0x40000000
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
ST_FUNC void tccelf_new(TCCState *s)
|
||||
@ -63,11 +68,10 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
||||
".strtab",
|
||||
".hashtab", SHF_PRIVATE);
|
||||
strtab_section = symtab_section->link;
|
||||
s->symtab = symtab_section;
|
||||
|
||||
/* private symbol table for dynamic symbols */
|
||||
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
|
||||
s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
|
||||
".dynstrtab",
|
||||
".dynhashtab", SHF_PRIVATE);
|
||||
get_sym_attr(s, 0, 1);
|
||||
@ -128,6 +132,8 @@ ST_FUNC void tccelf_delete(TCCState *s1)
|
||||
/* free loaded dlls array */
|
||||
dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
|
||||
tcc_free(s1->sym_attrs);
|
||||
|
||||
symtab_section = NULL; /* for tccrun.c:rt_printline() */
|
||||
}
|
||||
|
||||
/* save section data state */
|
||||
@ -536,7 +542,7 @@ ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
|
||||
goto do_patch;
|
||||
} else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) {
|
||||
/* data symbol keeps precedence over common/bss */
|
||||
} else if (s == tcc_state->dynsymtab_section) {
|
||||
} else if (s->sh_flags & SHF_DYNSYM) {
|
||||
/* we accept that two DLL define the same symbol */
|
||||
} else if (esym->st_other & ST_ASM_SET) {
|
||||
/* If the existing symbol came from an asm .set
|
||||
@ -779,7 +785,7 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||
for_each_elem(symtab, 1, sym, ElfW(Sym)) {
|
||||
sh_num = sym->st_shndx;
|
||||
if (sh_num == SHN_UNDEF) {
|
||||
name = (char *) strtab_section->data + sym->st_name;
|
||||
name = (char *) s1->symtab->link->data + sym->st_name;
|
||||
/* Use ld.so to resolve symbol for us (for tcc -run) */
|
||||
if (do_resolve) {
|
||||
#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
|
||||
|
49
tccgen.c
49
tccgen.c
@ -285,10 +285,7 @@ ST_FUNC ElfSym *elfsym(Sym *s)
|
||||
{
|
||||
if (!s || !s->c)
|
||||
return NULL;
|
||||
if (s->c == -1)
|
||||
return &tcc_state->esym_dot;
|
||||
else
|
||||
return &((ElfSym *)symtab_section->data)[s->c];
|
||||
return &((ElfSym *)symtab_section->data)[s->c];
|
||||
}
|
||||
|
||||
/* apply storage attributes to Elf symbol */
|
||||
@ -338,11 +335,11 @@ ST_FUNC void update_storage(Sym *sym)
|
||||
/* update sym->c so that it points to an external symbol in section
|
||||
'section' with value 'value' */
|
||||
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||
addr_t value, unsigned long size,
|
||||
int can_add_underscore)
|
||||
{
|
||||
int sym_type, sym_bind, sh_num, info, other, t;
|
||||
int sym_type, sym_bind, info, other, t;
|
||||
ElfSym *esym;
|
||||
const char *name;
|
||||
char buf1[256];
|
||||
@ -350,13 +347,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
char buf[32];
|
||||
#endif
|
||||
|
||||
if (section == NULL)
|
||||
sh_num = SHN_UNDEF;
|
||||
else if (section == SECTION_ABS)
|
||||
sh_num = SHN_ABS;
|
||||
else
|
||||
sh_num = section->sh_num;
|
||||
|
||||
if (!sym->c) {
|
||||
name = get_tok_str(sym->v, NULL);
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@ -431,7 +421,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||
ST_FUNC void put_extern_sym(Sym *sym, Section *section,
|
||||
addr_t value, unsigned long size)
|
||||
{
|
||||
put_extern_sym2(sym, section, value, size, 1);
|
||||
int sh_num = section ? section->sh_num : SHN_UNDEF;
|
||||
put_extern_sym2(sym, sh_num, value, size, 1);
|
||||
}
|
||||
|
||||
/* add a new relocation entry to symbol 'sym' in section 's' */
|
||||
@ -848,6 +839,7 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
|
||||
} else if (IS_ASM_SYM(s)) {
|
||||
s->type.t = type->t | (s->type.t & VT_EXTERN);
|
||||
s->type.ref = type->ref;
|
||||
update_storage(s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -862,9 +854,12 @@ static void patch_type(Sym *sym, CType *type)
|
||||
}
|
||||
|
||||
if (IS_ASM_SYM(sym)) {
|
||||
sym->type = *type;
|
||||
/* stay static if both are static */
|
||||
sym->type.t = type->t & (sym->type.t | ~VT_STATIC);
|
||||
sym->type.ref = type->ref;
|
||||
}
|
||||
|
||||
} else if (!is_compatible_types(&sym->type, type)) {
|
||||
if (!is_compatible_types(&sym->type, type)) {
|
||||
tcc_error("incompatible types for redefinition of '%s'",
|
||||
get_tok_str(sym->v, NULL));
|
||||
|
||||
@ -876,10 +871,11 @@ static void patch_type(Sym *sym, CType *type)
|
||||
get_tok_str(sym->v, NULL));
|
||||
|
||||
if (0 == (type->t & VT_EXTERN)) {
|
||||
/* put complete type */
|
||||
sym->type = *type;
|
||||
/* use static from prototype */
|
||||
sym->type.t |= static_proto;
|
||||
/* put complete type, use static from prototype */
|
||||
sym->type.t = (type->t & ~VT_STATIC) | static_proto;
|
||||
if (type->t & VT_INLINE)
|
||||
sym->type.t = type->t;
|
||||
sym->type.ref = type->ref;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -6570,8 +6566,10 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||
memcpy(ptr, &vtop->c.ld, 10);
|
||||
#ifdef __TINYC__
|
||||
else if (sizeof (long double) == sizeof (double))
|
||||
__asm__("fldl %1\nfstpt %0\n" : "=m" (ptr) : "m" (vtop->c.ld));
|
||||
__asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld));
|
||||
#endif
|
||||
else if (vtop->c.ld == 0.0)
|
||||
;
|
||||
else
|
||||
#endif
|
||||
if (sizeof(long double) == LDOUBLE_SIZE)
|
||||
@ -7019,6 +7017,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
|
||||
vla_runtime_type_size(type, &a);
|
||||
gen_vla_alloc(type, a);
|
||||
#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
|
||||
/* on _WIN64, because of the function args scratch area, the
|
||||
result of alloca differs from RSP and is returned in RAX. */
|
||||
gen_vla_result(addr), addr = (loc -= PTR_SIZE);
|
||||
#endif
|
||||
gen_vla_sp_save(addr);
|
||||
vla_sp_loc = addr;
|
||||
vlas_in_scope++;
|
||||
@ -7337,18 +7340,16 @@ found:
|
||||
type.t |= VT_EXTERN;
|
||||
sym = external_sym(v, &type, r, &ad);
|
||||
if (ad.alias_target) {
|
||||
Section tsec;
|
||||
ElfSym *esym;
|
||||
Sym *alias_target;
|
||||
alias_target = sym_find(ad.alias_target);
|
||||
esym = elfsym(alias_target);
|
||||
if (!esym)
|
||||
tcc_error("unsupported forward __alias__ attribute");
|
||||
tsec.sh_num = esym->st_shndx;
|
||||
/* Local statics have a scope until now (for
|
||||
warnings), remove it here. */
|
||||
sym->sym_scope = 0;
|
||||
put_extern_sym2(sym, &tsec, esym->st_value, esym->st_size, 0);
|
||||
put_extern_sym2(sym, esym->st_shndx, esym->st_value, esym->st_size, 0);
|
||||
}
|
||||
} else {
|
||||
if (type.t & VT_STATIC)
|
||||
|
31
tccpe.c
31
tccpe.c
@ -954,7 +954,7 @@ static void pe_build_exports(struct pe_info *pe)
|
||||
/* automatically write exports to <output-filename>.def */
|
||||
pstrcpy(buf, sizeof buf, pe->filename);
|
||||
strcpy(tcc_fileextension(buf), ".def");
|
||||
op = fopen(buf, "w");
|
||||
op = fopen(buf, "wb");
|
||||
if (NULL == op) {
|
||||
tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
|
||||
} else {
|
||||
@ -967,7 +967,7 @@ static void pe_build_exports(struct pe_info *pe)
|
||||
for (ord = 0; ord < sym_count; ++ord)
|
||||
{
|
||||
p = sorted[ord], sym_index = p->index, name = p->name;
|
||||
/* insert actual address later in pe_relocate_rva */
|
||||
/* insert actual address later in relocate_section() */
|
||||
put_elf_reloc(symtab_section, pe->thunk,
|
||||
func_o, R_XXX_RELATIVE, sym_index);
|
||||
*(DWORD*)(pe->thunk->data + name_o)
|
||||
@ -1181,26 +1181,6 @@ static int pe_assign_addresses (struct pe_info *pe)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
static void pe_relocate_rva (struct pe_info *pe, Section *s)
|
||||
{
|
||||
Section *sr = s->reloc;
|
||||
ElfW_Rel *rel, *rel_end;
|
||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
||||
for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
|
||||
if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) {
|
||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||
DWORD addr = s->sh_addr;
|
||||
if (sym_index) {
|
||||
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
|
||||
addr = sym->st_value;
|
||||
}
|
||||
// printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name);
|
||||
*(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
static int pe_isafunc(int sym_index)
|
||||
@ -1830,7 +1810,7 @@ ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
|
||||
/* put relocations on it */
|
||||
for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
|
||||
put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym);
|
||||
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
|
||||
}
|
||||
#endif
|
||||
/* ------------------------------------------------------------- */
|
||||
@ -1979,11 +1959,11 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||
else if (filename) {
|
||||
pe_assign_addresses(&pe);
|
||||
relocate_syms(s1, s1->symtab, 0);
|
||||
s1->pe_imagebase = pe.imagebase;
|
||||
for (i = 1; i < s1->nb_sections; ++i) {
|
||||
Section *s = s1->sections[i];
|
||||
if (s->reloc) {
|
||||
relocate_section(s1, s);
|
||||
pe_relocate_rva(&pe, s);
|
||||
}
|
||||
}
|
||||
pe.start_addr = (DWORD)
|
||||
@ -1999,6 +1979,9 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||
pe.thunk = data_section;
|
||||
pe_build_imports(&pe);
|
||||
s1->runtime_main = pe.start_symbol;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
s1->uw_pdata = find_section(s1, ".pdata");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
10
tccrun.c
10
tccrun.c
@ -238,6 +238,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
||||
if (0 == mem)
|
||||
return offset + RUN_SECTION_ALIGNMENT;
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
s1->pe_imagebase = mem;
|
||||
#endif
|
||||
|
||||
/* relocate each section */
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
@ -306,11 +310,11 @@ static void *win64_add_function_table(TCCState *s1)
|
||||
RtlAddFunctionTable(
|
||||
(RUNTIME_FUNCTION*)p,
|
||||
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
||||
text_section->sh_addr
|
||||
s1->pe_imagebase
|
||||
);
|
||||
s1->uw_pdata = NULL;
|
||||
}
|
||||
return p;;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void win64_del_function_table(void *p)
|
||||
@ -439,7 +443,7 @@ no_stabs:
|
||||
if (wanted_pc >= sym->st_value &&
|
||||
wanted_pc < sym->st_value + sym->st_size) {
|
||||
pstrcpy(last_func_name, sizeof(last_func_name),
|
||||
(char *) strtab_section->data + sym->st_name);
|
||||
(char *) symtab_section->link->data + sym->st_name);
|
||||
func_addr = sym->st_value;
|
||||
goto found;
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ usage:
|
||||
if (v)
|
||||
printf("-> %s\n", file);
|
||||
|
||||
op = fopen(outfile, "w");
|
||||
op = fopen(outfile, "wb");
|
||||
if (NULL == op) {
|
||||
fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
|
||||
goto the_end;
|
||||
|
@ -51,9 +51,8 @@ ifndef CONFIG_cross
|
||||
TESTS := $(filter-out cross-%,$(TESTS))
|
||||
endif
|
||||
|
||||
ifdef CONFIG_WIN32
|
||||
SEP = $(if $(findstring :\,$(PATH)),;,:)
|
||||
PATH := $(CURDIR)/$(TOP)$(SEP)$(PATH) # for libtcc_test to find libtcc.dll
|
||||
ifeq ($(OS),Windows_NT) # for libtcc_test to find libtcc.dll
|
||||
PATH := $(CURDIR)/$(TOP)$(if $(findstring :\,$(PATH)),;,:)$(PATH)
|
||||
endif
|
||||
|
||||
RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
|
||||
@ -243,8 +242,9 @@ asm-c-connect-sep$(EXESUF): asm-c-connect-1.o asm-c-connect-2.o
|
||||
|
||||
asm-c-connect-test: asm-c-connect$(EXESUF) asm-c-connect-sep$(EXESUF)
|
||||
@echo ------------ $@ ------------
|
||||
./asm-c-connect$(EXESUF)
|
||||
./asm-c-connect-sep$(EXESUF)
|
||||
./asm-c-connect$(EXESUF) > asm-c-connect.out1 && cat asm-c-connect.out1
|
||||
./asm-c-connect-sep$(EXESUF) > asm-c-connect.out2 && cat asm-c-connect.out2
|
||||
@diff -u asm-c-connect.out1 asm-c-connect.out2 && echo "ok"
|
||||
|
||||
cross-test :
|
||||
@echo ------------ $@ ------------
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
static int x1_c(void)
|
||||
{
|
||||
printf("x1\n");
|
||||
printf(" x1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -16,21 +16,30 @@ asm(".text;"_"x1: call "_"x1_c; ret");
|
||||
|
||||
void callx4(void);
|
||||
void callx5_again(void);
|
||||
|
||||
void x6()
|
||||
{
|
||||
printf(" x6-1");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("*");
|
||||
asm("call "_"x1");
|
||||
asm("call "_"x2");
|
||||
asm("call "_"x3");
|
||||
callx4();
|
||||
asm("call "_"x5");
|
||||
callx5_again();
|
||||
x6();
|
||||
printf(" *\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int x2(void)
|
||||
{
|
||||
printf("x2\n");
|
||||
printf(" x2");
|
||||
return 2;
|
||||
}
|
||||
|
||||
@ -38,11 +47,11 @@ extern int x3(void);
|
||||
|
||||
void x4(void)
|
||||
{
|
||||
printf("x4\n");
|
||||
printf(" x4");
|
||||
}
|
||||
|
||||
void x5(void);
|
||||
void x5(void)
|
||||
{
|
||||
printf("x5\n");
|
||||
printf(" x5");
|
||||
}
|
||||
|
@ -1,19 +1,36 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined _WIN32 && !defined __TINYC__
|
||||
# define _ "_"
|
||||
#else
|
||||
# define _
|
||||
#endif
|
||||
|
||||
int x3(void)
|
||||
{
|
||||
printf("x3\n");
|
||||
printf(" x3");
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* That callx4 is defined globally (as if ".globl callx4")
|
||||
is a TCC extension. GCC doesn't behave like this. */
|
||||
void callx4(void);
|
||||
__asm__("callx4: call x4; ret");
|
||||
__asm__(_"callx4: call "_"x4; ret;"
|
||||
#ifndef __TINYC__
|
||||
" .global "_"callx4"
|
||||
#endif
|
||||
);
|
||||
|
||||
extern void x5(void);
|
||||
|
||||
void callx5_again(void);
|
||||
void callx5_again(void)
|
||||
{
|
||||
x5();
|
||||
asm("call "_"x6");
|
||||
}
|
||||
|
||||
static void x6()
|
||||
{
|
||||
printf(" x6-2");
|
||||
}
|
||||
|
@ -3370,6 +3370,37 @@ void test_asm_call(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined __x86_64__
|
||||
# define RX "(%rip)"
|
||||
#else
|
||||
# define RX
|
||||
#endif
|
||||
|
||||
void asm_dot_test(void)
|
||||
{
|
||||
int x;
|
||||
for (x = 1;; ++x) {
|
||||
int r = x;
|
||||
switch (x) {
|
||||
case 1:
|
||||
asm(".text; lea S"RX",%eax; lea ."RX",%ecx; sub %ecx,%eax; S=.; jmp p0");
|
||||
case 2:
|
||||
asm(".text; jmp .+6; .int 123; mov .-4"RX",%eax; jmp p0");
|
||||
case 3:
|
||||
asm(".data; Y=.; .int 999; X=Y; .int 456; X=.-4");
|
||||
asm(".text; mov X"RX",%eax; jmp p0");
|
||||
case 4:
|
||||
asm(".data; X=.; .int 789; Y=.; .int 999");
|
||||
asm(".text; mov X"RX",%eax; X=Y; jmp p0");
|
||||
case 0:
|
||||
asm(".text; p0=.; mov %%eax,%0;" : "=m"(r)); break;
|
||||
}
|
||||
if (r == x)
|
||||
break;
|
||||
printf("asm_dot_test %d: %d\n", x, r);
|
||||
}
|
||||
}
|
||||
|
||||
void asm_test(void)
|
||||
{
|
||||
char buf[128];
|
||||
@ -3457,6 +3488,7 @@ void asm_test(void)
|
||||
trace_console(8, 8);
|
||||
test_asm_dead_code();
|
||||
test_asm_call();
|
||||
asm_dot_test();
|
||||
return;
|
||||
label1:
|
||||
goto label2;
|
||||
|
@ -1034,6 +1034,7 @@ void gfunc_epilog(void)
|
||||
saved_ind = ind;
|
||||
ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
|
||||
/* align local size to word & save local variables */
|
||||
func_scratch = (func_scratch + 15) & -16;
|
||||
v = (func_scratch + -loc + 15) & -16;
|
||||
|
||||
if (v >= 4096) {
|
||||
@ -2222,6 +2223,14 @@ ST_FUNC void gen_vla_sp_restore(int addr) {
|
||||
gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
/* Save result of gen_vla_alloc onto the stack */
|
||||
ST_FUNC void gen_vla_result(int addr) {
|
||||
/* mov %rax,addr(%rbp)*/
|
||||
gen_modrm64(0x89, TREG_RAX, VT_LOCAL, NULL, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Subtract from the stack pointer, and push the resulting value onto the stack */
|
||||
ST_FUNC void gen_vla_alloc(CType *type, int align) {
|
||||
#ifdef TCC_TARGET_PE
|
||||
|
@ -287,6 +287,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||
add64le(ptr, val - s1->got->sh_addr);
|
||||
break;
|
||||
case R_X86_64_RELATIVE:
|
||||
#ifdef TCC_TARGET_PE
|
||||
add32le(ptr, val - s1->pe_imagebase);
|
||||
#endif
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user