Commit 94d74b5f authored by Alexandre Julliard's avatar Alexandre Julliard

Added support for managing reserved memory areas in libwine and ntdll.

Try to reserve everything above 0x80000000 on startup.
parent 307edcca
...@@ -1116,8 +1116,6 @@ void __wine_kernel_init(void) ...@@ -1116,8 +1116,6 @@ void __wine_kernel_init(void)
} }
found: found:
wine_free_pe_load_area(); /* the main binary is loaded, we don't need this anymore */
/* build command line */ /* build command line */
set_library_wargv( __wine_main_argv ); set_library_wargv( __wine_main_argv );
if (!build_command_line( __wine_main_wargv )) goto error; if (!build_command_line( __wine_main_wargv )) goto error;
......
...@@ -70,10 +70,16 @@ extern int wine_dbg_parse_options( const char *str ); ...@@ -70,10 +70,16 @@ extern int wine_dbg_parse_options( const char *str );
/* portability */ /* portability */
extern void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack ); extern void DECLSPEC_NORETURN wine_switch_to_stack( void (*func)(void *), void *arg, void *stack );
extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
extern void wine_set_pe_load_area( void *base, size_t size ); extern void wine_set_pe_load_area( void *base, size_t size );
extern void wine_free_pe_load_area(void); extern void wine_free_pe_load_area(void);
/* memory mappings */
extern void *wine_anon_mmap( void *start, size_t size, int prot, int flags );
extern void wine_mmap_add_reserved_area( void *addr, size_t size );
extern void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap );
extern int wine_mmap_is_in_reserved_area( void *addr, size_t size );
/* LDT management */ /* LDT management */
extern void wine_ldt_init_locking( void (*lock_func)(void), void (*unlock_func)(void) ); extern void wine_ldt_init_locking( void (*lock_func)(void), void (*unlock_func)(void) );
......
...@@ -13,6 +13,7 @@ C_SRCS = \ ...@@ -13,6 +13,7 @@ C_SRCS = \
debug.c \ debug.c \
ldt.c \ ldt.c \
loader.c \ loader.c \
mmap.c \
port.c port.c
@MAKE_LIB_RULES@ @MAKE_LIB_RULES@
......
...@@ -71,6 +71,7 @@ static const char **dll_paths; ...@@ -71,6 +71,7 @@ static const char **dll_paths;
static int nb_dll_paths; static int nb_dll_paths;
static int dll_path_maxlen; static int dll_path_maxlen;
extern void mmap_init(void);
/* build the dll load path from the WINEDLLPATH variable */ /* build the dll load path from the WINEDLLPATH variable */
static void build_dll_path(void) static void build_dll_path(void)
...@@ -516,6 +517,7 @@ void wine_init( int argc, char *argv[], char *error, int error_size ) ...@@ -516,6 +517,7 @@ void wine_init( int argc, char *argv[], char *error, int error_size )
__wine_main_argc = argc; __wine_main_argc = argc;
__wine_main_argv = argv; __wine_main_argv = argv;
__wine_main_environ = environ; __wine_main_environ = environ;
mmap_init();
if ((wine_debug = getenv("WINEDEBUG"))) if ((wine_debug = getenv("WINEDEBUG")))
{ {
......
...@@ -21,21 +21,9 @@ ...@@ -21,21 +21,9 @@
#include "config.h" #include "config.h"
#include "wine/port.h" #include "wine/port.h"
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "wine/library.h" #include "wine/library.h"
#include "wine/pthread.h" #include "wine/pthread.h"
...@@ -149,173 +137,3 @@ __ASM_GLOBAL_FUNC( wine_switch_to_stack, ...@@ -149,173 +137,3 @@ __ASM_GLOBAL_FUNC( wine_switch_to_stack,
#else #else
#error You must implement wine_switch_to_stack for your platform #error You must implement wine_switch_to_stack for your platform
#endif #endif
static char *pe_area;
static size_t pe_area_size;
/***********************************************************************
* wine_set_pe_load_area
*
* Define the reserved area to use for loading the main PE binary.
*/
void wine_set_pe_load_area( void *base, size_t size )
{
unsigned int page_mask = getpagesize() - 1;
char *end = (char *)base + size;
pe_area = (char *)(((unsigned long)base + page_mask) & ~page_mask);
pe_area_size = (end - pe_area) & ~page_mask;
}
/***********************************************************************
* wine_free_pe_load_area
*
* Free the reserved area to use for loading the main PE binary.
*/
void wine_free_pe_load_area(void)
{
#ifdef HAVE_MMAP
if (pe_area) munmap( pe_area, pe_area_size );
#endif
pe_area = NULL;
}
#if (defined(__svr4__) || defined(__NetBSD__)) && !defined(MAP_TRYFIXED)
/***********************************************************************
* try_mmap_fixed
*
* The purpose of this routine is to emulate the behaviour of
* the Linux mmap() routine if a non-NULL address is passed,
* but the MAP_FIXED flag is not set. Linux in this case tries
* to place the mapping at the specified address, *unless* the
* range is already in use. Solaris, however, completely ignores
* the address argument in this case.
*
* As Wine code occasionally relies on the Linux behaviour, e.g. to
* be able to map non-relocateable PE executables to their proper
* start addresses, or to map the DOS memory to 0, this routine
* emulates the Linux behaviour by checking whether the desired
* address range is still available, and placing the mapping there
* using MAP_FIXED if so.
*/
static int try_mmap_fixed (void *addr, size_t len, int prot, int flags,
int fildes, off_t off)
{
char * volatile result = NULL;
int pagesize = getpagesize();
pid_t pid;
/* We only try to map to a fixed address if
addr is non-NULL and properly aligned,
and MAP_FIXED isn't already specified. */
if ( !addr )
return 0;
if ( (uintptr_t)addr & (pagesize-1) )
return 0;
if ( flags & MAP_FIXED )
return 0;
/* We use vfork() to freeze all threads of the
current process. This allows us to check without
race condition whether the desired memory range is
already in use. Note that because vfork() shares
the address spaces between parent and child, we
can actually perform the mapping in the child. */
if ( (pid = vfork()) == -1 )
{
perror("try_mmap_fixed: vfork");
exit(1);
}
if ( pid == 0 )
{
int i;
char vec;
/* We call mincore() for every page in the desired range.
If any of these calls succeeds, the page is already
mapped and we must fail. */
for ( i = 0; i < len; i += pagesize )
if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
_exit(1);
/* Perform the mapping with MAP_FIXED set. This is safe
now, as none of the pages is currently in use. */
result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
if ( result == addr )
_exit(0);
if ( result != (void *) -1 ) /* This should never happen ... */
munmap( result, len );
_exit(1);
}
/* vfork() lets the parent continue only after the child
has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
so we don't need to wait for the child. */
return result == addr;
}
#endif /* (__svr4__ || __NetBSD__) && !MAP_TRYFIXED */
/***********************************************************************
* wine_anon_mmap
*
* Portable wrapper for anonymous mmaps
*/
void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
{
#ifdef HAVE_MMAP
static int fdzero = -1;
#ifdef MAP_ANON
flags |= MAP_ANON;
#else
if (fdzero == -1)
{
if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
{
perror( "/dev/zero: open" );
exit(1);
}
}
#endif /* MAP_ANON */
#ifdef MAP_SHARED
flags &= ~MAP_SHARED;
#endif
/* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
#ifdef MAP_PRIVATE
flags |= MAP_PRIVATE;
#endif
if (pe_area && start &&
(char *)start >= pe_area &&
(char *)start + size <= pe_area + pe_area_size)
{
wine_free_pe_load_area();
flags |= MAP_FIXED;
}
if (!(flags & MAP_FIXED))
{
#ifdef MAP_TRYFIXED
/* If available, this will attempt a fixed mapping in-kernel */
flags |= MAP_TRYFIXED;
#elif defined(__svr4__) || defined(__NetBSD__)
if ( try_mmap_fixed( start, size, prot, flags, fdzero, 0 ) )
return start;
#endif
}
return mmap( start, size, prot, flags, fdzero, 0 );
#else
return (void *)-1;
#endif
}
...@@ -32,7 +32,6 @@ EXPORTS ...@@ -32,7 +32,6 @@ EXPORTS
wine_dlopen wine_dlopen
wine_dlsym wine_dlsym
wine_exec_wine_binary wine_exec_wine_binary
wine_free_pe_load_area
wine_get_config_dir wine_get_config_dir
wine_get_cs wine_get_cs
wine_get_ds wine_get_ds
...@@ -56,6 +55,9 @@ EXPORTS ...@@ -56,6 +55,9 @@ EXPORTS
wine_ldt_is_system wine_ldt_is_system
wine_ldt_realloc_entries wine_ldt_realloc_entries
wine_ldt_set_entry wine_ldt_set_entry
wine_mmap_add_reserved_area
wine_mmap_is_in_reserved_area
wine_mmap_remove_reserved_area
wine_pthread_abort_thread wine_pthread_abort_thread
wine_pthread_create_thread wine_pthread_create_thread
wine_pthread_exit_thread wine_pthread_exit_thread
...@@ -64,5 +66,4 @@ EXPORTS ...@@ -64,5 +66,4 @@ EXPORTS
wine_pthread_init_thread wine_pthread_init_thread
wine_set_fs wine_set_fs
wine_set_gs wine_set_gs
wine_set_pe_load_area
wine_switch_to_stack wine_switch_to_stack
...@@ -32,7 +32,6 @@ WINE_1.0 ...@@ -32,7 +32,6 @@ WINE_1.0
wine_dlopen; wine_dlopen;
wine_dlsym; wine_dlsym;
wine_exec_wine_binary; wine_exec_wine_binary;
wine_free_pe_load_area;
wine_get_config_dir; wine_get_config_dir;
wine_get_cs; wine_get_cs;
wine_get_ds; wine_get_ds;
...@@ -56,6 +55,9 @@ WINE_1.0 ...@@ -56,6 +55,9 @@ WINE_1.0
wine_ldt_is_system; wine_ldt_is_system;
wine_ldt_realloc_entries; wine_ldt_realloc_entries;
wine_ldt_set_entry; wine_ldt_set_entry;
wine_mmap_add_reserved_area;
wine_mmap_is_in_reserved_area;
wine_mmap_remove_reserved_area;
wine_pthread_abort_thread; wine_pthread_abort_thread;
wine_pthread_create_thread; wine_pthread_create_thread;
wine_pthread_exit_thread; wine_pthread_exit_thread;
...@@ -64,7 +66,6 @@ WINE_1.0 ...@@ -64,7 +66,6 @@ WINE_1.0
wine_pthread_init_thread; wine_pthread_init_thread;
wine_set_fs; wine_set_fs;
wine_set_gs; wine_set_gs;
wine_set_pe_load_area;
wine_switch_to_stack; wine_switch_to_stack;
local: *; local: *;
......
...@@ -29,11 +29,6 @@ int main( int argc, char *argv[] ) ...@@ -29,11 +29,6 @@ int main( int argc, char *argv[] )
{ {
char error[1024]; char error[1024];
#if 0
static char pe_load[256*1024*1024] __attribute__((aligned(4096)));
wine_set_pe_load_area( pe_load, sizeof(pe_load) );
#endif
wine_init( argc, argv, error, sizeof(error) ); wine_init( argc, argv, error, sizeof(error) );
fprintf( stderr, "wine: failed to initialize: %s\n", error ); fprintf( stderr, "wine: failed to initialize: %s\n", error );
exit(1); exit(1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment