diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | loader/ext.c | 73 | ||||
-rw-r--r-- | loader/ldt_keeper.c | 6 | ||||
-rw-r--r-- | osdep/Makefile | 1 | ||||
-rw-r--r-- | osdep/mmap_anon.c | 67 | ||||
-rw-r--r-- | osdep/mmap_anon.h | 8 |
6 files changed, 104 insertions, 54 deletions
@@ -62,7 +62,6 @@ COMMON_LIBS = libmpcodecs/libmpcodecs.a \ stream/stream.a \ libswscale/libswscale.a \ libvo/libosd.a \ - osdep/libosdep.a \ LIBS_MPLAYER = libvo/libvo.a \ libao2/libao2.a \ @@ -158,6 +157,8 @@ ifeq ($(TARGET_WIN32),yes) OBJS_MPLAYER += osdep/mplayer-rc.o endif +COMMON_LIBS += osdep/libosdep.a + COMMON_LDFLAGS += $(EXTRA_LIB)\ $(EXTRALIBS) \ diff --git a/loader/ext.c b/loader/ext.c index 4121da29bf..65de0e9afa 100644 --- a/loader/ext.c +++ b/loader/ext.c @@ -26,6 +26,7 @@ #include <stdarg.h> #include <ctype.h> +#include "osdep/mmap_anon.h" #include "wine/windef.h" #include "wine/winbase.h" #include "wine/debugtools.h" @@ -233,7 +234,6 @@ LPSTR HEAP_strdupWtoA(HANDLE heap, DWORD flags, LPCWSTR string) //#define MAP_PRIVATE //#define MAP_SHARED -#undef MAP_ANON LPVOID FILE_dommap( int unix_handle, LPVOID start, DWORD size_high, DWORD size_low, DWORD offset_high, DWORD offset_low, @@ -248,36 +248,15 @@ LPVOID FILE_dommap( int unix_handle, LPVOID start, if (unix_handle == -1) { -#ifdef MAP_ANON -// printf("Anonymous\n"); - flags |= MAP_ANON; -#else - static int fdzero = -1; - - if (fdzero == -1) - { - if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1) - { - perror( "Cannot open /dev/zero for READ. Check permissions! error: " ); - exit(1); - } - } - fd = fdzero; -#endif /* MAP_ANON */ - /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */ -#ifdef MAP_SHARED - flags &= ~MAP_SHARED; -#endif -#ifdef MAP_PRIVATE - flags |= MAP_PRIVATE; -#endif + ret = mmap_anon( start, size_low, prot, flags, &fd, offset_low ); } - else fd = unix_handle; -// printf("fd %x, start %x, size %x, pos %x, prot %x\n",fd,start,size_low, offset_low, prot); -// if ((ret = mmap( start, size_low, prot, -// flags, fd, offset_low )) != (LPVOID)-1) - if ((ret = mmap( start, size_low, prot, - MAP_PRIVATE | MAP_FIXED, fd, offset_low )) != (LPVOID)-1) + else + { + fd = unix_handle; + ret = mmap( start, size_low, prot, flags, fd, offset_low ); + } + + if (ret != (LPVOID)-1) { // printf("address %08x\n", *(int*)ret); // printf("%x\n", ret); @@ -371,14 +350,8 @@ HANDLE WINAPI CreateFileMappingA(HANDLE handle, LPSECURITY_ATTRIBUTES lpAttr, int anon=0; int mmap_access=0; if(hFile<0) - { - anon=1; - hFile=open("/dev/zero", O_RDWR); - if(hFile<0){ - perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " ); - return 0; - } - } + anon=1; + if(!anon) { len=lseek(hFile, 0, SEEK_END); @@ -391,8 +364,12 @@ HANDLE WINAPI CreateFileMappingA(HANDLE handle, LPSECURITY_ATTRIBUTES lpAttr, else mmap_access |=PROT_READ|PROT_WRITE; - answer=mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0); if(anon) + answer=mmap_anon(NULL, len, mmap_access, MAP_PRIVATE, &hFile, 0); + else + answer=mmap(NULL, len, mmap_access, MAP_PRIVATE, hFile, 0); + + if(hFile != -1) close(hFile); if(answer!=(LPVOID)-1) { @@ -418,7 +395,7 @@ HANDLE WINAPI CreateFileMappingA(HANDLE handle, LPSECURITY_ATTRIBUTES lpAttr, fm->name=NULL; fm->mapping_size=len; - if(anon) + if(hFile != -1) close(hFile); return (HANDLE)answer; } @@ -471,12 +448,6 @@ LPVOID WINAPI VirtualAlloc(LPVOID address, DWORD size, DWORD type, DWORD protec if ((type&(MEM_RESERVE|MEM_COMMIT)) == 0) return NULL; - fd=open("/dev/zero", O_RDWR); - if(fd<0){ - perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " ); - return NULL; - } - if (type&MEM_RESERVE && (unsigned)address&0xffff) { size += (unsigned)address&0xffff; address = (unsigned)address&~0xffff; @@ -513,23 +484,23 @@ LPVOID WINAPI VirtualAlloc(LPVOID address, DWORD size, DWORD type, DWORD protec && ((unsigned)address+size<=(unsigned)str->address+str->mapping_size) && (type & MEM_COMMIT)) { - close(fd); return address; //returning previously reserved memory } //printf(" VirtualAlloc(...) does not commit or not entirely within reserved, and\n"); } /*printf(" VirtualAlloc(...) (0x%08X, %u) overlaps with (0x%08X, %u, state=%d)\n", (unsigned)address, size, (unsigned)str->address, str->mapping_size, str->state);*/ - close(fd); return NULL; } } - answer=mmap(address, size, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE, fd, 0); + answer=mmap_anon(address, size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE, &fd, 0); // answer=FILE_dommap(-1, address, 0, size, 0, 0, // PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); - close(fd); + if (fd != -1) + close(fd); + if (answer != (void *)-1 && address && answer != address) { /* It is dangerous to try mmap() with MAP_FIXED since it does not always detect conflicts or non-allocation and chaos ensues after diff --git a/loader/ldt_keeper.c b/loader/ldt_keeper.c index 6b28776501..bf61f617cf 100644 --- a/loader/ldt_keeper.c +++ b/loader/ldt_keeper.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <stdio.h> #include <unistd.h> +#include "osdep/mmap_anon.h" #ifdef __linux__ #include <asm/unistd.h> #include <asm/ldt.h> @@ -200,8 +201,8 @@ ldt_fs_t* Setup_LDT_Keeper(void) return NULL; } fs_seg= - ldt_fs->fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, - ldt_fs->fd, 0); + ldt_fs->fs_seg = mmap_anon(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE, &ldt_fs->fd, + 0); if (ldt_fs->fs_seg == (void*)-1) { perror("ERROR: Couldn't allocate memory for fs segment"); @@ -286,6 +287,7 @@ void Restore_LDT_Keeper(ldt_fs_t* ldt_fs) free(ldt_fs->prev_struct); munmap((char*)ldt_fs->fs_seg, getpagesize()); ldt_fs->fs_seg = 0; + if (ldt_fs->fd != -1) close(ldt_fs->fd); free(ldt_fs); } diff --git a/osdep/Makefile b/osdep/Makefile index a5ee59201e..abd38716b1 100644 --- a/osdep/Makefile +++ b/osdep/Makefile @@ -12,6 +12,7 @@ SRCS= shmem.c \ fseeko.c \ swab.c \ setenv.c \ + mmap_anon.c \ # timer.c \ getch = getch2.c diff --git a/osdep/mmap_anon.c b/osdep/mmap_anon.c new file mode 100644 index 0000000000..b6d0b7cf35 --- /dev/null +++ b/osdep/mmap_anon.c @@ -0,0 +1,67 @@ + /** + * \file mmap_anon.c + * \brief Provide a compatible anonymous space mapping function + */ + +#include <sys/mman.h> +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif + +/* + * mmap() anonymous space, depending on the system's mmap() style. On systems + * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor + * of the opened /dev/zero. + */ + + /** + * \brief mmap() anonymous space, depending on the system's mmap() style. On systems + * that use the /dev/zero mapping idiom, zerofd will be set to the file descriptor + * of the opened /dev/zero. + * + * \param addr address to map at. + * \param len number of bytes from addr to be mapped. + * \param prot protections (region accessibility). + * \param flags specifies the type of the mapped object. + * \param offset start mapping at byte offset. + * \param zerofd + * \return a pointer to the mapped region upon successful completion, -1 otherwise. + */ +void *mmap_anon(void *addr, size_t len, int prot, int flags, int *zerofd, off_t offset) +{ + int fd; + void *result; + + /* From loader/ext.c: + * "Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap" + * Therefore we preserve the same behavior on all platforms, ie. no + * shared mappings of anon space (if the concepts are supported). */ +#if defined(MAP_SHARED) && defined(MAP_PRIVATE) + flags = (flags & ~MAP_SHARED) | MAP_PRIVATE; +#endif /* defined(MAP_SHARED) && defined(MAP_PRIVATE) */ + +#ifdef MAP_ANONYMOUS + /* BSD-style anonymous mapping */ + fd = -1; + result = mmap(addr, len, prot, flags | MAP_ANONYMOUS, -1, offset); +#else + /* SysV-style anonymous mapping */ + fd = open("/dev/zero", O_RDWR); + if(fd < 0){ + perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: "); + return NULL; + } + + result = mmap(addr, len, prot, flags, fd, offset); +#endif /* MAP_ANONYMOUS */ + + if (zerofd) + *zerofd = fd; + + return result; +} + diff --git a/osdep/mmap_anon.h b/osdep/mmap_anon.h new file mode 100644 index 0000000000..edb909bdc0 --- /dev/null +++ b/osdep/mmap_anon.h @@ -0,0 +1,8 @@ +#ifndef _OSDEP_MMAP_ANON_H_ +#define _OSDEP_MMAP_ANON_H_ + +#include <sys/types.h> + +void *mmap_anon(void *, size_t, int, int, int *, off_t); + +#endif /* _OSDEP_MMAP_ANON_H_ */ |