779 lines
29 KiB
Diff
779 lines
29 KiB
Diff
From 834e7d5da1ff024429c3e8b84ab7201babdd7ebf Mon Sep 17 00:00:00 2001
|
|
From: Tk-Glitch <ti3nou@gmail.com>
|
|
Date: Thu, 9 Apr 2020 12:20:12 +0200
|
|
Subject: Revert "libwine: Remove some no longer needed helper functions."
|
|
|
|
This reverts commit 18273d5e71e25575bdbdba1d252df72be3373f6d.
|
|
|
|
diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
|
|
index a8f4925019b..18b0b9be9bf 100644
|
|
--- a/libs/wine/ldt.c
|
|
+++ b/libs/wine/ldt.c
|
|
@@ -45,9 +45,26 @@ struct __wine_ldt_copy
|
|
unsigned char flags[8192]; /* flags (defined below) */
|
|
} wine_ldt_copy_obsolete = { { 0, 0, 0 } };
|
|
|
|
+#define WINE_LDT_FLAGS_DATA 0x13 /* Data segment */
|
|
+#define WINE_LDT_FLAGS_STACK 0x17 /* Stack segment */
|
|
+#define WINE_LDT_FLAGS_CODE 0x1b /* Code segment */
|
|
+#define WINE_LDT_FLAGS_TYPE_MASK 0x1f /* Mask for segment type */
|
|
#define WINE_LDT_FLAGS_32BIT 0x40 /* Segment is 32-bit (code or stack) */
|
|
#define WINE_LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
|
|
|
|
+/* helper functions to manipulate the LDT_ENTRY structure */
|
|
+static inline void wine_ldt_set_base( LDT_ENTRY *ent, const void *base )
|
|
+{
|
|
+ ent->BaseLow = (WORD)(ULONG_PTR)base;
|
|
+ ent->HighWord.Bits.BaseMid = (BYTE)((ULONG_PTR)base >> 16);
|
|
+ ent->HighWord.Bits.BaseHi = (BYTE)((ULONG_PTR)base >> 24);
|
|
+}
|
|
+static inline void wine_ldt_set_limit( LDT_ENTRY *ent, unsigned int limit )
|
|
+{
|
|
+ if ((ent->HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12;
|
|
+ ent->LimitLow = (WORD)limit;
|
|
+ ent->HighWord.Bits.LimitHi = (limit >> 16);
|
|
+}
|
|
static inline void *wine_ldt_get_base( const LDT_ENTRY *ent )
|
|
{
|
|
return (void *)(ent->BaseLow |
|
|
@@ -77,6 +60,26 @@ static inline unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
|
|
if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
|
|
return limit;
|
|
}
|
|
+static inline void wine_ldt_set_flags( LDT_ENTRY *ent, unsigned char flags )
|
|
+{
|
|
+ ent->HighWord.Bits.Dpl = 3;
|
|
+ ent->HighWord.Bits.Pres = 1;
|
|
+ ent->HighWord.Bits.Type = flags;
|
|
+ ent->HighWord.Bits.Sys = 0;
|
|
+ ent->HighWord.Bits.Reserved_0 = 0;
|
|
+ ent->HighWord.Bits.Default_Big = (flags & WINE_LDT_FLAGS_32BIT) != 0;
|
|
+}
|
|
+static inline unsigned char wine_ldt_get_flags( const LDT_ENTRY *ent )
|
|
+{
|
|
+ unsigned char ret = ent->HighWord.Bits.Type;
|
|
+ if (ent->HighWord.Bits.Default_Big) ret |= WINE_LDT_FLAGS_32BIT;
|
|
+ return ret;
|
|
+}
|
|
+static inline int wine_ldt_is_empty( const LDT_ENTRY *ent )
|
|
+{
|
|
+ const DWORD *dw = (const DWORD *)ent;
|
|
+ return (dw[0] | dw[1]) == 0;
|
|
+}
|
|
|
|
#ifdef __linux__
|
|
|
|
@@ -207,21 +170,9 @@ void wine_ldt_get_entry_obsolete( unsigned short sel, LDT_ENTRY *entry )
|
|
lock_ldt();
|
|
if (wine_ldt_copy_obsolete.flags[index] & WINE_LDT_FLAGS_ALLOCATED)
|
|
{
|
|
+ wine_ldt_set_base( entry, wine_ldt_copy_obsolete.base[index] );
|
|
+ wine_ldt_set_limit( entry, wine_ldt_copy_obsolete.limit[index] );
|
|
+ wine_ldt_set_flags( entry, wine_ldt_copy_obsolete.flags[index] );
|
|
- ULONG_PTR base = (ULONG_PTR)wine_ldt_copy_obsolete.base[index];
|
|
- ULONG limit = wine_ldt_copy_obsolete.limit[index];
|
|
-
|
|
- entry->BaseLow = (WORD)base;
|
|
- entry->HighWord.Bits.BaseMid = (BYTE)(base >> 16);
|
|
- entry->HighWord.Bits.BaseHi = (BYTE)(base >> 24);
|
|
- if ((entry->HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12;
|
|
- entry->LimitLow = (WORD)limit;
|
|
- entry->HighWord.Bits.LimitHi = (limit >> 16);
|
|
- entry->HighWord.Bits.Dpl = 3;
|
|
- entry->HighWord.Bits.Pres = 1;
|
|
- entry->HighWord.Bits.Type = wine_ldt_copy_obsolete.flags[index];
|
|
- entry->HighWord.Bits.Sys = 0;
|
|
- entry->HighWord.Bits.Reserved_0 = 0;
|
|
- entry->HighWord.Bits.Default_Big = !!(wine_ldt_copy_obsolete.flags[index] & WINE_LDT_FLAGS_32BIT);
|
|
}
|
|
else *entry = null_entry;
|
|
unlock_ldt();
|
|
|
|
From 834e7d5da1ff024429c3e8b84ab7201babdd7ebf Mon Sep 17 00:00:00 2001
|
|
From: Tk-Glitch <ti3nou@gmail.com>
|
|
Date: Sat, 4 Apr 2020 13:05:43 +0200
|
|
Subject: Revert "libwine: Make the LDT functions obsolete."
|
|
|
|
This reverts commit 3b16f35413f3a6641df42b782ead294f343e7d5e.
|
|
|
|
diff --git a/include/wine/library.h b/include/wine/library.h
|
|
index f338c4da19..a6fe28059f 100644
|
|
--- a/include/wine/library.h
|
|
+++ b/include/wine/library.h
|
|
@@ -76,6 +76,116 @@ extern int wine_mmap_is_in_reserved_area( void *addr, size_t size );
|
|
extern int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg),
|
|
void *arg, int top_down );
|
|
|
|
+#ifdef __i386__
|
|
+
|
|
+/* LDT management */
|
|
+
|
|
+extern void wine_ldt_init_locking( void (*lock_func)(void), void (*unlock_func)(void) );
|
|
+extern void wine_ldt_get_entry( unsigned short sel, LDT_ENTRY *entry );
|
|
+extern int wine_ldt_set_entry( unsigned short sel, const LDT_ENTRY *entry );
|
|
+extern int wine_ldt_is_system( unsigned short sel );
|
|
+extern void *wine_ldt_get_ptr( unsigned short sel, unsigned long offset );
|
|
+extern unsigned short wine_ldt_alloc_entries( int count );
|
|
+extern unsigned short wine_ldt_realloc_entries( unsigned short sel, int oldcount, int newcount );
|
|
+extern void wine_ldt_free_entries( unsigned short sel, int count );
|
|
+extern unsigned short wine_ldt_alloc_fs(void);
|
|
+extern void wine_ldt_init_fs( unsigned short sel, const LDT_ENTRY *entry );
|
|
+extern void wine_ldt_free_fs( unsigned short sel );
|
|
+
|
|
+/* the local copy of the LDT */
|
|
+extern struct __wine_ldt_copy
|
|
+{
|
|
+ void *base[8192]; /* base address or 0 if entry is free */
|
|
+ unsigned long limit[8192]; /* limit in bytes or 0 if entry is free */
|
|
+ unsigned char flags[8192]; /* flags (defined below) */
|
|
+} wine_ldt_copy;
|
|
+
|
|
+#define WINE_LDT_FLAGS_DATA 0x13 /* Data segment */
|
|
+#define WINE_LDT_FLAGS_STACK 0x17 /* Stack segment */
|
|
+#define WINE_LDT_FLAGS_CODE 0x1b /* Code segment */
|
|
+#define WINE_LDT_FLAGS_TYPE_MASK 0x1f /* Mask for segment type */
|
|
+#define WINE_LDT_FLAGS_32BIT 0x40 /* Segment is 32-bit (code or stack) */
|
|
+#define WINE_LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
|
|
+
|
|
+/* helper functions to manipulate the LDT_ENTRY structure */
|
|
+static inline void wine_ldt_set_base( LDT_ENTRY *ent, const void *base )
|
|
+{
|
|
+ ent->BaseLow = (WORD)(ULONG_PTR)base;
|
|
+ ent->HighWord.Bits.BaseMid = (BYTE)((ULONG_PTR)base >> 16);
|
|
+ ent->HighWord.Bits.BaseHi = (BYTE)((ULONG_PTR)base >> 24);
|
|
+}
|
|
+static inline void wine_ldt_set_limit( LDT_ENTRY *ent, unsigned int limit )
|
|
+{
|
|
+ if ((ent->HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12;
|
|
+ ent->LimitLow = (WORD)limit;
|
|
+ ent->HighWord.Bits.LimitHi = (limit >> 16);
|
|
+}
|
|
+static inline void *wine_ldt_get_base( const LDT_ENTRY *ent )
|
|
+{
|
|
+ return (void *)(ent->BaseLow |
|
|
+ (ULONG_PTR)ent->HighWord.Bits.BaseMid << 16 |
|
|
+ (ULONG_PTR)ent->HighWord.Bits.BaseHi << 24);
|
|
+}
|
|
+static inline unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
|
|
+{
|
|
+ unsigned int limit = ent->LimitLow | (ent->HighWord.Bits.LimitHi << 16);
|
|
+ if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
|
|
+ return limit;
|
|
+}
|
|
+static inline void wine_ldt_set_flags( LDT_ENTRY *ent, unsigned char flags )
|
|
+{
|
|
+ ent->HighWord.Bits.Dpl = 3;
|
|
+ ent->HighWord.Bits.Pres = 1;
|
|
+ ent->HighWord.Bits.Type = flags;
|
|
+ ent->HighWord.Bits.Sys = 0;
|
|
+ ent->HighWord.Bits.Reserved_0 = 0;
|
|
+ ent->HighWord.Bits.Default_Big = (flags & WINE_LDT_FLAGS_32BIT) != 0;
|
|
+}
|
|
+static inline unsigned char wine_ldt_get_flags( const LDT_ENTRY *ent )
|
|
+{
|
|
+ unsigned char ret = ent->HighWord.Bits.Type;
|
|
+ if (ent->HighWord.Bits.Default_Big) ret |= WINE_LDT_FLAGS_32BIT;
|
|
+ return ret;
|
|
+}
|
|
+static inline int wine_ldt_is_empty( const LDT_ENTRY *ent )
|
|
+{
|
|
+ const DWORD *dw = (const DWORD *)ent;
|
|
+ return (dw[0] | dw[1]) == 0;
|
|
+}
|
|
+
|
|
+/* segment register access */
|
|
+
|
|
+# if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 2)))
|
|
+# define __DEFINE_GET_SEG(seg) \
|
|
+ static FORCEINLINE unsigned short wine_get_##seg(void) \
|
|
+ { unsigned short res; __asm__ __volatile__("movw %%" #seg ",%w0" : "=r"(res)); return res; }
|
|
+# define __DEFINE_SET_SEG(seg) \
|
|
+ static FORCEINLINE void wine_set_##seg(int val) \
|
|
+ { __asm__("movw %w0,%%" #seg : : "r" (val)); }
|
|
+# elif defined(_MSC_VER)
|
|
+# define __DEFINE_GET_SEG(seg) \
|
|
+ static inline unsigned short wine_get_##seg(void) \
|
|
+ { unsigned short res; __asm { mov res, seg } return res; }
|
|
+# define __DEFINE_SET_SEG(seg) \
|
|
+ static inline void wine_set_##seg(unsigned short val) { __asm { mov seg, val } }
|
|
+# else /* __GNUC__ || _MSC_VER */
|
|
+# define __DEFINE_GET_SEG(seg) extern unsigned short wine_get_##seg(void);
|
|
+# define __DEFINE_SET_SEG(seg) extern void wine_set_##seg(unsigned int);
|
|
+# endif /* __GNUC__ || _MSC_VER */
|
|
+
|
|
+__DEFINE_GET_SEG(cs)
|
|
+__DEFINE_GET_SEG(ds)
|
|
+__DEFINE_GET_SEG(es)
|
|
+__DEFINE_GET_SEG(fs)
|
|
+__DEFINE_GET_SEG(gs)
|
|
+__DEFINE_GET_SEG(ss)
|
|
+__DEFINE_SET_SEG(fs)
|
|
+__DEFINE_SET_SEG(gs)
|
|
+#undef __DEFINE_GET_SEG
|
|
+#undef __DEFINE_SET_SEG
|
|
+
|
|
+#endif /* __i386__ */
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
|
|
index a8f4925019..5fabd1968d 100644
|
|
--- a/libs/wine/ldt.c
|
|
+++ b/libs/wine/ldt.c
|
|
@@ -31,73 +31,11 @@
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
+#include "wine/library.h"
|
|
#include "wine/asm.h"
|
|
|
|
#ifdef __i386__
|
|
|
|
-#ifdef __ASM_OBSOLETE
|
|
-
|
|
-/* the local copy of the LDT */
|
|
-struct __wine_ldt_copy
|
|
-{
|
|
- void *base[8192]; /* base address or 0 if entry is free */
|
|
- unsigned long limit[8192]; /* limit in bytes or 0 if entry is free */
|
|
- unsigned char flags[8192]; /* flags (defined below) */
|
|
-} wine_ldt_copy_obsolete = { { 0, 0, 0 } };
|
|
-
|
|
-#define WINE_LDT_FLAGS_DATA 0x13 /* Data segment */
|
|
-#define WINE_LDT_FLAGS_STACK 0x17 /* Stack segment */
|
|
-#define WINE_LDT_FLAGS_CODE 0x1b /* Code segment */
|
|
-#define WINE_LDT_FLAGS_TYPE_MASK 0x1f /* Mask for segment type */
|
|
-#define WINE_LDT_FLAGS_32BIT 0x40 /* Segment is 32-bit (code or stack) */
|
|
-#define WINE_LDT_FLAGS_ALLOCATED 0x80 /* Segment is allocated (no longer free) */
|
|
-
|
|
-/* helper functions to manipulate the LDT_ENTRY structure */
|
|
-static inline void wine_ldt_set_base( LDT_ENTRY *ent, const void *base )
|
|
-{
|
|
- ent->BaseLow = (WORD)(ULONG_PTR)base;
|
|
- ent->HighWord.Bits.BaseMid = (BYTE)((ULONG_PTR)base >> 16);
|
|
- ent->HighWord.Bits.BaseHi = (BYTE)((ULONG_PTR)base >> 24);
|
|
-}
|
|
-static inline void wine_ldt_set_limit( LDT_ENTRY *ent, unsigned int limit )
|
|
-{
|
|
- if ((ent->HighWord.Bits.Granularity = (limit >= 0x100000))) limit >>= 12;
|
|
- ent->LimitLow = (WORD)limit;
|
|
- ent->HighWord.Bits.LimitHi = (limit >> 16);
|
|
-}
|
|
-static inline void *wine_ldt_get_base( const LDT_ENTRY *ent )
|
|
-{
|
|
- return (void *)(ent->BaseLow |
|
|
- (ULONG_PTR)ent->HighWord.Bits.BaseMid << 16 |
|
|
- (ULONG_PTR)ent->HighWord.Bits.BaseHi << 24);
|
|
-}
|
|
-static inline unsigned int wine_ldt_get_limit( const LDT_ENTRY *ent )
|
|
-{
|
|
- unsigned int limit = ent->LimitLow | (ent->HighWord.Bits.LimitHi << 16);
|
|
- if (ent->HighWord.Bits.Granularity) limit = (limit << 12) | 0xfff;
|
|
- return limit;
|
|
-}
|
|
-static inline void wine_ldt_set_flags( LDT_ENTRY *ent, unsigned char flags )
|
|
-{
|
|
- ent->HighWord.Bits.Dpl = 3;
|
|
- ent->HighWord.Bits.Pres = 1;
|
|
- ent->HighWord.Bits.Type = flags;
|
|
- ent->HighWord.Bits.Sys = 0;
|
|
- ent->HighWord.Bits.Reserved_0 = 0;
|
|
- ent->HighWord.Bits.Default_Big = (flags & WINE_LDT_FLAGS_32BIT) != 0;
|
|
-}
|
|
-static inline unsigned char wine_ldt_get_flags( const LDT_ENTRY *ent )
|
|
-{
|
|
- unsigned char ret = ent->HighWord.Bits.Type;
|
|
- if (ent->HighWord.Bits.Default_Big) ret |= WINE_LDT_FLAGS_32BIT;
|
|
- return ret;
|
|
-}
|
|
-static inline int wine_ldt_is_empty( const LDT_ENTRY *ent )
|
|
-{
|
|
- const DWORD *dw = (const DWORD *)ent;
|
|
- return (dw[0] | dw[1]) == 0;
|
|
-}
|
|
-
|
|
#ifdef __linux__
|
|
|
|
#ifdef HAVE_SYS_SYSCALL_H
|
|
@@ -164,6 +102,13 @@ static inline int set_thread_area( struct modify_ldt_s *ptr )
|
|
#include <i386/user_ldt.h>
|
|
#endif
|
|
|
|
+/* local copy of the LDT */
|
|
+#ifdef __APPLE__
|
|
+struct __wine_ldt_copy wine_ldt_copy = { { 0, 0, 0 } };
|
|
+#else
|
|
+struct __wine_ldt_copy wine_ldt_copy;
|
|
+#endif
|
|
+
|
|
static const LDT_ENTRY null_entry; /* all-zeros, used to clear LDT entries */
|
|
|
|
#define LDT_FIRST_ENTRY 512
|
|
@@ -183,7 +128,7 @@ static inline int is_gdt_sel( unsigned short sel ) { return !(sel & 4); }
|
|
*
|
|
* Set the LDT locking/unlocking functions.
|
|
*/
|
|
-void wine_ldt_init_locking_obsolete( void (*lock_func)(void), void (*unlock_func)(void) )
|
|
+void wine_ldt_init_locking( void (*lock_func)(void), void (*unlock_func)(void) )
|
|
{
|
|
lock_ldt = lock_func;
|
|
unlock_ldt = unlock_func;
|
|
@@ -195,7 +140,7 @@ void wine_ldt_init_locking_obsolete( void (*lock_func)(void), void (*unlock_func
|
|
*
|
|
* Retrieve an LDT entry. Return a null entry if selector is not allocated.
|
|
*/
|
|
-void wine_ldt_get_entry_obsolete( unsigned short sel, LDT_ENTRY *entry )
|
|
+void wine_ldt_get_entry( unsigned short sel, LDT_ENTRY *entry )
|
|
{
|
|
int index = sel >> 3;
|
|
|
|
@@ -205,11 +150,11 @@ void wine_ldt_get_entry_obsolete( unsigned short sel, LDT_ENTRY *entry )
|
|
return;
|
|
}
|
|
lock_ldt();
|
|
- if (wine_ldt_copy_obsolete.flags[index] & WINE_LDT_FLAGS_ALLOCATED)
|
|
+ if (wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_ALLOCATED)
|
|
{
|
|
- wine_ldt_set_base( entry, wine_ldt_copy_obsolete.base[index] );
|
|
- wine_ldt_set_limit( entry, wine_ldt_copy_obsolete.limit[index] );
|
|
- wine_ldt_set_flags( entry, wine_ldt_copy_obsolete.flags[index] );
|
|
+ wine_ldt_set_base( entry, wine_ldt_copy.base[index] );
|
|
+ wine_ldt_set_limit( entry, wine_ldt_copy.limit[index] );
|
|
+ wine_ldt_set_flags( entry, wine_ldt_copy.flags[index] );
|
|
}
|
|
else *entry = null_entry;
|
|
unlock_ldt();
|
|
@@ -274,9 +219,9 @@ static int internal_set_entry( unsigned short sel, const LDT_ENTRY *entry )
|
|
|
|
if (ret >= 0)
|
|
{
|
|
- wine_ldt_copy_obsolete.base[index] = wine_ldt_get_base(entry);
|
|
- wine_ldt_copy_obsolete.limit[index] = wine_ldt_get_limit(entry);
|
|
- wine_ldt_copy_obsolete.flags[index] = (entry->HighWord.Bits.Type |
|
|
+ wine_ldt_copy.base[index] = wine_ldt_get_base(entry);
|
|
+ wine_ldt_copy.limit[index] = wine_ldt_get_limit(entry);
|
|
+ wine_ldt_copy.flags[index] = (entry->HighWord.Bits.Type |
|
|
(entry->HighWord.Bits.Default_Big ? WINE_LDT_FLAGS_32BIT : 0) |
|
|
WINE_LDT_FLAGS_ALLOCATED);
|
|
}
|
|
@@ -289,7 +234,7 @@ static int internal_set_entry( unsigned short sel, const LDT_ENTRY *entry )
|
|
*
|
|
* Set an LDT entry.
|
|
*/
|
|
-int wine_ldt_set_entry_obsolete( unsigned short sel, const LDT_ENTRY *entry )
|
|
+int wine_ldt_set_entry( unsigned short sel, const LDT_ENTRY *entry )
|
|
{
|
|
int ret;
|
|
|
|
@@ -305,7 +250,7 @@ int wine_ldt_set_entry_obsolete( unsigned short sel, const LDT_ENTRY *entry )
|
|
*
|
|
* Check if the selector is a system selector (i.e. not managed by Wine).
|
|
*/
|
|
-int wine_ldt_is_system_obsolete( unsigned short sel )
|
|
+int wine_ldt_is_system( unsigned short sel )
|
|
{
|
|
return is_gdt_sel(sel) || ((sel >> 3) < LDT_FIRST_ENTRY);
|
|
}
|
|
@@ -317,7 +262,7 @@ int wine_ldt_is_system_obsolete( unsigned short sel )
|
|
* Convert a segment:offset pair to a linear pointer.
|
|
* Note: we don't lock the LDT since this has to be fast.
|
|
*/
|
|
-void *wine_ldt_get_ptr_obsolete( unsigned short sel, unsigned long offset )
|
|
+void *wine_ldt_get_ptr( unsigned short sel, unsigned long offset )
|
|
{
|
|
int index;
|
|
|
|
@@ -325,8 +270,8 @@ void *wine_ldt_get_ptr_obsolete( unsigned short sel, unsigned long offset )
|
|
return (void *)offset;
|
|
if ((index = (sel >> 3)) < LDT_FIRST_ENTRY) /* system selector */
|
|
return (void *)offset;
|
|
- if (!(wine_ldt_copy_obsolete.flags[index] & WINE_LDT_FLAGS_32BIT)) offset &= 0xffff;
|
|
- return (char *)wine_ldt_copy_obsolete.base[index] + offset;
|
|
+ if (!(wine_ldt_copy.flags[index] & WINE_LDT_FLAGS_32BIT)) offset &= 0xffff;
|
|
+ return (char *)wine_ldt_copy.base[index] + offset;
|
|
}
|
|
|
|
|
|
@@ -336,7 +281,7 @@ void *wine_ldt_get_ptr_obsolete( unsigned short sel, unsigned long offset )
|
|
* Allocate a number of consecutive ldt entries, without setting the LDT contents.
|
|
* Return a selector for the first entry.
|
|
*/
|
|
-unsigned short wine_ldt_alloc_entries_obsolete( int count )
|
|
+unsigned short wine_ldt_alloc_entries( int count )
|
|
{
|
|
int i, index, size = 0;
|
|
|
|
@@ -344,13 +289,13 @@ unsigned short wine_ldt_alloc_entries_obsolete( int count )
|
|
lock_ldt();
|
|
for (i = LDT_FIRST_ENTRY; i < LDT_SIZE; i++)
|
|
{
|
|
- if (wine_ldt_copy_obsolete.flags[i] & WINE_LDT_FLAGS_ALLOCATED) size = 0;
|
|
+ if (wine_ldt_copy.flags[i] & WINE_LDT_FLAGS_ALLOCATED) size = 0;
|
|
else if (++size >= count) /* found a large enough block */
|
|
{
|
|
index = i - size + 1;
|
|
|
|
/* mark selectors as allocated */
|
|
- for (i = 0; i < count; i++) wine_ldt_copy_obsolete.flags[index + i] |= WINE_LDT_FLAGS_ALLOCATED;
|
|
+ for (i = 0; i < count; i++) wine_ldt_copy.flags[index + i] |= WINE_LDT_FLAGS_ALLOCATED;
|
|
unlock_ldt();
|
|
return (index << 3) | 7;
|
|
}
|
|
@@ -360,15 +305,13 @@ unsigned short wine_ldt_alloc_entries_obsolete( int count )
|
|
}
|
|
|
|
|
|
-void wine_ldt_free_entries_obsolete( unsigned short sel, int count );
|
|
-
|
|
/***********************************************************************
|
|
* wine_ldt_realloc_entries
|
|
*
|
|
* Reallocate a number of consecutive ldt entries, without changing the LDT contents.
|
|
* Return a selector for the first entry.
|
|
*/
|
|
-unsigned short wine_ldt_realloc_entries_obsolete( unsigned short sel, int oldcount, int newcount )
|
|
+unsigned short wine_ldt_realloc_entries( unsigned short sel, int oldcount, int newcount )
|
|
{
|
|
int i;
|
|
|
|
@@ -381,23 +324,23 @@ unsigned short wine_ldt_realloc_entries_obsolete( unsigned short sel, int oldcou
|
|
if (index + newcount > LDT_SIZE) i = oldcount;
|
|
else
|
|
for (i = oldcount; i < newcount; i++)
|
|
- if (wine_ldt_copy_obsolete.flags[index+i] & WINE_LDT_FLAGS_ALLOCATED) break;
|
|
+ if (wine_ldt_copy.flags[index+i] & WINE_LDT_FLAGS_ALLOCATED) break;
|
|
|
|
if (i < newcount) /* they are not free */
|
|
{
|
|
- wine_ldt_free_entries_obsolete( sel, oldcount );
|
|
- sel = wine_ldt_alloc_entries_obsolete( newcount );
|
|
+ wine_ldt_free_entries( sel, oldcount );
|
|
+ sel = wine_ldt_alloc_entries( newcount );
|
|
}
|
|
else /* mark the selectors as allocated */
|
|
{
|
|
for (i = oldcount; i < newcount; i++)
|
|
- wine_ldt_copy_obsolete.flags[index+i] |= WINE_LDT_FLAGS_ALLOCATED;
|
|
+ wine_ldt_copy.flags[index+i] |= WINE_LDT_FLAGS_ALLOCATED;
|
|
}
|
|
unlock_ldt();
|
|
}
|
|
else if (oldcount > newcount) /* we need to remove selectors */
|
|
{
|
|
- wine_ldt_free_entries_obsolete( sel + (newcount << 3), newcount - oldcount );
|
|
+ wine_ldt_free_entries( sel + (newcount << 3), newcount - oldcount );
|
|
}
|
|
return sel;
|
|
}
|
|
@@ -408,7 +351,7 @@ unsigned short wine_ldt_realloc_entries_obsolete( unsigned short sel, int oldcou
|
|
*
|
|
* Free a number of consecutive ldt entries and clear their contents.
|
|
*/
|
|
-void wine_ldt_free_entries_obsolete( unsigned short sel, int count )
|
|
+void wine_ldt_free_entries( unsigned short sel, int count )
|
|
{
|
|
int index;
|
|
|
|
@@ -416,7 +359,7 @@ void wine_ldt_free_entries_obsolete( unsigned short sel, int count )
|
|
for (index = sel >> 3; count > 0; count--, index++)
|
|
{
|
|
internal_set_entry( sel, &null_entry );
|
|
- wine_ldt_copy_obsolete.flags[index] = 0;
|
|
+ wine_ldt_copy.flags[index] = 0;
|
|
}
|
|
unlock_ldt();
|
|
}
|
|
@@ -430,7 +373,7 @@ static int global_fs_sel = -1; /* global selector for %fs shared among all thre
|
|
* Allocate an LDT entry for a %fs selector, reusing a global
|
|
* GDT selector if possible. Return the selector value.
|
|
*/
|
|
-unsigned short wine_ldt_alloc_fs_obsolete(void)
|
|
+unsigned short wine_ldt_alloc_fs(void)
|
|
{
|
|
if (global_fs_sel == -1)
|
|
{
|
|
@@ -457,7 +400,7 @@ unsigned short wine_ldt_alloc_fs_obsolete(void)
|
|
#endif
|
|
}
|
|
if (global_fs_sel > 0) return global_fs_sel;
|
|
- return wine_ldt_alloc_entries_obsolete( 1 );
|
|
+ return wine_ldt_alloc_entries( 1 );
|
|
}
|
|
|
|
|
|
@@ -469,7 +412,7 @@ unsigned short wine_ldt_alloc_fs_obsolete(void)
|
|
*
|
|
* Note: this runs in the context of the new thread, so cannot acquire locks.
|
|
*/
|
|
-void wine_ldt_init_fs_obsolete( unsigned short sel, const LDT_ENTRY *entry )
|
|
+void wine_ldt_init_fs( unsigned short sel, const LDT_ENTRY *entry )
|
|
{
|
|
if ((sel & ~3) == (global_fs_sel & ~3))
|
|
{
|
|
@@ -497,7 +440,7 @@ void wine_ldt_init_fs_obsolete( unsigned short sel, const LDT_ENTRY *entry )
|
|
*
|
|
* Free a %fs selector returned by wine_ldt_alloc_fs.
|
|
*/
|
|
-void wine_ldt_free_fs_obsolete( unsigned short sel )
|
|
+void wine_ldt_free_fs( unsigned short sel )
|
|
{
|
|
WORD fs;
|
|
|
|
@@ -508,46 +451,22 @@ void wine_ldt_free_fs_obsolete( unsigned short sel )
|
|
/* FIXME: if freeing current %fs we cannot acquire locks */
|
|
__asm__( "mov %0,%%fs" :: "r" (0) );
|
|
internal_set_entry( sel, &null_entry );
|
|
- wine_ldt_copy_obsolete.flags[sel >> 3] = 0;
|
|
+ wine_ldt_copy.flags[sel >> 3] = 0;
|
|
}
|
|
- else wine_ldt_free_entries_obsolete( sel, 1 );
|
|
+ else wine_ldt_free_entries( sel, 1 );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* selector access functions
|
|
*/
|
|
-__ASM_GLOBAL_FUNC( wine_get_cs_obsolete, "movw %cs,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_get_ds_obsolete, "movw %ds,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_get_es_obsolete, "movw %es,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_get_fs_obsolete, "movw %fs,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_get_gs_obsolete, "movw %gs,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_get_ss_obsolete, "movw %ss,%ax\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_set_fs_obsolete, "movl 4(%esp),%eax\n\tmovw %ax,%fs\n\tret" )
|
|
-__ASM_GLOBAL_FUNC( wine_set_gs_obsolete, "movl 4(%esp),%eax\n\tmovw %ax,%gs\n\tret" )
|
|
-
|
|
-
|
|
-__ASM_OBSOLETE(wine_ldt_alloc_entries);
|
|
-__ASM_OBSOLETE(wine_ldt_alloc_fs);
|
|
-__ASM_OBSOLETE(wine_ldt_copy);
|
|
-__ASM_OBSOLETE(wine_ldt_free_entries);
|
|
-__ASM_OBSOLETE(wine_ldt_free_fs);
|
|
-__ASM_OBSOLETE(wine_ldt_get_entry);
|
|
-__ASM_OBSOLETE(wine_ldt_get_ptr);
|
|
-__ASM_OBSOLETE(wine_ldt_init_fs);
|
|
-__ASM_OBSOLETE(wine_ldt_init_locking);
|
|
-__ASM_OBSOLETE(wine_ldt_is_system);
|
|
-__ASM_OBSOLETE(wine_ldt_realloc_entries);
|
|
-__ASM_OBSOLETE(wine_ldt_set_entry);
|
|
-__ASM_OBSOLETE(wine_get_cs);
|
|
-__ASM_OBSOLETE(wine_get_ds);
|
|
-__ASM_OBSOLETE(wine_get_es);
|
|
-__ASM_OBSOLETE(wine_get_fs);
|
|
-__ASM_OBSOLETE(wine_get_gs);
|
|
-__ASM_OBSOLETE(wine_get_ss);
|
|
-__ASM_OBSOLETE(wine_set_fs);
|
|
-__ASM_OBSOLETE(wine_set_gs);
|
|
-
|
|
-#endif /* __ASM_OBSOLETE */
|
|
+__ASM_GLOBAL_FUNC( wine_get_cs, "movw %cs,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_get_ds, "movw %ds,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_get_es, "movw %es,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_get_fs, "movw %fs,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_get_gs, "movw %gs,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_get_ss, "movw %ss,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_set_fs, "movl 4(%esp),%eax\n\tmovw %ax,%fs\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_set_gs, "movl 4(%esp),%eax\n\tmovw %ax,%gs\n\tret" )
|
|
|
|
#endif /* __i386__ */
|
|
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
|
|
index 7ea849b908..3f2c430fa8 100644
|
|
--- a/libs/wine/wine.map
|
|
+++ b/libs/wine/wine.map
|
|
@@ -18,21 +18,41 @@ WINE_1.0
|
|
wine_get_build_dir;
|
|
wine_get_build_id;
|
|
wine_get_config_dir;
|
|
+ wine_get_cs;
|
|
wine_get_data_dir;
|
|
+ wine_get_ds;
|
|
+ wine_get_es;
|
|
+ wine_get_fs;
|
|
+ wine_get_gs;
|
|
wine_get_server_dir;
|
|
+ wine_get_ss;
|
|
wine_get_user_name;
|
|
wine_get_version;
|
|
wine_get_patches;
|
|
wine_init;
|
|
wine_init_argv0_path;
|
|
+ wine_ldt_alloc_entries;
|
|
+ wine_ldt_alloc_fs;
|
|
+ wine_ldt_copy;
|
|
+ wine_ldt_free_entries;
|
|
+ wine_ldt_free_fs;
|
|
+ wine_ldt_get_entry;
|
|
+ wine_ldt_get_ptr;
|
|
+ wine_ldt_init_fs;
|
|
+ wine_ldt_init_locking;
|
|
+ wine_ldt_is_system;
|
|
+ wine_ldt_realloc_entries;
|
|
+ wine_ldt_set_entry;
|
|
wine_mmap_add_reserved_area;
|
|
wine_mmap_enum_reserved_areas;
|
|
wine_mmap_is_in_reserved_area;
|
|
wine_mmap_remove_reserved_area;
|
|
wine_mmap_add_free_area;
|
|
wine_mmap_enum_free_areas;
|
|
wine_mmap_is_in_free_area;
|
|
wine_mmap_remove_free_area;
|
|
+ wine_set_fs;
|
|
+ wine_set_gs;
|
|
wine_wctype_table;
|
|
|
|
/* the following functions are obsolete and only exported for backwards compatibility */
|
|
@@ -93,30 +113,10 @@ WINE_1.0
|
|
wine_dll_load_main_exe;
|
|
wine_dll_unload;
|
|
wine_fold_string;
|
|
- wine_get_cs;
|
|
- wine_get_ds;
|
|
- wine_get_es;
|
|
- wine_get_fs;
|
|
- wine_get_gs;
|
|
wine_get_sortkey;
|
|
- wine_get_ss;
|
|
wine_is_dbcs_leadbyte;
|
|
- wine_ldt_alloc_entries;
|
|
- wine_ldt_alloc_fs;
|
|
- wine_ldt_copy;
|
|
- wine_ldt_free_entries;
|
|
- wine_ldt_free_fs;
|
|
- wine_ldt_get_entry;
|
|
- wine_ldt_get_ptr;
|
|
- wine_ldt_init_fs;
|
|
- wine_ldt_init_locking;
|
|
- wine_ldt_is_system;
|
|
- wine_ldt_realloc_entries;
|
|
- wine_ldt_set_entry;
|
|
wine_pthread_get_functions;
|
|
wine_pthread_set_functions;
|
|
- wine_set_fs;
|
|
- wine_set_gs;
|
|
wine_switch_to_stack;
|
|
wine_utf8_mbstowcs;
|
|
wine_utf8_wcstombs;
|
|
|
|
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
|
|
index abdc0efc51..411abb86d8 100644
|
|
--- a/dlls/ntdll/signal_i386.c
|
|
+++ b/dlls/ntdll/signal_i386.c
|
|
@@ -437,6 +437,8 @@ static wine_signal_handler handlers[256];
|
|
extern void DECLSPEC_NORETURN __wine_syscall_dispatcher( void );
|
|
extern NTSTATUS WINAPI __syscall_NtGetContextThread( HANDLE handle, CONTEXT *context );
|
|
|
|
+static int wine_cs;
|
|
+
|
|
static void* WINAPI __wine_fakedll_dispatcher( const char *module, ULONG ord )
|
|
{
|
|
UNICODE_STRING name;
|
|
@@ -885,7 +887,7 @@ static inline void * SIGNALFUNC init_handler( const ucontext_t *sigcontext, WORD
|
|
}
|
|
#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)))
|
|
{
|
|
/*
|
|
* Win16 or DOS protected mode. Note that during switch
|
|
@@ -1576,7 +1578,7 @@ static inline DWORD is_privileged_instr( CONTEXT *context )
|
|
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])
|
|
@@ -1674,7 +1676,7 @@ static inline BOOL check_invalid_gs( CONTEXT *context )
|
|
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 0;
|
|
/* only handle faults in system libraries */
|
|
if (virtual_is_valid_code_address( instr, 1 )) return FALSE;
|
|
|
|
@@ -1916,7 +1918,7 @@ static EXCEPTION_RECORD *setup_exception_record( ucontext_t *sigcontext, void *s
|
|
EIP_sig(sigcontext) = (DWORD)func;
|
|
/* 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_es();
|
|
FS_sig(sigcontext) = get_fs();
|
|
@@ -2394,6 +2396,21 @@ static void ldt_unlock(void)
|
|
else RtlLeaveCriticalSection( &ldt_section );
|
|
}
|
|
|
|
+void signal_init_cs(void)
|
|
+{
|
|
+ LDT_ENTRY entry;
|
|
+
|
|
+ if (!wine_cs)
|
|
+ wine_cs = wine_ldt_alloc_entries( 1 );
|
|
+
|
|
+ wine_ldt_set_base( &entry, 0 );
|
|
+ wine_ldt_set_limit( &entry, (UINT_PTR)-1 );
|
|
+ wine_ldt_set_flags( &entry, WINE_LDT_FLAGS_CODE|WINE_LDT_FLAGS_32BIT );
|
|
+ wine_ldt_set_entry( wine_cs, &entry );
|
|
+
|
|
+ wine_set_cs( wine_cs );
|
|
+}
|
|
+
|
|
|
|
/**********************************************************************
|
|
* signal_alloc_thread
|
|
@@ -2433,6 +2450,9 @@ NTSTATUS signal_alloc_thread( TEB **teb )
|
|
status = STATUS_TOO_MANY_THREADS;
|
|
}
|
|
}
|
|
+
|
|
+ signal_init_cs();
|
|
+
|
|
return status;
|
|
}
|
|
|
|
diff --git a/include/wine/library.h b/include/wine/library.h
|
|
index 7395a117c7..56e749033e 100644
|
|
--- a/include/wine/library.h
|
|
+++ b/include/wine/library.h
|
|
@@ -192,6 +192,7 @@ __DEFINE_SET_SEG(fs)
|
|
__DEFINE_SET_SEG(gs)
|
|
#undef __DEFINE_GET_SEG
|
|
#undef __DEFINE_SET_SEG
|
|
+extern void wine_set_cs(unsigned int);
|
|
|
|
#endif /* __i386__ */
|
|
|
|
diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
|
|
index b9371814ba..21e9f0528b 100644
|
|
--- a/libs/wine/ldt.c
|
|
+++ b/libs/wine/ldt.c
|
|
@@ -461,6 +461,10 @@ __ASM_GLOBAL_FUNC( wine_get_es, "movw %es,%ax\n\tret" )
|
|
__ASM_GLOBAL_FUNC( wine_get_fs, "movw %fs,%ax\n\tret" )
|
|
__ASM_GLOBAL_FUNC( wine_get_gs, "movw %gs,%ax\n\tret" )
|
|
__ASM_GLOBAL_FUNC( wine_get_ss, "movw %ss,%ax\n\tret" )
|
|
+__ASM_GLOBAL_FUNC( wine_set_cs, "movl 4(%esp),%eax\n\t"
|
|
+ "xchg 0(%esp),%eax\n\t"
|
|
+ "push %eax\n\t"
|
|
+ "retf" )
|
|
__ASM_GLOBAL_FUNC( wine_set_fs, "movl 4(%esp),%eax\n\tmovw %ax,%fs\n\tret" )
|
|
__ASM_GLOBAL_FUNC( wine_set_gs, "movl 4(%esp),%eax\n\tmovw %ax,%gs\n\tret" )
|
|
|
|
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
|
|
index 72ffed80c0..c41f567fb6 100644
|
|
--- a/libs/wine/wine.map
|
|
+++ b/libs/wine/wine.map
|
|
@@ -114,6 +114,7 @@ WINE_1.0
|
|
wine_mmap_enum_free_areas;
|
|
wine_mmap_is_in_free_area;
|
|
wine_mmap_remove_free_area;
|
|
+ wine_set_cs;
|
|
wine_set_fs;
|
|
wine_set_gs;
|
|
wine_utf8_mbstowcs;
|
|
|