aboutsummaryrefslogtreecommitdiff
path: root/tccpe.c
diff options
context:
space:
mode:
authorgrischka <grischka>2011-07-14 19:09:49 +0200
committergrischka <grischka>2011-07-14 19:09:49 +0200
commitdf4c0892f3fb5170042652cd648a29c94c3a2eca (patch)
tree0db41a085d08276f9804b4905949c60ff1f7500f /tccpe.c
parent232650f8b3a786e82071c12a1ee8eea60684279a (diff)
downloadtinycc-df4c0892f3fb5170042652cd648a29c94c3a2eca.tar.gz
tinycc-df4c0892f3fb5170042652cd648a29c94c3a2eca.tar.bz2
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.
Diffstat (limited to 'tccpe.c')
-rw-r--r--tccpe.c87
1 files changed, 49 insertions, 38 deletions
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