From df4c0892f3fb5170042652cd648a29c94c3a2eca Mon Sep 17 00:00:00 2001 From: grischka Date: Thu, 14 Jul 2011 19:09:49 +0200 Subject: 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. --- tccpe.c | 87 +++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 38 deletions(-) (limited to 'tccpe.c') diff --git a/tccpe.c b/tccpe.c index 22b61a6..3510d9c 100644 --- a/tccpe.c +++ b/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) - }; + 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); + } - struct pe_uw *pe_uw = &tcc_state->pe_unwind; + 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 *uw, *pd; - WORD *p1; - DWORD *p2; - unsigned o2; + Section *s = text_section; + unsigned char *p; - 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); + 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); } - o2 = pd->data_offset; - p2 = section_ptr_add(pd, 3 * sizeof (DWORD)); + 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 -- cgit v1.3.1