209 lines
8.2 KiB
Diff
209 lines
8.2 KiB
Diff
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
|
|
index c876d51f8e6..654c84de587 100644
|
|
--- a/tools/winebuild/import.c
|
|
+++ b/tools/winebuild/import.c
|
|
@@ -1401,19 +1401,9 @@ void output_syscalls( DLLSPEC *spec )
|
|
switch (target.cpu)
|
|
{
|
|
case CPU_i386:
|
|
- 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", id );
|
|
- needs_get_pc_thunk = 1;
|
|
- }
|
|
- else
|
|
- {
|
|
- output( "\tmovl $%u,%%eax\n", id );
|
|
- 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", id );
|
|
+ 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;
|
|
}
|
|
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
|
|
index 3d0c2deca35..b0c03d992d4 100644
|
|
--- a/dlls/ws2_32/socket.c
|
|
+++ b/dlls/ws2_32/socket.c
|
|
@@ -2516,6 +2516,17 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr,
|
|
|
|
TRACE( "read %p, write %p, except %p, timeout %p\n", read_ptr, write_ptr, except_ptr, timeout );
|
|
|
|
+ static int is_RCS = -1;
|
|
+ if (is_RCS < 0) {
|
|
+ is_RCS = GetModuleHandleA(NULL) == GetModuleHandleA("RiotClientServices.exe");
|
|
+ }
|
|
+ const struct timeval zero_tv = { 0, 1000 };
|
|
+ if (is_RCS && read_ptr && write_ptr && except_ptr && timeout && timeout->tv_sec == 1 && timeout->tv_usec == 0) {
|
|
+ if (read_ptr->fd_count >= 4 && read_ptr->fd_count <= 8 && write_ptr->fd_count == 0 && except_ptr->fd_count == 1) {
|
|
+ timeout = &zero_tv;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (!(sync_event = get_sync_event())) return -1;
|
|
|
|
if (read_ptr) poll_count += read_ptr->fd_count;
|
|
diff --git a/loader/preloader.c b/loader/preloader.c
|
|
index d88964e9c4b..1ac8b9bd16b 100644
|
|
--- a/loader/preloader.c
|
|
+++ b/loader/preloader.c
|
|
@@ -1460,7 +1460,7 @@ void* wld_start( void **stack )
|
|
|
|
i = 0;
|
|
/* delete sysinfo values if addresses conflict */
|
|
- if (is_in_preload_range( av, AT_SYSINFO ) || is_in_preload_range( av, AT_SYSINFO_EHDR ))
|
|
+ if (1)
|
|
{
|
|
delete_av[i++].a_type = AT_SYSINFO;
|
|
delete_av[i++].a_type = AT_SYSINFO_EHDR;
|