win64: fix pe_isafunc()

- tccpe.c: commit "tidy support for helper function" created
  STT_NOTYPE symbols and hence relied on ad-hoc detection which
  didn't work for x86_64 (as reported by Christian Jullien)

- tccgen.c: However to be more safe the helper symbols are
  now made STT_FUNC anyway (via new VT_ASM_FUNC).

Also:
- tcc.h: minor reorder
- riscv64-*, arm64-*, tccmacho.c: avoid some gcc format-warnings
  (mingw-gcc complains about "%llx" being "unknown conversion",
  although it does work since Vista or so)
This commit is contained in:
grischka 2020-11-25 11:23:01 +01:00
parent 13a18906ef
commit cf8d9cf072
9 changed files with 66 additions and 49 deletions

View File

@ -138,7 +138,7 @@ DEF-i386-win32 = -DTCC_TARGET_PE -DTCC_TARGET_I386
DEF-x86_64-win32= -DTCC_TARGET_PE -DTCC_TARGET_X86_64
DEF-x86_64-osx = -DTCC_TARGET_MACHO -DTCC_TARGET_X86_64
DEF-arm-wince = -DTCC_TARGET_PE -DTCC_TARGET_ARM -DTCC_ARM_EABI -DTCC_ARM_VFP -DTCC_ARM_HARDFLOAT
DEF-arm64 = -DTCC_TARGET_ARM64 -Wno-format
DEF-arm64 = -DTCC_TARGET_ARM64
DEF-c67 = -DTCC_TARGET_C67 -w # disable warnigs
DEF-arm-fpa = -DTCC_TARGET_ARM
DEF-arm-fpa-ld = -DTCC_TARGET_ARM -DLDOUBLE_SIZE=12

View File

@ -587,7 +587,7 @@ ST_FUNC void load(int r, SValue *sv)
return;
}
printf("load(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul);
printf("load(%x, (%x, %x, %lx))\n", r, svtt, sv->r, (long)svcul);
assert(0);
}
@ -639,7 +639,7 @@ ST_FUNC void store(int r, SValue *sv)
return;
}
printf("store(%x, (%x, %x, %llx))\n", r, svtt, sv->r, (long long)svcul);
printf("store(%x, (%x, %x, %lx))\n", r, svtt, sv->r, (long)svcul);
assert(0);
}

View File

@ -116,7 +116,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t got = s1->got->sh_addr;
uint64_t off = (got >> 12) - (plt >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
write32le(p + 4, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
@ -134,7 +134,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t addr = got + read64le(p);
uint64_t off = (addr >> 12) - (pc >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
@ -239,7 +239,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
#endif
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed"
" (val=%lx, addr=%lx)", val, addr);
" (val=%lx, addr=%lx)", (long)val, (long)addr);
write32le(ptr, (0x14000000 |
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
((val - addr) >> 2 & 0x3ffffff)));

View File

@ -166,7 +166,7 @@ static int load_symofs(int r, SValue *sv, int forstore)
sv->c.i = 0;
} else {
if (((unsigned)fc + (1 << 11)) >> 12)
tcc_error("unimp: large addend for global address (0x%llx)", (long long)sv->c.i);
tcc_error("unimp: large addend for global address (0x%lx)", (long)sv->c.i);
greloca(cur_text_section, sv->sym, ind,
R_RISCV_GOT_HI20, 0);
doload = 1;
@ -188,7 +188,7 @@ static int load_symofs(int r, SValue *sv, int forstore)
} else if (v == VT_LOCAL || v == VT_LLOCAL) {
rr = 8; // s0
if (fc != sv->c.i)
tcc_error("unimp: store(giant local off) (0x%llx)", (long long)sv->c.i);
tcc_error("unimp: store(giant local off) (0x%lx)", (long)sv->c.i);
if (((unsigned)fc + (1 << 11)) >> 12) {
rr = is_ireg(r) ? ireg(r) : 5; // t0
o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)); //lui RR, upper(fc)

View File

@ -127,7 +127,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t got = s1->got->sh_addr;
uint64_t off = (got - plt + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
@ -144,7 +144,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
uint64_t addr = got + read64le(p);
uint64_t off = (addr - pc + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
| (((addr - pc) & 0xfff) << 20));
@ -177,7 +177,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
off64 = val - addr;
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
tcc_error("R_RISCV_BRANCH relocation failed"
" (val=%lx, addr=%lx)", val, addr);
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64 >> 1;
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
| ((off32 & 0x800) << 20)
@ -189,7 +189,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
off64 = val - addr;
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
tcc_error("R_RISCV_JAL relocation failed"
" (val=%lx, addr=%lx)", val, addr);
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write32le(ptr, (read32le(ptr) & 0xfff)
| (((off32 >> 12) & 0xff) << 12)
@ -206,12 +206,12 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
return;
case R_RISCV_PCREL_HI20:
#ifdef DEBUG_RELOC
printf("PCREL_HI20: val=%lx addr=%lx\n", val, addr);
printf("PCREL_HI20: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif
off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
off64, ((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
symtab_section->link->data + sym->st_name);
write32le(ptr, (read32le(ptr) & 0xfff)
| ((off64 & 0xfffff) << 12));
@ -230,7 +230,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
return;
case R_RISCV_PCREL_LO12_I:
#ifdef DEBUG_RELOC
printf("PCREL_LO12_I: val=%lx addr=%lx\n", val, addr);
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif
if (val != last_hi.addr)
tcc_error("unsupported hi/lo pcrel reloc scheme");
@ -254,7 +254,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
off64 = (val - addr);
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", val, addr);
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe383)
| (((off32 >> 5) & 1) << 2)
@ -267,7 +267,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
off64 = (val - addr);
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", val, addr);
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe003)
| (((off32 >> 5) & 1) << 2)

43
tcc.h
View File

@ -1011,7 +1011,8 @@ struct filespec {
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
/* symbol was created by tccasm.c first */
#define VT_ASM (VT_VOID | VT_UNSIGNED)
#define VT_ASM (VT_VOID | 1 << VT_STRUCT_SHIFT)
#define VT_ASM_FUNC (VT_ASM | 2 << VT_STRUCT_SHIFT)
#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
/* general: set/get the pseudo-bitfield value for bit-mask M */
@ -1251,15 +1252,6 @@ ST_FUNC void cstr_free(CString *cstr);
ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
ST_FUNC void cstr_reset(CString *cstr);
ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
ST_FUNC Sym *sym_find2(Sym *s, int v);
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_INLN Sym *struct_find(int v);
ST_INLN Sym *sym_find(int v);
ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
ST_FUNC void tcc_close(void);
@ -1433,25 +1425,44 @@ ST_INLN int is_float(int t);
ST_FUNC int ieee_finite(double d);
ST_FUNC int exact_log2p1(int i);
ST_FUNC void test_lvalue(void);
ST_FUNC void vpushi(int v);
ST_FUNC ElfSym *elfsym(Sym *);
ST_FUNC void update_storage(Sym *sym);
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);
#endif
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
ST_FUNC Sym *sym_find2(Sym *s, int v);
ST_INLN Sym *sym_find(int v);
ST_INLN Sym *struct_find(int v);
ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC Sym *external_global_sym(int v, CType *type);
ST_FUNC Sym *external_helper_sym(int v);
ST_FUNC void vpush_helper_func(int v);
ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vset_VT_CMP(int op);
ST_FUNC void vpushi(int v);
ST_FUNC void vpushv(SValue *v);
ST_FUNC void vpushsym(CType *type, Sym *sym);
ST_FUNC void vswap(void);
ST_FUNC void vrote(SValue *e, int n);
ST_FUNC void vrott(int n);
ST_FUNC void vrotb(int n);
ST_FUNC void vpop(void);
#if PTR_SIZE == 4
ST_FUNC void lexpand(void);
#endif
#ifdef TCC_TARGET_ARM
ST_FUNC int get_reg_ex(int rc, int rc2);
#endif
ST_FUNC void vpushv(SValue *v);
ST_FUNC void save_reg(int r);
ST_FUNC void save_reg_upstack(int r, int n);
ST_FUNC int get_reg(int rc);
@ -1459,7 +1470,6 @@ ST_FUNC void save_regs(int n);
ST_FUNC void gaddrof(void);
ST_FUNC int gv(int rc);
ST_FUNC void gv2(int rc1, int rc2);
ST_FUNC void vpop(void);
ST_FUNC void gen_op(int op);
ST_FUNC int type_size(CType *type, int *a);
ST_FUNC void mk_pointer(CType *type);
@ -1513,13 +1523,6 @@ ST_FUNC void *section_ptr_add(Section *sec, addr_t 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, 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);
#endif
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
ST_FUNC int put_elf_str(Section *s, const char *sym);
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);

View File

@ -921,6 +921,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
sym_type = STT_FUNC;
} else if ((t & VT_BTYPE) == VT_VOID) {
sym_type = STT_NOTYPE;
if ((t & (VT_BTYPE|VT_ASM_FUNC)) == VT_ASM_FUNC)
sym_type = STT_FUNC;
} else {
sym_type = STT_OBJECT;
}
@ -1440,7 +1442,7 @@ static void gen_test_zero(int op)
/* ------------------------------------------------------------------------- */
/* push a symbol value of TYPE */
static inline void vpushsym(CType *type, Sym *sym)
ST_FUNC void vpushsym(CType *type, Sym *sym)
{
CValue cval;
cval.i = 0;
@ -1489,7 +1491,7 @@ ST_FUNC Sym *external_global_sym(int v, CType *type)
This avoids type conflicts if the symbol is used from C too */
ST_FUNC Sym *external_helper_sym(int v)
{
CType ct = { VT_ASM, NULL };
CType ct = { VT_ASM_FUNC, NULL };
return external_global_sym(v, &ct);
}

View File

@ -384,8 +384,8 @@ static int check_symbols(TCCState *s1, struct macho *mo)
unsigned bind = ELFW(ST_BIND)(sym->st_info);
unsigned vis = ELFW(ST_VISIBILITY)(sym->st_other);
dprintf("%4d (%4d): %09llx %4d %4d %4d %3d %s\n",
sym_index, elf_index, sym->st_value,
dprintf("%4d (%4d): %09lx %4d %4d %4d %3d %s\n",
sym_index, elf_index, (long)sym->st_value,
type, bind, vis, sym->st_shndx, name);
if (bind == STB_LOCAL) {
if (mo->ilocal == -1)
@ -680,14 +680,14 @@ static void collect_sections(TCCState *s1, struct macho *mo)
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
al = s->sh_addralign;
curaddr = (curaddr + al - 1) & -al;
dprintf("curaddr now 0x%llx\n", curaddr);
dprintf("curaddr now 0x%lx\n", (long)curaddr);
s->sh_addr = curaddr;
curaddr += s->sh_size;
if (s->sh_type != SHT_NOBITS) {
fileofs = (fileofs + al - 1) & -al;
s->sh_offset = fileofs;
fileofs += s->sh_size;
dprintf("fileofs now %lld\n", fileofs);
dprintf("fileofs now %ld\n", (long)fileofs);
}
if (sec)
mo->elfsectomacho[s->sh_num] = numsec;
@ -699,7 +699,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
int type = s->sh_type;
int flags = s->sh_flags;
printf("%d section %-16s %-10s %09llx %04x %02d %s,%s,%s\n",
printf("%d section %-16s %-10s %09lx %04x %02d %s,%s,%s\n",
sk,
s->name,
type == SHT_PROGBITS ? "progbits" :
@ -709,7 +709,7 @@ static void collect_sections(TCCState *s1, struct macho *mo)
type == SHT_INIT_ARRAY ? "init" :
type == SHT_FINI_ARRAY ? "fini" :
type == SHT_RELX ? "rel" : "???",
s->sh_addr,
(long)s->sh_addr,
(unsigned)s->data_offset,
s->sh_addralign,
flags & SHF_ALLOC ? "alloc" : "",
@ -966,8 +966,8 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev)
//for (i = 0; i < nsyms; i++) {
for (i = iextdef; i < iextdef + nextdef; i++) {
struct nlist_64 *sym = symtab + i;
dprintf("%5d: %3d %3d 0x%04x 0x%016llx %s\n",
i, sym->n_type, sym->n_sect, sym->n_desc, sym->n_value,
dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n",
i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value,
strtab + sym->n_strx);
set_elf_sym(s1->dynsymtab_section, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),

16
tccpe.c
View File

@ -35,6 +35,7 @@
# define REL_TYPE_DIRECT R_X86_64_64
# define R_XXX_THUNKFIX R_X86_64_PC32
# define R_XXX_RELATIVE R_X86_64_RELATIVE
# define R_XXX_FUNCCALL R_X86_64_PC32
# define IMAGE_FILE_MACHINE 0x8664
# define RSRC_RELTYPE 3
@ -44,6 +45,8 @@
# define REL_TYPE_DIRECT R_ARM_ABS32
# define R_XXX_THUNKFIX R_ARM_ABS32
# define R_XXX_RELATIVE R_ARM_RELATIVE
# define R_XXX_FUNCCALL R_ARM_PC24
# define R_XXX_FUNCCALL2 R_ARM_ABS32
# define IMAGE_FILE_MACHINE 0x01C0
# define RSRC_RELTYPE 7 /* ??? (not tested) */
@ -53,6 +56,7 @@
# define REL_TYPE_DIRECT R_386_32
# define R_XXX_THUNKFIX R_386_32
# define R_XXX_RELATIVE R_386_RELATIVE
# define R_XXX_FUNCCALL R_386_PC32
# define IMAGE_FILE_MACHINE 0x014C
# define RSRC_RELTYPE 7 /* DIR32NB */
@ -1217,13 +1221,21 @@ static int pe_isafunc(TCCState *s1, int sym_index)
{
Section *sr = text_section->reloc;
ElfW_Rel *rel, *rel_end;
Elf32_Word info = ELF32_R_INFO(sym_index, R_386_PC32);
ElfW(Addr)info = ELFW(R_INFO)(sym_index, R_XXX_FUNCCALL);
#ifdef R_XXX_FUNCCALL2
ElfW(Addr)info2 = ELFW(R_INFO)(sym_index, R_XXX_FUNCCALL2);
#endif
if (!sr)
return 0;
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
for (rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++)
for (rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
if (rel->r_info == info)
return 1;
#ifdef R_XXX_FUNCCALL2
if (rel->r_info == info2)
return 1;
#endif
}
return 0;
}