Do direct Linux system calls in the preloader to avoid trouble with
some broken static libcs.
This commit is contained in:
parent
fc51760f48
commit
bfac60bfeb
|
@ -14607,56 +14607,6 @@ esac
|
|||
|
||||
case $host_os in
|
||||
linux*)
|
||||
ac_wine_try_cflags_saved=$CFLAGS
|
||||
CFLAGS="$CFLAGS -static"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
:
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
{ { echo "$as_me:$LINENO: error: You need to install the static version of glibc to build Wine." >&5
|
||||
echo "$as_me: error: You need to install the static version of glibc to build Wine." >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
CFLAGS=$ac_wine_try_cflags_saved
|
||||
WINE_BINARIES="wine-glibc wine-kthread wine-pthread wine-preloader"
|
||||
|
||||
MAIN_BINARY="wine-glibc"
|
||||
|
|
|
@ -989,7 +989,6 @@ esac
|
|||
|
||||
case $host_os in
|
||||
linux*)
|
||||
WINE_TRY_CFLAGS([-static],,AC_MSG_ERROR([You need to install the static version of glibc to build Wine.]))
|
||||
AC_SUBST(WINE_BINARIES,"wine-glibc wine-kthread wine-pthread wine-preloader")
|
||||
AC_SUBST(MAIN_BINARY,"wine-glibc")
|
||||
;;
|
||||
|
|
|
@ -28,7 +28,7 @@ wine-glibc: glibc.o Makefile.in
|
|||
$(CC) -o $@ glibc.o $(LIBWINE) $(LIBPORT) $(LIBPTHREAD) $(EXTRALIBS) $(LDFLAGS)
|
||||
|
||||
wine-preloader: preloader.o Makefile.in
|
||||
$(CC) -o $@ -static -nostartfiles -Wl,-Ttext=0x78000000 preloader.o $(LIBPORT) $(LDFLAGS)
|
||||
$(CC) -o $@ -static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x78000000 preloader.o $(LIBPORT) $(LDFLAGS)
|
||||
|
||||
wine-kthread: $(KTHREAD_OBJS) Makefile.in
|
||||
$(CC) -o $@ $(LDEXECFLAGS) $(KTHREAD_OBJS) $(LIBWINE) $(LIBPORT) $(EXTRALIBS) $(LDFLAGS)
|
||||
|
|
|
@ -73,6 +73,9 @@
|
|||
#ifdef HAVE_SYS_MMAN_H
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SYSCALL_H
|
||||
# include <sys/syscall.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
@ -156,6 +159,140 @@ __ASM_GLOBAL_FUNC(_start,
|
|||
"\txor %edx,%edx\n"
|
||||
"\tret\n")
|
||||
|
||||
/* wrappers for Linux system calls */
|
||||
|
||||
#define SYSCALL_RET(ret) (((ret) < 0 && (ret) > -4096) ? -1 : (ret))
|
||||
|
||||
static inline __attribute__((noreturn)) void wld_exit( int code )
|
||||
{
|
||||
for (;;) /* avoid warning */
|
||||
__asm__ __volatile__( "int $0x80" : : "a" (SYS_exit), "b" (code) );
|
||||
}
|
||||
|
||||
static inline int wld_open( const char *name, int flags )
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret) : "0" (SYS_open), "b" (name), "c" (flags) );
|
||||
return SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static inline int wld_close( int fd )
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret) : "0" (SYS_close), "b" (fd) );
|
||||
return SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static inline ssize_t wld_read( int fd, void *buffer, size_t len )
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret)
|
||||
: "0" (SYS_read), "b" (fd), "c" (buffer), "d" (len)
|
||||
: "memory" );
|
||||
return SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static inline ssize_t wld_write( int fd, const void *buffer, size_t len )
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret)
|
||||
: "0" (SYS_write), "b" (fd), "c" (buffer), "d" (len) );
|
||||
return SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static inline int wld_mprotect( const void *addr, size_t len, int prot )
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret) : "0" (SYS_mprotect), "b" (addr), "c" (len), "d" (prot) );
|
||||
return SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset )
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct
|
||||
{
|
||||
void *addr;
|
||||
unsigned int length;
|
||||
unsigned int prot;
|
||||
unsigned int flags;
|
||||
unsigned int fd;
|
||||
unsigned int offset;
|
||||
} args;
|
||||
|
||||
args.addr = start;
|
||||
args.length = len;
|
||||
args.prot = prot;
|
||||
args.flags = flags;
|
||||
args.fd = fd;
|
||||
args.offset = offset;
|
||||
__asm__ __volatile__( "int $0x80" : "=a" (ret) : "0" (SYS_mmap), "b" (&args) : "memory" );
|
||||
return (void *)SYSCALL_RET(ret);
|
||||
}
|
||||
|
||||
static inline uid_t wld_getuid(void)
|
||||
{
|
||||
uid_t ret;
|
||||
__asm__( "int $0x80" : "=a" (ret) : "0" (SYS_getuid) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uid_t wld_geteuid(void)
|
||||
{
|
||||
uid_t ret;
|
||||
__asm__( "int $0x80" : "=a" (ret) : "0" (SYS_geteuid) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline gid_t wld_getgid(void)
|
||||
{
|
||||
gid_t ret;
|
||||
__asm__( "int $0x80" : "=a" (ret) : "0" (SYS_getgid) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline gid_t wld_getegid(void)
|
||||
{
|
||||
gid_t ret;
|
||||
__asm__( "int $0x80" : "=a" (ret) : "0" (SYS_getegid) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* replacement for libc functions */
|
||||
|
||||
static int wld_strcmp( const char *str1, const char *str2 )
|
||||
{
|
||||
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
return *str1 - *str2;
|
||||
}
|
||||
|
||||
static int wld_strncmp( const char *str1, const char *str2, size_t len )
|
||||
{
|
||||
if (len <= 0) return 0;
|
||||
while ((--len > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
|
||||
return *str1 - *str2;
|
||||
}
|
||||
|
||||
static inline void *wld_memset( void *dest, int val, size_t len )
|
||||
{
|
||||
char *dst = dest;
|
||||
while (len--) *dst++ = val;
|
||||
return dest;
|
||||
}
|
||||
|
||||
static inline void *wld_memmove( void *dest, const void *src, size_t len )
|
||||
{
|
||||
const char *s = src;
|
||||
char *d = dest;
|
||||
int i;
|
||||
|
||||
if (d < s) for (i = 0; i < len; i++) d[i] = s[i];
|
||||
else for (i = len - 1; i >= 0; i--) d[i] = s[i];
|
||||
return dest;
|
||||
}
|
||||
|
||||
/*
|
||||
* wld_printf - just the basics
|
||||
*
|
||||
|
@ -202,10 +339,10 @@ static void wld_printf(const char *fmt, ... )
|
|||
va_start( args, fmt );
|
||||
wld_vsprintf(buffer, fmt, args );
|
||||
va_end( args );
|
||||
write(2, buffer, strlen(buffer));
|
||||
wld_write(2, buffer, strlen(buffer));
|
||||
}
|
||||
|
||||
static void fatal_error(const char *fmt, ... )
|
||||
static __attribute__((noreturn)) void fatal_error(const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
char buffer[256];
|
||||
|
@ -213,8 +350,8 @@ static void fatal_error(const char *fmt, ... )
|
|||
va_start( args, fmt );
|
||||
wld_vsprintf(buffer, fmt, args );
|
||||
va_end( args );
|
||||
write(2, buffer, strlen(buffer));
|
||||
_exit(1);
|
||||
wld_write(2, buffer, strlen(buffer));
|
||||
wld_exit(1);
|
||||
}
|
||||
|
||||
#ifdef DUMP_AUX_INFO
|
||||
|
@ -278,7 +415,7 @@ static void set_auxiliary_values( ElfW(auxv_t) *av, const ElfW(auxv_t) *new_av,
|
|||
if (new_count) /* need to make room for the extra values */
|
||||
{
|
||||
char *new_stack = (char *)*stack - new_count * sizeof(*av);
|
||||
memmove( new_stack, *stack, (char *)(av + av_count) - (char *)*stack );
|
||||
wld_memmove( new_stack, *stack, (char *)(av + av_count) - (char *)*stack );
|
||||
*stack = new_stack;
|
||||
av -= new_count;
|
||||
}
|
||||
|
@ -337,10 +474,10 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
} loadcmds[16], *c;
|
||||
size_t nloadcmds = 0, maplength;
|
||||
|
||||
fd = open( name, O_RDONLY );
|
||||
fd = wld_open( name, O_RDONLY );
|
||||
if (fd == -1) fatal_error("%s: could not open\n", name );
|
||||
|
||||
if (read( fd, buf, sizeof(buf) ) != sizeof(buf))
|
||||
if (wld_read( fd, buf, sizeof(buf) ) != sizeof(buf))
|
||||
fatal_error("%s: failed to read ELF header\n", name);
|
||||
|
||||
phdr = (void*) (((unsigned char*)buf) + header->e_phoff);
|
||||
|
@ -452,7 +589,7 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
- MAP_BASE_ADDR (l));
|
||||
|
||||
/* Remember which part of the address space this object uses. */
|
||||
l->l_map_start = (ElfW(Addr)) mmap ((void *) mappref, maplength,
|
||||
l->l_map_start = (ElfW(Addr)) wld_mmap ((void *) mappref, maplength,
|
||||
c->prot, MAP_COPY | MAP_FILE,
|
||||
fd, c->mapoff);
|
||||
/* wld_printf("set : offset = %x\n", c->mapoff); */
|
||||
|
@ -461,7 +598,7 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
l->l_map_end = l->l_map_start + maplength;
|
||||
l->l_addr = l->l_map_start - c->mapstart;
|
||||
|
||||
mprotect ((caddr_t) (l->l_addr + c->mapend),
|
||||
wld_mprotect ((caddr_t) (l->l_addr + c->mapend),
|
||||
loadcmds[nloadcmds - 1].allocend - c->mapend,
|
||||
PROT_NONE);
|
||||
goto postmap;
|
||||
|
@ -485,7 +622,7 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
{
|
||||
if (c->mapend > c->mapstart)
|
||||
/* Map the segment contents from the file. */
|
||||
mmap ((void *) (l->l_addr + c->mapstart),
|
||||
wld_mmap ((void *) (l->l_addr + c->mapstart),
|
||||
c->mapend - c->mapstart, c->prot,
|
||||
MAP_FIXED | MAP_COPY | MAP_FILE, fd, c->mapoff);
|
||||
|
||||
|
@ -526,18 +663,18 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
if ((c->prot & PROT_WRITE) == 0)
|
||||
{
|
||||
/* Dag nab it. */
|
||||
mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot|PROT_WRITE);
|
||||
wld_mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot|PROT_WRITE);
|
||||
}
|
||||
memset ((void *) zero, '\0', zeropage - zero);
|
||||
wld_memset ((void *) zero, '\0', zeropage - zero);
|
||||
if ((c->prot & PROT_WRITE) == 0)
|
||||
mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot);
|
||||
wld_mprotect ((caddr_t) (zero & ~page_mask), page_size, c->prot);
|
||||
}
|
||||
|
||||
if (zeroend > zeropage)
|
||||
{
|
||||
/* Map the remaining zero pages in from the zero fill FD. */
|
||||
caddr_t mapat;
|
||||
mapat = mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||
mapat = wld_mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||
-1, 0);
|
||||
}
|
||||
|
@ -551,7 +688,7 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
l->l_phdr = (void *)((ElfW(Addr))l->l_phdr + l->l_addr);
|
||||
l->l_entry += l->l_addr;
|
||||
|
||||
close( fd );
|
||||
wld_close( fd );
|
||||
}
|
||||
|
||||
|
||||
|
@ -607,7 +744,7 @@ static void *find_symbol( const ElfW(Phdr) *phdr, int num, char *var )
|
|||
for (i = 0; i < symtabend; i++)
|
||||
{
|
||||
if( ( ELF32_ST_BIND(symtab[i].st_info) == STT_OBJECT ) &&
|
||||
( 0 == strcmp( strings+symtab[i].st_name, var ) ) )
|
||||
( 0 == wld_strcmp( strings+symtab[i].st_name, var ) ) )
|
||||
{
|
||||
#ifdef DUMP_SYMS
|
||||
wld_printf("Found %s -> %x\n", strings+symtab[i].st_name, symtab[i].st_value );
|
||||
|
@ -694,7 +831,7 @@ void* wld_start( void **stack )
|
|||
while (*p)
|
||||
{
|
||||
static const char res[] = "WINEPRELOADRESERVE=";
|
||||
if (!strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
|
||||
if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
|
||||
p++;
|
||||
}
|
||||
|
||||
|
@ -714,7 +851,7 @@ void* wld_start( void **stack )
|
|||
/* reserve memory that Wine needs */
|
||||
if (reserve) preload_reserve( reserve );
|
||||
for (i = 0; preload_info[i].size; i++)
|
||||
mmap( preload_info[i].addr, preload_info[i].size,
|
||||
wld_mmap( preload_info[i].addr, preload_info[i].size,
|
||||
PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 );
|
||||
|
||||
/* load the main binary */
|
||||
|
@ -738,10 +875,10 @@ void* wld_start( void **stack )
|
|||
SET_NEW_AV( 4, AT_BASE, ld_so_map.l_addr );
|
||||
SET_NEW_AV( 5, AT_FLAGS, get_auxiliary( av, AT_FLAGS, 0 ) );
|
||||
SET_NEW_AV( 6, AT_ENTRY, main_binary_map.l_entry );
|
||||
SET_NEW_AV( 7, AT_UID, get_auxiliary( av, AT_UID, getuid() ) );
|
||||
SET_NEW_AV( 8, AT_EUID, get_auxiliary( av, AT_EUID, geteuid() ) );
|
||||
SET_NEW_AV( 9, AT_GID, get_auxiliary( av, AT_GID, getgid() ) );
|
||||
SET_NEW_AV(10, AT_EGID, get_auxiliary( av, AT_EGID, getegid() ) );
|
||||
SET_NEW_AV( 7, AT_UID, get_auxiliary( av, AT_UID, wld_getuid() ) );
|
||||
SET_NEW_AV( 8, AT_EUID, get_auxiliary( av, AT_EUID, wld_geteuid() ) );
|
||||
SET_NEW_AV( 9, AT_GID, get_auxiliary( av, AT_GID, wld_getgid() ) );
|
||||
SET_NEW_AV(10, AT_EGID, get_auxiliary( av, AT_EGID, wld_getegid() ) );
|
||||
#undef SET_NEW_AV
|
||||
|
||||
/* get rid of first argument */
|
||||
|
|
Loading…
Reference in New Issue