diff --git a/libs/wine/ldt.c b/libs/wine/ldt.c index 0613c83c79d..ceb8db423f8 100644 --- a/libs/wine/ldt.c +++ b/libs/wine/ldt.c @@ -405,6 +405,10 @@ unsigned short wine_ldt_alloc_fs(void) 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 7140f3a7884..bd303da979c 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 */