PKGBUILDS/wine-tkg-git/wine-tkg-git/wine-tkg-patches/game-specific/leagueoflolfix/legacy/leagueoflolfix-3513a17.patch

172 lines
6.7 KiB
Diff

--- a/tools/winebuild/import.c
+++ a/tools/winebuild/import.c
@@ -1951,19 +1951,9 @@ void output_syscalls( DLLSPEC *spec )
switch (target_cpu)
{
case CPU_x86:
- if (UsePIC)
- {
- output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
- output( "1:\tmovl %s-1b(%%eax),%%edx\n", asm_name("__wine_syscall_dispatcher") );
- output( "\tmovl $%u,%%eax\n", i );
- needs_get_pc_thunk = 1;
- }
- else
- {
- output( "\tmovl $%u,%%eax\n", i );
- output( "\tmovl $%s,%%edx\n", asm_name("__wine_syscall") );
- }
- output( "\tcall *%%edx\n" );
+ output( "\t.byte 0xb8\n" ); /* mov eax, SYSCALL */
+ output( "\t.long %d\n", i );
+ output( "\t.byte 0x64,0xff,0x15,0xc0,0x00,0x00,0x00\n" ); /* call dword ptr fs:[0C0h] */
output( "\tret $%u\n", odp->type == TYPE_STDCALL ? get_args_size( odp ) : 0 );
break;
case CPU_x86_64:
--- a/dlls/ntdll/unix/signal_i386.c
+++ a/dlls/ntdll/unix/signal_i386.c
@@ -415,6 +415,8 @@ static inline int set_thread_area( struc
static ULONG first_ldt_entry = 32;
+static int wine_cs;
+
enum i386_trap_code
{
#if defined(__FreeBSD__) || defined (__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
@@ -528,6 +530,11 @@ static inline WORD get_cs(void) { WORD r
static inline WORD get_ds(void) { WORD res; __asm__( "movw %%ds,%0" : "=r" (res) ); return res; }
static inline WORD get_fs(void) { WORD res; __asm__( "movw %%fs,%0" : "=r" (res) ); return res; }
static inline WORD get_gs(void) { WORD res; __asm__( "movw %%gs,%0" : "=r" (res) ); return res; }
+static CDECL void __attribute((naked)) set_cs( DWORD val ) {
+ asm ( "movl 4(%esp),%eax\n\t"
+ "xchg 0(%esp),%eax\n\t"
+ "push %eax\n\t"
+ "lret"); }
static inline void set_fs( WORD val ) { __asm__( "mov %0,%%fs" :: "r" (val)); }
static inline void set_gs( WORD val ) { __asm__( "mov %0,%%gs" :: "r" (val)); }
@@ -694,7 +701,8 @@ static inline void *init_handler( const
}
#endif
- if (!ldt_is_system(CS_sig(sigcontext)) || !ldt_is_system(SS_sig(sigcontext))) /* 16-bit mode */
+ if ((CS_sig(sigcontext) != wine_cs && !ldt_is_system(CS_sig(sigcontext))) ||
+ !ldt_is_system(SS_sig(sigcontext))) /* 16-bit mode */
{
/*
* Win16 or DOS protected mode. Note that during switch
@@ -1185,7 +1193,7 @@ static inline DWORD is_privileged_instr(
BYTE instr[16];
unsigned int i, len, prefix_count = 0;
- if (!ldt_is_system( context->SegCs )) return 0;
+ if (context->SegCs != wine_cs && !ldt_is_system( context->SegCs )) return 0;
len = virtual_uninterrupted_read_memory( (BYTE *)context->Eip, instr, sizeof(instr) );
for (i = 0; i < len; i++) switch (instr[i])
@@ -1252,7 +1260,7 @@ static inline BOOL check_invalid_gs( uco
WORD system_gs = x86_thread_data()->gs;
if (context->SegGs == system_gs) return FALSE;
- if (!ldt_is_system( context->SegCs )) return FALSE;
+ if (context->SegCs != wine_cs && !ldt_is_system( context->SegCs )) return FALSE;
/* only handle faults in system libraries */
if (virtual_is_valid_code_address( instr, 1 )) return FALSE;
@@ -1489,7 +1497,7 @@ C_ASSERT( (offsetof(struct stack_layout,
EIP_sig(sigcontext) = (DWORD)pKiUserExceptionDispatcher;
/* clear single-step, direction, and align check flag */
EFL_sig(sigcontext) &= ~(0x100|0x400|0x40000);
- CS_sig(sigcontext) = get_cs();
+ CS_sig(sigcontext) = wine_cs;
DS_sig(sigcontext) = get_ds();
ES_sig(sigcontext) = get_ds();
FS_sig(sigcontext) = get_fs();
@@ -2108,6 +2116,36 @@ static void ldt_set_entry( WORD sel, LDT
LDT_FLAGS_ALLOCATED);
}
+static WORD internal_ldt_alloc_entry(void)
+{
+ for (int idx = first_ldt_entry; idx < LDT_SIZE; idx++)
+ {
+ if (__wine_ldt_copy.flags[idx] & LDT_FLAGS_ALLOCATED) continue;
+
+ /* mark selector as allocated */
+ __wine_ldt_copy.flags[idx] |= LDT_FLAGS_ALLOCATED;
+ return (idx << 3) | 7;
+ }
+ return 0;
+}
+
+static inline void cs_init( int first_thread )
+{
+ LDT_ENTRY entry;
+ sigset_t sigset;
+
+ /* no locking for first thread */
+ if (!first_thread) server_enter_uninterrupted_section( &ldt_mutex, &sigset );
+ if (!wine_cs)
+ wine_cs = internal_ldt_alloc_entry();
+
+ entry = ldt_make_entry( 0, (UINT_PTR)-1, LDT_FLAGS_CODE|LDT_FLAGS_32BIT );
+ ldt_set_entry( wine_cs, entry );
+
+ if (!first_thread) server_leave_uninterrupted_section( &ldt_mutex, &sigset );
+ set_cs( wine_cs );
+}
+
static void ldt_set_fs( WORD sel, TEB *teb )
{
if (sel == gdt_fs_sel)
@@ -2223,38 +2261,35 @@ void signal_init_threading(void)
NTSTATUS signal_alloc_thread( TEB *teb )
{
struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch;
+ static int first_thread = 1;
if (!gdt_fs_sel)
{
- static int first_thread = 1;
sigset_t sigset;
- int idx;
+ WORD sel;
LDT_ENTRY entry = ldt_make_entry( teb, page_size - 1, LDT_FLAGS_DATA | LDT_FLAGS_32BIT );
if (first_thread) /* no locking for first thread */
{
/* leave some space if libc is using the LDT for %gs */
if (!is_gdt_sel( get_gs() )) first_ldt_entry = 512;
- idx = first_ldt_entry;
- ldt_set_entry( (idx << 3) | 7, entry );
- first_thread = 0;
+ sel = (first_ldt_entry << 3) | 7;
+ ldt_set_entry( sel, entry );
}
else
{
server_enter_uninterrupted_section( &ldt_mutex, &sigset );
- for (idx = first_ldt_entry; idx < LDT_SIZE; idx++)
- {
- if (__wine_ldt_copy.flags[idx]) continue;
- ldt_set_entry( (idx << 3) | 7, entry );
- break;
- }
+ sel = internal_ldt_alloc_entry();
+ if (sel) ldt_set_entry( sel, entry );
server_leave_uninterrupted_section( &ldt_mutex, &sigset );
- if (idx == LDT_SIZE) return STATUS_TOO_MANY_THREADS;
+ if (!sel) return STATUS_TOO_MANY_THREADS;
}
- thread_data->fs = (idx << 3) | 7;
+ thread_data->fs = sel;
}
else thread_data->fs = gdt_fs_sel;
+ cs_init( first_thread );
+ first_thread = 0;
teb->WOW32Reserved = __wine_syscall_dispatcher;
return STATUS_SUCCESS;
}