diff options
author | Tor Lillqvist <tlillqvist@novell.com> | 2011-01-28 04:22:11 +0200 |
---|---|---|
committer | Tor Lillqvist <tlillqvist@novell.com> | 2011-01-28 04:22:11 +0200 |
commit | 5287150cb7b37c094d43f1e3f1e38825a813540e (patch) | |
tree | 43ce062d7656e4dcefe166af1183cb6ef04640f6 /bridges/source | |
parent | 44abf1ea66fbf0ee3f3b5195c6af6b631d633cba (diff) |
Add a function table entry for the dynamically generated trampoline
Diffstat (limited to 'bridges/source')
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm | 2 | ||||
-rw-r--r-- | bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx | 94 |
2 files changed, 91 insertions, 5 deletions
diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm b/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm index 377132a9623c..b1a4f73907fc 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/codeSnippet.asm @@ -132,6 +132,8 @@ public trampoline_template_spill_end ;; cpp_vtable_call()) to spill their register parameters. sub rsp, 40 +trampoline_template_prolog_end:: +public trampoline_template_prolog_end ;; Call cpp_vtable_call() with 3 parameters: diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx index 29545337b16b..952c6dfb537a 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -374,18 +374,69 @@ extern "C" typelib_TypeClass cpp_vtable_call( //================================================================================================== extern "C" { +// From http://msdn.microsoft.com/en-us/library/ssa62fwe%28v=VS.90%29.aspx + +typedef enum _UNWIND_OP_CODES { + UWOP_PUSH_NONVOL = 0, /* info == register number */ + UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */ + UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */ + UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */ + UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */ + UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */ + UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */ + UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */ + UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */ +} UNWIND_CODE_OPS; + +typedef union _UNWIND_CODE { + struct { + sal_uChar CodeOffset; + sal_uChar UnwindOp : 4; + sal_uChar OpInfo : 4; + } u; + USHORT FrameOffset; +} UNWIND_CODE, *PUNWIND_CODE; + +#define UNW_FLAG_EHANDLER 0x01 +#define UNW_FLAG_UHANDLER 0x02 +#define UNW_FLAG_CHAININFO 0x04 + +typedef struct _UNWIND_INFO { + sal_uChar Version : 3; + sal_uChar Flags : 5; + sal_uChar SizeOfProlog; + sal_uChar CountOfCodes; + sal_uChar FrameRegister : 4; + sal_uChar FrameOffset : 4; + UNWIND_CODE UnwindCode[1]; +/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1]; +* union { +* OPTIONAL ULONG ExceptionHandler; +* OPTIONAL ULONG FunctionEntry; +* }; +* OPTIONAL ULONG ExceptionData[]; */ +} UNWIND_INFO, *PUNWIND_INFO; + // These are actually addresses in the code compiled from codeSnippet.asm extern char fp_spill_templates, fp_spill_templates_end, trampoline_template, trampoline_template_spill_end, + trampoline_template_prolog_end, trampoline_template_function_index, trampoline_template_vtable_offset, trampoline_template_end; } -int const codeSnippetSize = (int) (&trampoline_template_end - &trampoline_template); +// Just the code +int const codeSnippetCodeSize = + (int) (&trampoline_template_end - &trampoline_template); + +// Including the function table entry and unwind information, plus +// alignment padding +int const codeSnippetSize = + codeSnippetCodeSize + (int) (sizeof( RUNTIME_FUNCTION ) + sizeof( UNWIND_INFO )) + 8; // This function generates the code that acts as a proxy for the UNO function to be called. // The generated code does the following: @@ -409,7 +460,7 @@ unsigned char * codeSnippet( int const one_spill_instruction_size = (int) ((&fp_spill_templates_end - &fp_spill_templates)) / 4; - memcpy( code, &trampoline_template, codeSnippetSize ); + memcpy( code, &trampoline_template, codeSnippetCodeSize ); for (int i = 0; i < 4; ++i) if ( param_kind[i] == CPPU_CURRENT_NAMESPACE::REGPARAM_FLT ) @@ -420,9 +471,42 @@ unsigned char * codeSnippet( ((sal_uInt64*) trampoline_template_function_index)[-1] = functionIndex; ((sal_uInt64*) trampoline_template_vtable_offset)[-1] = vtableOffset; - // TODO: Add unwind data for the dynamically generated function by - // calling RtlAddFunctionTable(). We also need to remove the - // unwind data with RtlDeleteFunctionTable() in freeExec() then. + // Add unwind data for the dynamically generated function by + // calling RtlAddFunctionTable(). + + // TODO: We need to remove the unwind data with + // RtlDeleteFunctionTable() in freeExec() in + // vtablefactory.cxx. How can we get at the function pointer table + // there? Maybe we should move the function table and unwind info + // to be at the beginning of the allocated block, and add another + // parameter to this function to return the actual trampoline + // start, etc? + + // Just one function with one unwind info with one unwind code + // included in it. Here we just "know" what the code in + // codeSnippet.asm looks like, sorry. + + RUNTIME_FUNCTION *pFunTable = + (RUNTIME_FUNCTION *) (((((sal_uInt64) (code + codeSnippetSize) - 1) / 4) + 1) * 4); + UNWIND_INFO *pUnwInfo = + (UNWIND_INFO *) (pFunTable + 1); + + OSL_ASSERT( (unsigned char *) (pUnwInfo + 1) <= code + codeSnippetSize ); + + pFunTable->BeginAddress = 0; + pFunTable->EndAddress = codeSnippetCodeSize; + pFunTable->UnwindData = (DWORD) ((unsigned char *) pUnwInfo - code); + + pUnwInfo->Version = 1; + pUnwInfo->Flags = 0; + pUnwInfo->SizeOfProlog = (sal_uChar) (&trampoline_template_prolog_end - &trampoline_template); + pUnwInfo->CountOfCodes = 1; + pUnwInfo->FrameRegister = 0; + pUnwInfo->UnwindCode[0].u.CodeOffset = (sal_uChar) (&trampoline_template_prolog_end - &trampoline_template); + pUnwInfo->UnwindCode[0].u.UnwindOp = UWOP_ALLOC_SMALL; + pUnwInfo->UnwindCode[0].u.OpInfo = 4; + + RtlAddFunctionTable( pFunTable, 1, (DWORD64) code ); return code + codeSnippetSize; } |