Alexandre Julliard : preloader: Setup a fake thread-local storage block pointed to by %gs.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Nov 3 07:32:43 CST 2006


Module: wine
Branch: master
Commit: a68d293bae6cec6deafafb94972c9277791256b5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a68d293bae6cec6deafafb94972c9277791256b5

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Nov  3 13:55:41 2006 +0100

preloader: Setup a fake thread-local storage block pointed to by %gs.

---

 libs/wine/ldt.c    |    4 ++++
 loader/preloader.c |   32 +++++++++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletions(-)

diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c
index 0613c83..ceb8db4 100644
--- a/libs/wine/ldt.c
+++ b/libs/wine/ldt.c
@@ -405,6 +405,10 @@ #ifdef __linux__
         struct modify_ldt_s ldt_info;
         int ret;
 
+        /* the preloader may have allocated it already */
+        global_fs_sel = wine_get_fs();
+        if (global_fs_sel && is_gdt_sel(global_fs_sel)) return global_fs_sel;
+
         ldt_info.entry_number = -1;
         fill_modify_ldt_struct( &ldt_info, &null_entry );
         if ((ret = set_thread_area( &ldt_info ) < 0))
diff --git a/loader/preloader.c b/loader/preloader.c
index 7140f3a..bd303da 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -163,6 +163,26 @@ void __bb_init_func(void) { return; }
 void *__stack_chk_guard = 0;
 void __stack_chk_fail(void) { return; }
 
+/* data for setting up the glibc-style thread-local storage in %gs */
+
+static int thread_data[256];
+
+struct
+{
+    /* this is the kernel modify_ldt struct */
+    unsigned int  entry_number;
+    unsigned long base_addr;
+    unsigned int  limit;
+    unsigned int  seg_32bit : 1;
+    unsigned int  contents : 2;
+    unsigned int  read_exec_only : 1;
+    unsigned int  limit_in_pages : 1;
+    unsigned int  seg_not_present : 1;
+    unsigned int  useable : 1;
+    unsigned int  garbage : 25;
+} thread_ldt = { -1, (unsigned long)thread_data, 0xfffff, 1, 0, 0, 1, 0, 1, 0 };
+
+
 /*
  * The _start function is the entry and exit point of this program
  *
@@ -172,7 +192,17 @@ void __stack_chk_fail(void) { return; }
 void _start();
 extern char _end[];
 __ASM_GLOBAL_FUNC(_start,
-                  "\tmovl %esp,%eax\n"
+                  "\tmovl $243,%eax\n"        /* SYS_set_thread_area */
+                  "\tmovl $thread_ldt,%ebx\n"
+                  "\tint $0x80\n"             /* allocate gs segment */
+                  "\torl %eax,%eax\n"
+                  "\tjl 1f\n"
+                  "\tmovl thread_ldt,%eax\n"  /* thread_ldt.entry_number */
+                  "\tshl $3,%eax\n"
+                  "\torl $3,%eax\n"
+                  "\tmov %ax,%gs\n"
+                  "\tmov %ax,%fs\n"           /* set %fs too so libwine can retrieve it later on */
+                  "1:\tmovl %esp,%eax\n"
                   "\tleal -136(%esp),%esp\n"  /* allocate some space for extra aux values */
                   "\tpushl %eax\n"            /* orig stack pointer */
                   "\tpushl %esp\n"            /* ptr to orig stack pointer */




More information about the wine-cvs mailing list