forked from Mirrors/tinycc
tccrun: win64: add unwind function table for dynamic code
This works only when tcc.exe is compiled using MSC. MinGW does something in the startup code that defeats it.master
parent
232650f8b3
commit
df4c0892f3
9
tcc.h
9
tcc.h
|
@ -566,10 +566,11 @@ struct TCCState {
|
|||
int pe_subsystem;
|
||||
unsigned long pe_file_align;
|
||||
unsigned long pe_stack_size;
|
||||
struct pe_uw {
|
||||
Section *pdata;
|
||||
int sym_1, sym_2, offs_1;
|
||||
} pe_unwind;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
Section *uw_pdata;
|
||||
int uw_sym;
|
||||
unsigned uw_offs;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TCC_TARGET_PE
|
||||
|
|
93
tccpe.c
93
tccpe.c
|
@ -1694,54 +1694,65 @@ ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname)
|
|||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
static unsigned pe_add_uwwind_info(TCCState *s1)
|
||||
{
|
||||
static const char uw_info[] = {
|
||||
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
|
||||
0x04, // UBYTE Size of prolog
|
||||
0x02, // UBYTE Count of unwind codes
|
||||
0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
|
||||
// USHORT * n Unwind codes array
|
||||
// 0x0b, 0x01, 0xff, 0xff, // stack size
|
||||
0x04, 0x03, // set frame ptr (mov rsp -> rbp)
|
||||
0x01, 0x50 // push reg (rbp)
|
||||
};
|
||||
|
||||
struct pe_uw *pe_uw = &tcc_state->pe_unwind;
|
||||
|
||||
Section *uw, *pd;
|
||||
WORD *p1;
|
||||
DWORD *p2;
|
||||
unsigned o2;
|
||||
|
||||
uw = data_section;
|
||||
pd = pe_uw->pdata;
|
||||
if (NULL == pd)
|
||||
{
|
||||
pe_uw->pdata = pd = find_section(tcc_state, ".pdata");
|
||||
pe_uw->pdata->sh_addralign = 4;
|
||||
section_ptr_add(uw, -uw->data_offset & 3);
|
||||
pe_uw->offs_1 = uw->data_offset;
|
||||
p1 = section_ptr_add(uw, sizeof uw_info);
|
||||
/* use one common entry for all functions */
|
||||
memcpy(p1, uw_info, sizeof uw_info);
|
||||
pe_uw->sym_1 = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
|
||||
pe_uw->sym_2 = put_elf_sym(symtab_section, 0, 0, 0, 0, uw->sh_num, NULL);
|
||||
if (NULL == s1->uw_pdata) {
|
||||
s1->uw_pdata = find_section(tcc_state, ".pdata");
|
||||
s1->uw_pdata->sh_addralign = 4;
|
||||
s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
|
||||
}
|
||||
|
||||
o2 = pd->data_offset;
|
||||
p2 = section_ptr_add(pd, 3 * sizeof (DWORD));
|
||||
if (0 == s1->uw_offs) {
|
||||
/* As our functions all have the same stackframe, we use one entry for all */
|
||||
static const unsigned char uw_info[] = {
|
||||
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
|
||||
0x04, // UBYTE Size of prolog
|
||||
0x02, // UBYTE Count of unwind codes
|
||||
0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
|
||||
// USHORT * n Unwind codes array
|
||||
// 0x0b, 0x01, 0xff, 0xff, // stack size
|
||||
0x04, 0x03, // set frame ptr (mov rsp -> rbp)
|
||||
0x01, 0x50 // push reg (rbp)
|
||||
};
|
||||
|
||||
Section *s = text_section;
|
||||
unsigned char *p;
|
||||
|
||||
section_ptr_add(s, -s->data_offset & 3); /* align */
|
||||
s1->uw_offs = s->data_offset;
|
||||
p = section_ptr_add(s, sizeof uw_info);
|
||||
memcpy(p, uw_info, sizeof uw_info);
|
||||
}
|
||||
|
||||
return s1->uw_offs;
|
||||
}
|
||||
|
||||
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
Section *pd;
|
||||
unsigned o, n, d;
|
||||
struct /* _RUNTIME_FUNCTION */ {
|
||||
DWORD BeginAddress;
|
||||
DWORD EndAddress;
|
||||
DWORD UnwindData;
|
||||
} *p;
|
||||
|
||||
d = pe_add_uwwind_info(s1);
|
||||
pd = s1->uw_pdata;
|
||||
o = pd->data_offset;
|
||||
p = section_ptr_add(pd, sizeof *p);
|
||||
|
||||
/* record this function */
|
||||
p2[0] = start;
|
||||
p2[1] = end;
|
||||
p2[2] = pe_uw->offs_1;
|
||||
p->BeginAddress = start;
|
||||
p->EndAddress = end;
|
||||
p->UnwindData = d;
|
||||
|
||||
/* put relocations on it */
|
||||
put_elf_reloc(symtab_section, pd, o2, R_X86_64_RELATIVE, pe_uw->sym_1);
|
||||
put_elf_reloc(symtab_section, pd, o2+4, R_X86_64_RELATIVE, pe_uw->sym_1);
|
||||
put_elf_reloc(symtab_section, pd, o2+8, R_X86_64_RELATIVE, pe_uw->sym_2);
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#define PE_STDSYM(n,s) n
|
||||
|
|
19
tccrun.c
19
tccrun.c
|
@ -30,6 +30,10 @@ static int rt_get_caller_pc(uplong *paddr, ucontext_t *uc, int level);
|
|||
static void rt_error(ucontext_t *uc, const char *fmt, ...);
|
||||
static int tcc_relocate_ex(TCCState *s1, void *ptr);
|
||||
|
||||
#ifdef _WIN64
|
||||
static void win64_add_function_table(TCCState *s1);
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
/* Do all relocations (needed before using tcc_get_symbol())
|
||||
Returns -1 on error. */
|
||||
|
@ -189,6 +193,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr)
|
|||
set_pages_executable(s1->runtime_plt_and_got,
|
||||
s1->runtime_plt_and_got_offset);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
win64_add_function_table(s1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -578,6 +586,17 @@ static void set_exception_handler(void)
|
|||
SetUnhandledExceptionFilter(cpu_exception_handler);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void win64_add_function_table(TCCState *s1)
|
||||
{
|
||||
RtlAddFunctionTable(
|
||||
(RUNTIME_FUNCTION*)(uplong)s1->uw_pdata->sh_addr,
|
||||
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
|
||||
(uplong)text_section->sh_addr
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#define Eip Rip
|
||||
#define Ebp Rbp
|
||||
|
|
|
@ -57,17 +57,9 @@ P0:
|
|||
/* ---------------------------------------------- */
|
||||
/* setjmp/longjmp support */
|
||||
|
||||
.globl tinyc_no_getbp
|
||||
tinyc_no_getbp:
|
||||
.byte 0x90
|
||||
|
||||
.globl tinyc_getbp
|
||||
tinyc_getbp:
|
||||
xor %rax,%rax
|
||||
cmp %al,tinyc_no_getbp(%rax)
|
||||
je t1
|
||||
mov %rbp,%rax
|
||||
t1:
|
||||
ret
|
||||
|
||||
/* ---------------------------------------------- */
|
||||
|
|
|
@ -549,7 +549,9 @@ ResetEvent
|
|||
ResetNLSUserInfoCache
|
||||
ResetWriteWatch
|
||||
ResumeThread
|
||||
RtlAddFunctionTable
|
||||
RtlFillMemory
|
||||
RtlInstallFunctionTableCallback
|
||||
RtlMoveMemory
|
||||
RtlUnwind
|
||||
RtlZeroMemory
|
||||
|
|
|
@ -772,8 +772,6 @@ void gfunc_epilog(void)
|
|||
/* align local size to word & save local variables */
|
||||
v = (func_scratch + -loc + 15) & -16;
|
||||
|
||||
pe_add_unwind_data(ind, saved_ind, v);
|
||||
|
||||
if (v >= 4096) {
|
||||
Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
|
||||
oad(0xb8, v); /* mov stacksize, %eax */
|
||||
|
@ -785,7 +783,10 @@ void gfunc_epilog(void)
|
|||
o(0xec8148); /* sub rsp, stacksize */
|
||||
gen_le32(v);
|
||||
}
|
||||
ind = saved_ind;
|
||||
|
||||
cur_text_section->data_offset = saved_ind;
|
||||
pe_add_unwind_data(ind, saved_ind, v);
|
||||
ind = cur_text_section->data_offset;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
Loading…
Reference in New Issue