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.
This commit is contained in:
grischka
2011-07-14 19:09:49 +02:00
parent 232650f8b3
commit df4c0892f3
6 changed files with 82 additions and 56 deletions

93
tccpe.c
View File

@ -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