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
566566 int pe_subsystem;
567567 unsigned long pe_file_align;
568568 unsigned long pe_stack_size;
569− struct pe_uw {
570− Section *pdata;
571− int sym_1, sym_2, offs_1;
572− } pe_unwind;
569+#ifdef TCC_TARGET_X86_64
570+ Section *uw_pdata;
571+ int uw_sym;
572+ unsigned uw_offs;
573+#endif
573574 #endif
574575
575576 #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
16941694
16951695 /* ------------------------------------------------------------- */
16961696 #ifdef TCC_TARGET_X86_64
1697−ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
1697+static unsigned pe_add_uwwind_info(TCCState *s1)
16981698 {
1699− static const char uw_info[] = {
1700− 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
1701− 0x04, // UBYTE Size of prolog
1702− 0x02, // UBYTE Count of unwind codes
1703− 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
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− };
1699+ if (NULL == s1->uw_pdata) {
1700+ s1->uw_pdata = find_section(tcc_state, ".pdata");
1701+ s1->uw_pdata->sh_addralign = 4;
1702+ s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, NULL);
1703+ }
17091704
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+ };
17111717
1712− Section *uw, *pd;
1713− WORD *p1;
1714− DWORD *p2;
1715− unsigned o2;
1718+ Section *s = text_section;
1719+ unsigned char *p;
17161720
1717− uw = data_section;
1718− pd = pe_uw->pdata;
1719− if (NULL == pd)
1720− {
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);
1721+ section_ptr_add(s, -s->data_offset & 3); /* align */
1722+ s1->uw_offs = s->data_offset;
1723+ p = section_ptr_add(s, sizeof uw_info);
1724+ memcpy(p, uw_info, sizeof uw_info);
17301725 }
17311726
1732− o2 = pd->data_offset;
1733− p2 = section_ptr_add(pd, 3 * sizeof (DWORD));
1727+ return s1->uw_offs;
1728+}
1729+
1730+ST_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+
17341746 /* record this function */
1735− p2[0] = start;
1736− p2[1] = end;
1737− p2[2] = pe_uw->offs_1;
1747+ p->BeginAddress = start;
1748+ p->EndAddress = end;
1749+ p->UnwindData = d;
1750+
17381751 /* put relocations on it */
1739− put_elf_reloc(symtab_section, pd, o2, R_X86_64_RELATIVE, pe_uw->sym_1);
1740− put_elf_reloc(symtab_section, pd, o2+4, R_X86_64_RELATIVE, pe_uw->sym_1);
1741− put_elf_reloc(symtab_section, pd, o2+8, R_X86_64_RELATIVE, pe_uw->sym_2);
1752+ for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
1753+ put_elf_reloc(symtab_section, pd, o, R_X86_64_RELATIVE, s1->uw_sym);
17421754 }
17431755 #endif
1744−
17451756 /* ------------------------------------------------------------- */
17461757 #ifdef TCC_TARGET_X86_64
17471758 #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
3030 static void rt_error(ucontext_t *uc, const char *fmt, ...);
3131 static int tcc_relocate_ex(TCCState *s1, void *ptr);
3232
33+#ifdef _WIN64
34+static void win64_add_function_table(TCCState *s1);
35+#endif
36+
3337 /* ------------------------------------------------------------- */
3438 /* Do all relocations (needed before using tcc_get_symbol())
3539 Returns -1 on error. */
@@ -189,6 +193,10 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr) · 153 unmodified lines
189193 set_pages_executable(s1->runtime_plt_and_got,
190194 s1->runtime_plt_and_got_offset);
191195 #endif
196+
197+#ifdef _WIN64
198+ win64_add_function_table(s1);
199+#endif
192200 return 0;
193201 }
194202
@@ -578,6 +586,17 @@ static void set_exception_handler(void) · 383 unmodified lines
578586 SetUnhandledExceptionFilter(cpu_exception_handler);
579587 }
580588
589+#ifdef _WIN64
590+static 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+
581600 #ifdef _WIN64
582601 #define Eip Rip
583602 #define Ebp Rbp
win32/lib/chkstk.S+0−8
@@ -57,17 +57,9 @@ P0: · 56 unmodified lines
5757 /* ---------------------------------------------- */
5858 /* setjmp/longjmp support */
5959
60−.globl tinyc_no_getbp
61−tinyc_no_getbp:
62− .byte 0x90
63−
6460 .globl tinyc_getbp
6561 tinyc_getbp:
66− xor %rax,%rax
67− cmp %al,tinyc_no_getbp(%rax)
68− je t1
6962 mov %rbp,%rax
70−t1:
7163 ret
7264
7365 /* ---------------------------------------------- */
win32/lib/kernel32.def+2−0
@@ -549,7 +549,9 @@ ResetEvent · 548 unmodified lines
549549 ResetNLSUserInfoCache
550550 ResetWriteWatch
551551 ResumeThread
552+RtlAddFunctionTable
552553 RtlFillMemory
554+RtlInstallFunctionTableCallback
553555 RtlMoveMemory
554556 RtlUnwind
555557 RtlZeroMemory
x86_64-gen.c+4−3
@@ -772,8 +772,6 @@ void gfunc_epilog(void) · 771 unmodified lines
772772 /* align local size to word & save local variables */
773773 v = (func_scratch + -loc + 15) & -16;
774774
775− pe_add_unwind_data(ind, saved_ind, v);
776−
777775 if (v >= 4096) {
778776 Sym *sym = external_global_sym(TOK___chkstk, &func_old_type, 0);
779777 oad(0xb8, v); /* mov stacksize, %eax */
@@ -785,7 +783,10 @@ void gfunc_epilog(void) · 5 unmodified lines
785783 o(0xec8148); /* sub rsp, stacksize */
786784 gen_le32(v);
787785 }
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;
789790 }
790791
791792 #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