History

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.

grischka committed 15 years ago

Commit df4c0891 parent 232650f6 files · +79 −53Browse files

Unified · Split

6 files
  1. tcc.h +5 −4
  2. tccpe.c +49 −38
  3. tccrun.c +19 −0
  4. win32/lib/chkstk.S +0 −8
  5. win32/lib/kernel32.def +2 −0
  6. x86_64-gen.c +4 −3
tcc.h+5−4
@@ -566,10 +566,11 @@ struct TCCState { · 565 unmodified lines
566 int pe_subsystem;566 int pe_subsystem;
567 unsigned long pe_file_align;567 unsigned long pe_file_align;
568 unsigned long pe_stack_size;568 unsigned long pe_stack_size;
569 struct pe_uw {569#ifdef TCC_TARGET_X86_64
570 Section *pdata;570 Section *uw_pdata;
571 int sym_1, sym_2, offs_1;571 int uw_sym;
572 } pe_unwind;572 unsigned uw_offs;
573#endif
573#endif574#endif
574 575
575#ifndef TCC_TARGET_PE576#ifndef TCC_TARGET_PE
tccpe.c+49−38
@@ -1694,54 +1694,65 @@ ST_FUNC int pe_add_dll(struct TCCState *s, const char *libname) · 1693 unmodified lines
1694 1694
1695/* ------------------------------------------------------------- */1695/* ------------------------------------------------------------- */
1696#ifdef TCC_TARGET_X86_641696#ifdef TCC_TARGET_X86_64
1697ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)1697static unsigned pe_add_uwwind_info(TCCState *s1)
1698{1698{
1699 static const char uw_info[] = {1699 if (NULL == s1->uw_pdata) {
1700 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags1700 s1->uw_pdata = find_section(tcc_state, ".pdata");
1701 0x04, // UBYTE Size of prolog1701 s1->uw_pdata->sh_addralign = 4;
1702 0x02, // UBYTE Count of unwind codes1702 s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
1703 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)1703 }
1704 // USHORT * n Unwind codes array
1705 // 0x0b, 0x01, 0xff, 0xff, // stack size
1706 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
1707 0x01, 0x50 // push reg (rbp)
1708 };
1709 1704
1710 struct pe_uw *pe_uw = &tcc_state->pe_unwind;1705 if (0 == s1->uw_offs) {
1706 /* As our functions all have the same stackframe, we use one entry for all */
1707 static const unsigned char uw_info[] = {
1708 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
1709 0x04, // UBYTE Size of prolog
1710 0x02, // UBYTE Count of unwind codes
1711 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
1712 // USHORT * n Unwind codes array
1713 // 0x0b, 0x01, 0xff, 0xff, // stack size
1714 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
1715 0x01, 0x50 // push reg (rbp)
1716 };
1711 1717
1712 Section *uw, *pd;1718 Section *s = text_section;
1713 WORD *p1;1719 unsigned char *p;
1714 DWORD *p2;
1715 unsigned o2;
1716 1720
1717 uw = data_section;1721 section_ptr_add(s, -s->data_offset & 3); /* align */
1718 pd = pe_uw->pdata;1722 s1->uw_offs = s->data_offset;
1719 if (NULL == pd)1723 p = section_ptr_add(s, sizeof uw_info);
1720 {1724 memcpy(p, uw_info, sizeof uw_info);
1721 pe_uw->pdata = pd = find_section(tcc_state, ".pdata");
1722 pe_uw->pdata->sh_addralign = 4;
1723 section_ptr_add(uw, -uw->data_offset & 3);
1724 pe_uw->offs_1 = uw->data_offset;
1725 p1 = section_ptr_add(uw, sizeof uw_info);
1726 /* use one common entry for all functions */
1727 memcpy(p1, uw_info, sizeof uw_info);
1728 pe_uw->sym_1 = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
1729 pe_uw->sym_2 = put_elf_sym(symtab_section, 0, 0, 0, 0, uw->sh_num, NULL);
1730 }1725 }
1731 1726
1732 o2 = pd->data_offset;1727 return s1->uw_offs;
1733 p2 = section_ptr_add(pd, 3 * sizeof (DWORD));1728}
1729
1730ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
1731{
1732 TCCState *s1 = tcc_state;
1733 Section *pd;
1734 unsigned o, n, d;
1735 struct /* _RUNTIME_FUNCTION */ {
1736 DWORD BeginAddress;
1737 DWORD EndAddress;
1738 DWORD UnwindData;
1739 } *p;
1740
1741 d = pe_add_uwwind_info(s1);
1742 pd = s1->uw_pdata;
1743 o = pd->data_offset;
1744 p = section_ptr_add(pd, sizeof *p);
1745
1734 /* record this function */1746 /* record this function */
1735 p2[0] = start;1747 p->BeginAddress = start;
1736 p2[1] = end;1748 p->EndAddress = end;
1737 p2[2] = pe_uw->offs_1;1749 p->UnwindData = d;
1750
1738 /* put relocations on it */1751 /* put relocations on it */
1739 put_elf_reloc(symtab_section, pd, o2, R_X86_64_RELATIVE, pe_uw->sym_1);1752 for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
1740 put_elf_reloc(symtab_section, pd, o2+4, R_X86_64_RELATIVE, pe_uw->sym_1);1753 put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym);
1741 put_elf_reloc(symtab_section, pd, o2+8, R_X86_64_RELATIVE, pe_uw->sym_2);
1742}1754}
1743#endif1755#endif
1744
1745/* ------------------------------------------------------------- */1756/* ------------------------------------------------------------- */
1746#ifdef TCC_TARGET_X86_641757#ifdef TCC_TARGET_X86_64
1747#define PE_STDSYM(n,s) n1758#define PE_STDSYM(n,s) n
tccrun.c+19−0
@@ -30,6 +30,10 @@ static int rt_get_caller_pc(uplong *paddr, ucontext_t *uc, int level); · 29 unmodified lines
30static void rt_error(ucontext_t *uc, const char *fmt, ...);30static void rt_error(ucontext_t *uc, const char *fmt, ...);
31static int tcc_relocate_ex(TCCState *s1, void *ptr);31static int tcc_relocate_ex(TCCState *s1, void *ptr);
32 32
33#ifdef _WIN64
34static void win64_add_function_table(TCCState *s1);
35#endif
36
33/* ------------------------------------------------------------- */37/* ------------------------------------------------------------- */
34/* Do all relocations (needed before using tcc_get_symbol())38/* Do all relocations (needed before using tcc_get_symbol())
35 Returns -1 on error. */39 Returns -1 on error. */
@@ -189,6 +193,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) · 153 unmodified lines
189 set_pages_executable(s1->runtime_plt_and_got,193 set_pages_executable(s1->runtime_plt_and_got,
190 s1->runtime_plt_and_got_offset);194 s1->runtime_plt_and_got_offset);
191#endif195#endif
196
197#ifdef _WIN64
198 win64_add_function_table(s1);
199#endif
192 return 0;200 return 0;
193}201}
194 202
@@ -578,6 +586,17 @@ static void set_exception_handler(void) · 383 unmodified lines
578 SetUnhandledExceptionFilter(cpu_exception_handler);586 SetUnhandledExceptionFilter(cpu_exception_handler);
579}587}
580 588
589#ifdef _WIN64
590static void win64_add_function_table(TCCState *s1)
591{
592 RtlAddFunctionTable(
593 (RUNTIME_FUNCTION*)(uplong)s1->uw_pdata->sh_addr,
594 s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
595 (uplong)text_section->sh_addr
596 );
597}
598#endif
599
581#ifdef _WIN64600#ifdef _WIN64
582#define Eip Rip601#define Eip Rip
583#define Ebp Rbp602#define Ebp Rbp
win32/lib/chkstk.S+0−8
@@ -57,17 +57,9 @@ P0: · 56 unmodified lines
57/* ---------------------------------------------- */57/* ---------------------------------------------- */
58/* setjmp/longjmp support */58/* setjmp/longjmp support */
59 59
60.globl tinyc_no_getbp
61tinyc_no_getbp:
62 .byte 0x90
63
64.globl tinyc_getbp60.globl tinyc_getbp
65tinyc_getbp:61tinyc_getbp:
66 xor %rax,%rax
67 cmp %al,tinyc_no_getbp(%rax)
68 je t1
69 mov %rbp,%rax62 mov %rbp,%rax
70t1:
71 ret63 ret
72 64
73/* ---------------------------------------------- */65/* ---------------------------------------------- */
win32/lib/kernel32.def+2−0
@@ -549,7 +549,9 @@ ResetEvent · 548 unmodified lines
549ResetNLSUserInfoCache549ResetNLSUserInfoCache
550ResetWriteWatch550ResetWriteWatch
551ResumeThread551ResumeThread
552RtlAddFunctionTable
552RtlFillMemory553RtlFillMemory
554RtlInstallFunctionTableCallback
553RtlMoveMemory555RtlMoveMemory
554RtlUnwind556RtlUnwind
555RtlZeroMemory557RtlZeroMemory
x86_64-gen.c+4−3
@@ -772,8 +772,6 @@ void gfunc_epilog(void) · 771 unmodified lines
772 /* align local size to word & save local variables */772 /* align local size to word & save local variables */
773 v = (func_scratch + -loc + 15) & -16;773 v = (func_scratch + -loc + 15) & -16;
774 774
775 pe_add_unwind_data(ind, saved_ind, v);
776
777 if (v >= 4096) {775 if (v >= 4096) {
778 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);776 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
779 oad(0xb8, v); /* mov stacksize, %eax */777 oad(0xb8, v); /* mov stacksize, %eax */
@@ -785,7 +783,10 @@ void gfunc_epilog(void) · 5 unmodified lines
785 o(0xec8148); /* sub rsp, stacksize */783 o(0xec8148); /* sub rsp, stacksize */
786 gen_le32(v);784 gen_le32(v);
787 }785 }
788 ind = saved_ind;786
787 cur_text_section->data_offset = saved_ind;
788 pe_add_unwind_data(ind, saved_ind, v);
789 ind = cur_text_section->data_offset;
789}790}
790 791
791#else792#else

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t