static void output_import_thunk (FILE *outfile, const char *pName, const char *pTable, int Pos) { output_function_name (outfile, pName); fprintf( outfile, " \"\\t.globl " PREFIX "%s\\n\"\n", pName); fprintf( outfile, " \"" PREFIX "%s:\\n\\t", pName ); #if defined(__i386__) if (!UsePIC) fprintf( outfile, "jmp *(" __ASM_NAME("%s") "+%d)\\n\\tmovl %%esi,%%esi\\n", pTable, Pos ); else { fprintf( outfile, "call %s\\n", __ASM_NAME("__wine_spec_get_pc_thunk_eax") ); fprintf( outfile, "1:\\tjmp *" __ASM_NAME ("%s") "+%d-1b(%%eax)\\n", pTable, Pos); } #elif defined(__sparc__) if ( !UsePIC ) { fprintf( outfile, "sethi %%hi(" __ASM_NAME ("%s") "+%d), %%g1\\n\\t", pTable, Pos ); fprintf( outfile, "ld [%%g1+%%lo(" __ASM_NAME ("%s") "+%d)], %%g1\\n\\t", pTable, Pos ); fprintf( outfile, "jmp %%g1\\n\\tnop\\n" ); } else { /* Hmpf. Stupid sparc assembler always interprets global variable names as GOT offsets, so we have to do it the long way ... */ fprintf( outfile, "save %%sp, -96, %%sp\\n" ); fprintf( outfile, "0:\\tcall 1f\\n\\tnop\\n" ); fprintf( outfile, "1:\\tsethi %%hi(" __ASM_NAME ("%s") "+%d-0b), %%g1\\n\\t", pTable, Pos ); fprintf( outfile, "or %%g1, %%lo(" __ASM_NAME ("%s") "+%d-0b), %%g1\\n\\t", pTable, Pos ); fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" ); fprintf( outfile, "jmp %%g1\\n\\trestore\\n" ); } #elif defined(__PPC__) fprintf(outfile, "\taddis r11,0,ha16(" __ASM_NAME ("%s") "+%d)\\n\"\n", pTable, Pos); fprintf(outfile, "\t\"\\tla r12,lo16(" __ASM_NAME ("%s") "+%d)(r11)\\n\"\n", pTable, Pos); fprintf(outfile, "\t\"\\tlwz r11, 0(r12)\\n\"\n"); fprintf(outfile, "\t\"\\tmtctr r11\\n\"\n"); fprintf(outfile, "\t\"\\tbctr\\n"); #else #error You need to define import thunks for your architecture! #endif fprintf( outfile, "\"\n" ); }
void output_get_pc_thunk (FILE *outfile) { #ifndef __i386__ return; #else if (!UsePIC) return; fprintf( outfile, "asm(\"\\n\\t.text\\n\"\n" ); fprintf( outfile, "\"\\t.align %d\\n\"\n", get_alignment(4) ); output_function_name (outfile, "__wine_spec_get_pc_thunk_eax"); fprintf( outfile, "\"%s:\\n\"\n", __ASM_NAME("__wine_spec_get_pc_thunk_eax") ); fprintf( outfile, "\"\\tpopl %%eax\\n\"\n" ); fprintf( outfile, "\"\\tpushl %%eax\\n\"\n" ); fprintf( outfile, "\"\\tret\\n\"\n" ); fprintf( outfile, ");\n"); #endif }
"movl (%ecx),%ecx\n\t" /* This->lpVtbl */ "movl -8(%ecx),%ecx\n\t" /* MIDL_STUBLESS_PROXY_INFO */ "movl 8(%ecx),%edx\n\t" /* info->FormatStringOffset */ "movzwl (%edx,%eax,2),%edx\n\t" /* FormatStringOffset[index] */ "addl 4(%ecx),%edx\n\t" /* info->ProcFormatString + offset */ "movzwl 8(%edx),%eax\n\t" /* arguments size */ "pushl %eax\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "leal 8(%esp),%eax\n\t" /* &This */ "pushl %eax\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "pushl %edx\n\t" /* format string */ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "pushl (%ecx)\n\t" /* info->pStubDesc */ __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") "call " __ASM_NAME("ndr_client_call") "\n\t" "leal 12(%esp),%esp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset -12\n\t") "popl %edx\n\t" /* arguments size */ __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t") "movl (%esp),%ecx\n\t" /* return address */ "addl %edx,%esp\n\t" "jmp *%ecx" ); #include "pshpack1.h" struct thunk { BYTE mov_eax; DWORD index; BYTE jmp; LONG handler;
* * NOTE * On x86, Shrinker, an executable compressor, depends on the * "call access_resource" instruction being there. */ #ifdef __i386__ __ASM_STDCALL_FUNC( LdrAccessResource, 16, "pushl %ebp\n\t" "movl %esp, %ebp\n\t" "subl $4,%esp\n\t" "pushl 24(%ebp)\n\t" "pushl 20(%ebp)\n\t" "pushl 16(%ebp)\n\t" "pushl 12(%ebp)\n\t" "pushl 8(%ebp)\n\t" "call " __ASM_NAME("access_resource") "\n\t" "leave\n\t" "ret $16" ) #else NTSTATUS WINAPI LdrAccessResource( HMODULE hmod, const IMAGE_RESOURCE_DATA_ENTRY *entry, void **ptr, ULONG *size ) { return access_resource( hmod, entry, ptr, size ); } #endif /********************************************************************** * RtlFindMessage (NTDLL.@) */ NTSTATUS WINAPI RtlFindMessage( HMODULE hmod, ULONG type, ULONG lang,
/********************************************************************* * __CxxQueryExceptionSize (MSVCRT.@) */ unsigned int CDECL __CxxQueryExceptionSize(void) { return sizeof(cxx_exception_type); } /******************************************************************* * _setjmp (MSVCRT.@) */ __ASM_GLOBAL_FUNC(MSVCRT__setjmp, "mov r1, #0\n\t" /* frame */ "b " __ASM_NAME("MSVCRT__setjmpex")); /******************************************************************* * _setjmpex (MSVCRT.@) */ __ASM_GLOBAL_FUNC(MSVCRT__setjmpex, "str r1, [r0]\n\t" /* jmp_buf->Frame */ "str r4, [r0, #0x4]\n\t" /* jmp_buf->R4 */ "str r5, [r0, #0x8]\n\t" /* jmp_buf->R5 */ "str r6, [r0, #0xc]\n\t" /* jmp_buf->R6 */ "str r7, [r0, #0x10]\n\t" /* jmp_buf->R7 */ "str r8, [r0, #0x14]\n\t" /* jmp_buf->R8 */ "str r9, [r0, #0x18]\n\t" /* jmp_buf->R9 */ "str r10, [r0, #0x1c]\n\t" /* jmp_buf->R10 */ "str r11, [r0, #0x20]\n\t" /* jmp_buf->R11 */ "str sp, [r0, #0x24]\n\t" /* jmp_buf->Sp */
# ifdef __GNUC__ __ASM_GLOBAL_FUNC(_chkesp, "jnz 1f\n\t" "ret\n" "1:\tpushl %ebp\n\t" __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") "movl %esp,%ebp\n\t" __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") "subl $12,%esp\n\t" "pushl %eax\n\t" "pushl %ecx\n\t" "pushl %edx\n\t" "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t" "popl %edx\n\t" "popl %ecx\n\t" "popl %eax\n\t" "leave\n\t" __ASM_CFI(".cfi_def_cfa %esp,4\n\t") __ASM_CFI(".cfi_same_value %ebp\n\t") "ret") void CDECL MSVCRT_chkesp_fail(void) { ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n"); DebugBreak(); } # else /* __GNUC__ */
/* output the delayed import table of a Win32 module */ static int output_delayed_imports( FILE *outfile ) { int i, idx, j, pos; if (!nb_delayed) goto done; for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i); for (j = 0; j < dll_imports[i]->nb_imports; j++) { fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, dll_imports[i]->imports[j] ); } } fprintf( outfile, "\n" ); fprintf( outfile, "static struct {\n" ); fprintf( outfile, " struct ImgDelayDescr {\n" ); fprintf( outfile, " unsigned int grAttrs;\n" ); fprintf( outfile, " const char *szName;\n" ); fprintf( outfile, " void **phmod;\n" ); fprintf( outfile, " void **pIAT;\n" ); fprintf( outfile, " const char **pINT;\n" ); fprintf( outfile, " void* pBoundIAT;\n" ); fprintf( outfile, " void* pUnloadIAT;\n" ); fprintf( outfile, " unsigned long dwTimeStamp;\n" ); fprintf( outfile, " } imp[%d];\n", nb_delayed ); fprintf( outfile, " void *IAT[%d];\n", total_delayed ); fprintf( outfile, " const char *INT[%d];\n", total_delayed ); fprintf( outfile, "} delay_imports = {\n" ); fprintf( outfile, " {\n" ); for (i = j = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n", dll_imports[i]->dll, i, j, j ); j += dll_imports[i]->nb_imports; } fprintf( outfile, " },\n {\n" ); for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; fprintf( outfile, " /* %s */\n", dll_imports[i]->dll ); for (j = 0; j < dll_imports[i]->nb_imports; j++) { fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j] ); } } fprintf( outfile, " },\n {\n" ); for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; fprintf( outfile, " /* %s */\n", dll_imports[i]->dll ); for (j = 0; j < dll_imports[i]->nb_imports; j++) { fprintf( outfile, " \"\\0\\0%s\",\n", dll_imports[i]->imports[j] ); } } fprintf( outfile, " }\n};\n\n" ); /* check if there's some stub defined. if so, exception struct * is already defined, so don't emit it twice */ for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break; if (i == nb_entry_points) { fprintf( outfile, "struct exc_record {\n" ); fprintf( outfile, " unsigned int code, flags;\n" ); fprintf( outfile, " void *rec, *addr;\n" ); fprintf( outfile, " unsigned int params;\n" ); fprintf( outfile, " const void *info[15];\n" ); fprintf( outfile, "};\n\n" ); fprintf( outfile, "extern void __stdcall RtlRaiseException( struct exc_record * );\n" ); } fprintf( outfile, "extern void * __stdcall LoadLibraryA(const char*);\n"); fprintf( outfile, "extern void * __stdcall GetProcAddress(void *, const char*);\n"); fprintf( outfile, "\n" ); fprintf( outfile, "void *__stdcall __wine_delay_load( int idx_nr )\n" ); fprintf( outfile, "{\n" ); fprintf( outfile, " int idx = idx_nr >> 16, nr = idx_nr & 0xffff;\n" ); fprintf( outfile, " struct ImgDelayDescr *imd = delay_imports.imp + idx;\n" ); fprintf( outfile, " void **pIAT = imd->pIAT + nr;\n" ); fprintf( outfile, " const char** pINT = imd->pINT + nr;\n" ); fprintf( outfile, " void *fn;\n\n" ); fprintf( outfile, " if (!*imd->phmod) *imd->phmod = LoadLibraryA(imd->szName);\n" ); fprintf( outfile, " if (*imd->phmod && (fn = GetProcAddress(*imd->phmod, *pINT + 2)))\n"); fprintf( outfile, " /* patch IAT with final value */\n" ); fprintf( outfile, " return *pIAT = fn;\n" ); fprintf( outfile, " else {\n"); fprintf( outfile, " struct exc_record rec;\n" ); fprintf( outfile, " rec.code = 0x80000100;\n" ); fprintf( outfile, " rec.flags = 1;\n" ); fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.params = 2;\n" ); fprintf( outfile, " rec.info[0] = imd->szName;\n" ); fprintf( outfile, " rec.info[1] = *pINT + 2;\n" ); fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); fprintf( outfile, "#else\n" ); fprintf( outfile, " rec.addr = 0;\n" ); fprintf( outfile, "#endif\n" ); fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n" ); fprintf( outfile, " return 0; /* shouldn't go here */\n" ); fprintf( outfile, " }\n}\n\n" ); fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" ); fprintf( outfile, "#endif\n" ); fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) ); output_function_name (outfile, "__wine_delay_load_asm"); fprintf( outfile, " \"" PREFIX "__wine_delay_load_asm:\\n\"\n" ); #if defined(__i386__) fprintf( outfile, " \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" ); fprintf( outfile, " \"\\tcall " __ASM_NAME("__wine_delay_load") "\\n\"\n" ); fprintf( outfile, " \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" ); #elif defined(__sparc__) fprintf( outfile, " \"\\tsave %%sp, -96, %%sp\\n\"\n" ); fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" ); fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" ); fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" ); #elif defined(__PPC__) fprintf(outfile, "#error: DELAYED IMPORTS NOT SUPPORTED ON PPC!!!\n"); #else #error You need to defined delayed import thunks for your architecture! #endif for (i = idx = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; for (j = 0; j < dll_imports[i]->nb_imports; j++) { char buffer[128]; sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j]); output_function_name (outfile, buffer); fprintf( outfile, " \"" PREFIX "%s:\\n\"\n", buffer ); #if defined(__i386__) fprintf( outfile, " \"\\tmovl $%d, %%eax\\n\"\n", (idx << 16) | j ); fprintf( outfile, " \"\\tjmp " __ASM_NAME("__wine_delay_load_asm")"\\n\"\n" ); #elif defined(__sparc__) fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j ); fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" ); #elif defined(__PPC__) fprintf(outfile, "#error: DELAYED IMPORTS NOT SUPPORTED ON PPC!!!\n"); #else #error You need to defined delayed import thunks for your architecture! #endif } idx++; } fprintf( outfile, "\n \".align %d\\n\"\n", get_alignment(8) ); pos = nb_delayed * 32; for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4) output_import_thunk (outfile, dll_imports[i]->imports[j], "delay_imports", pos); } fprintf( outfile, ");\n" ); fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "}\n" ); fprintf( outfile, "#endif\n" ); fprintf( outfile, "\n" ); done: return nb_delayed; }
if (!RtlUnicodeStringToAnsiString( &strA, &strW, TRUE )) { OutputDebugStringA( strA.Buffer ); RtlFreeAnsiString( &strA ); } } /*********************************************************************** * DebugBreak (KERNEL32.@) * * Raises an exception so that a debugger (if attached) * can take some action. */ #if defined(__i386__) || defined(__x86_64__) __ASM_STDCALL_FUNC( DebugBreak, 0, "jmp " __ASM_NAME("DbgBreakPoint") ) #else void WINAPI DebugBreak(void) { DbgBreakPoint(); } #endif /*********************************************************************** * DebugBreakProcess (KERNEL32.@) * * Raises an exception so that a debugger (if attached) * can take some action. Same as DebugBreak, but applies to any process. * * PARAMS * hProc [I] Process to break into.