loader: Duplicate some preloader code instead of trying to share it.
This mostly reverts bd2d795240
.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
05fa21e188
commit
df8c5a37ec
|
@ -60,9 +60,12 @@
|
||||||
* http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/book387.html
|
* http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/book387.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -90,9 +93,7 @@
|
||||||
# include <sys/link.h>
|
# include <sys/link.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "preloader.h"
|
#include "main.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
|
||||||
|
|
||||||
/* ELF definitions */
|
/* ELF definitions */
|
||||||
#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
|
#define ELF_PREFERRED_ADDRESS(loader, maplength, mapstartpref) (mapstartpref)
|
||||||
|
@ -538,6 +539,107 @@ SYSCALL_NOERR( wld_getegid, 177 /* SYS_getegid */ );
|
||||||
#error preloader not implemented for this CPU
|
#error preloader not implemented for this CPU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wld_printf - just the basics
|
||||||
|
*
|
||||||
|
* %x prints a hex number
|
||||||
|
* %s prints a string
|
||||||
|
* %p prints a pointer
|
||||||
|
*/
|
||||||
|
static int wld_vsprintf(char *buffer, const char *fmt, va_list args )
|
||||||
|
{
|
||||||
|
static const char hex_chars[16] = "0123456789abcdef";
|
||||||
|
const char *p = fmt;
|
||||||
|
char *str = buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while( *p )
|
||||||
|
{
|
||||||
|
if( *p == '%' )
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if( *p == 'x' )
|
||||||
|
{
|
||||||
|
unsigned int x = va_arg( args, unsigned int );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
}
|
||||||
|
else if (p[0] == 'l' && p[1] == 'x')
|
||||||
|
{
|
||||||
|
unsigned long x = va_arg( args, unsigned long );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if( *p == 'p' )
|
||||||
|
{
|
||||||
|
unsigned long x = (unsigned long)va_arg( args, void * );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
}
|
||||||
|
else if( *p == 's' )
|
||||||
|
{
|
||||||
|
char *s = va_arg( args, char * );
|
||||||
|
while(*s)
|
||||||
|
*str++ = *s++;
|
||||||
|
}
|
||||||
|
else if( *p == 0 )
|
||||||
|
break;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
*str++ = *p++;
|
||||||
|
}
|
||||||
|
*str = 0;
|
||||||
|
return str - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char buffer[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
len = wld_vsprintf(buffer, fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
wld_write(2, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char buffer[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
len = wld_vsprintf(buffer, fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
wld_write(2, buffer, len);
|
||||||
|
wld_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DUMP_AUX_INFO
|
#ifdef DUMP_AUX_INFO
|
||||||
/*
|
/*
|
||||||
* Dump interesting bits of the ELF auxv_t structure that is passed
|
* Dump interesting bits of the ELF auxv_t structure that is passed
|
||||||
|
@ -1020,6 +1122,67 @@ found:
|
||||||
return (void *)(symtab[idx].st_value + map->l_addr);
|
return (void *)(symtab[idx].st_value + map->l_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* preload_reserve
|
||||||
|
*
|
||||||
|
* Reserve a range specified in string format
|
||||||
|
*/
|
||||||
|
static void preload_reserve( const char *str )
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
unsigned long result = 0;
|
||||||
|
void *start = NULL, *end = NULL;
|
||||||
|
int i, first = 1;
|
||||||
|
|
||||||
|
for (p = str; *p; p++)
|
||||||
|
{
|
||||||
|
if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
|
||||||
|
else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
|
||||||
|
else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
|
||||||
|
else if (*p == '-')
|
||||||
|
{
|
||||||
|
if (!first) goto error;
|
||||||
|
start = (void *)(result & ~page_mask);
|
||||||
|
result = 0;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
else goto error;
|
||||||
|
}
|
||||||
|
if (!first) end = (void *)((result + page_mask) & ~page_mask);
|
||||||
|
else if (result) goto error; /* single value '0' is allowed */
|
||||||
|
|
||||||
|
/* sanity checks */
|
||||||
|
if (end <= start) start = end = NULL;
|
||||||
|
else if ((char *)end > preloader_start &&
|
||||||
|
(char *)start <= preloader_end)
|
||||||
|
{
|
||||||
|
wld_printf( "WINEPRELOADRESERVE range %p-%p overlaps preloader %p-%p\n",
|
||||||
|
start, end, preloader_start, preloader_end );
|
||||||
|
start = end = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for overlap with low memory areas */
|
||||||
|
for (i = 0; preload_info[i].size; i++)
|
||||||
|
{
|
||||||
|
if ((char *)preload_info[i].addr > (char *)0x00110000) break;
|
||||||
|
if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
|
{
|
||||||
|
start = end = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
|
start = (char *)preload_info[i].addr + preload_info[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (preload_info[i].size) i++;
|
||||||
|
preload_info[i].addr = start;
|
||||||
|
preload_info[i].size = (char *)end - (char *)start;
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
|
||||||
|
}
|
||||||
|
|
||||||
/* check if address is in one of the reserved ranges */
|
/* check if address is in one of the reserved ranges */
|
||||||
static int is_addr_reserved( const void *addr )
|
static int is_addr_reserved( const void *addr )
|
||||||
{
|
{
|
||||||
|
@ -1034,6 +1197,17 @@ static int is_addr_reserved( const void *addr )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove a range from the preload list */
|
||||||
|
static void remove_preload_range( int i )
|
||||||
|
{
|
||||||
|
while (preload_info[i].size)
|
||||||
|
{
|
||||||
|
preload_info[i].addr = preload_info[i+1].addr;
|
||||||
|
preload_info[i].size = preload_info[i+1].size;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is_in_preload_range
|
* is_in_preload_range
|
||||||
*
|
*
|
||||||
|
@ -1115,13 +1289,13 @@ void* wld_start( void **stack )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reserve memory that Wine needs */
|
/* reserve memory that Wine needs */
|
||||||
if (reserve) preload_reserve( reserve, preload_info, page_mask );
|
if (reserve) preload_reserve( reserve );
|
||||||
for (i = 0; preload_info[i].size; i++)
|
for (i = 0; preload_info[i].size; i++)
|
||||||
{
|
{
|
||||||
if ((char *)av >= (char *)preload_info[i].addr &&
|
if ((char *)av >= (char *)preload_info[i].addr &&
|
||||||
(char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
|
(char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
{
|
{
|
||||||
remove_preload_range( i, preload_info );
|
remove_preload_range( i );
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
|
else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
|
||||||
|
@ -1135,7 +1309,7 @@ void* wld_start( void **stack )
|
||||||
)
|
)
|
||||||
wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
|
wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
|
||||||
preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size );
|
preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size );
|
||||||
remove_preload_range( i, preload_info );
|
remove_preload_range( i );
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1204,145 +1378,3 @@ void* wld_start( void **stack )
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
/* replacement for libc functions */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* wld_printf - just the basics
|
|
||||||
*
|
|
||||||
* %x prints a hex number
|
|
||||||
* %s prints a string
|
|
||||||
* %p prints a pointer
|
|
||||||
*/
|
|
||||||
int wld_vsprintf(char *buffer, const char *fmt, va_list args )
|
|
||||||
{
|
|
||||||
static const char hex_chars[16] = "0123456789abcdef";
|
|
||||||
const char *p = fmt;
|
|
||||||
char *str = buffer;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while( *p )
|
|
||||||
{
|
|
||||||
if( *p == '%' )
|
|
||||||
{
|
|
||||||
p++;
|
|
||||||
if( *p == 'x' )
|
|
||||||
{
|
|
||||||
unsigned int x = va_arg( args, unsigned int );
|
|
||||||
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
|
||||||
*str++ = hex_chars[(x>>(i*4))&0xf];
|
|
||||||
}
|
|
||||||
else if (p[0] == 'l' && p[1] == 'x')
|
|
||||||
{
|
|
||||||
unsigned long x = va_arg( args, unsigned long );
|
|
||||||
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
|
||||||
*str++ = hex_chars[(x>>(i*4))&0xf];
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else if( *p == 'p' )
|
|
||||||
{
|
|
||||||
unsigned long x = (unsigned long)va_arg( args, void * );
|
|
||||||
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
|
||||||
*str++ = hex_chars[(x>>(i*4))&0xf];
|
|
||||||
}
|
|
||||||
else if( *p == 's' )
|
|
||||||
{
|
|
||||||
char *s = va_arg( args, char * );
|
|
||||||
while(*s)
|
|
||||||
*str++ = *s++;
|
|
||||||
}
|
|
||||||
else if( *p == 0 )
|
|
||||||
break;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
*str++ = *p++;
|
|
||||||
}
|
|
||||||
*str = 0;
|
|
||||||
return str - buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wld_printf(const char *fmt, ... )
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
char buffer[256];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
va_start( args, fmt );
|
|
||||||
len = wld_vsprintf(buffer, fmt, args );
|
|
||||||
va_end( args );
|
|
||||||
wld_write(2, buffer, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fatal_error(const char *fmt, ... )
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
char buffer[256];
|
|
||||||
int len;
|
|
||||||
|
|
||||||
va_start( args, fmt );
|
|
||||||
len = wld_vsprintf(buffer, fmt, args );
|
|
||||||
va_end( args );
|
|
||||||
wld_write(2, buffer, len);
|
|
||||||
wld_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* preload_reserve
|
|
||||||
*
|
|
||||||
* Reserve a range specified in string format
|
|
||||||
*/
|
|
||||||
void preload_reserve( const char *str, struct wine_preload_info *preload_info, size_t page_mask )
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
unsigned long result = 0;
|
|
||||||
void *start = NULL, *end = NULL;
|
|
||||||
int i, first = 1;
|
|
||||||
|
|
||||||
for (p = str; *p; p++)
|
|
||||||
{
|
|
||||||
if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
|
|
||||||
else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
|
|
||||||
else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
|
|
||||||
else if (*p == '-')
|
|
||||||
{
|
|
||||||
if (!first) goto error;
|
|
||||||
start = (void *)(result & ~page_mask);
|
|
||||||
result = 0;
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
else goto error;
|
|
||||||
}
|
|
||||||
if (!first) end = (void *)((result + page_mask) & ~page_mask);
|
|
||||||
else if (result) goto error; /* single value '0' is allowed */
|
|
||||||
|
|
||||||
/* sanity checks */
|
|
||||||
if (end <= start) start = end = NULL;
|
|
||||||
else if ((char *)end > preloader_start &&
|
|
||||||
(char *)start <= preloader_end)
|
|
||||||
{
|
|
||||||
wld_printf( "WINEPRELOADRESERVE range %p-%p overlaps preloader %p-%p\n",
|
|
||||||
start, end, preloader_start, preloader_end );
|
|
||||||
start = end = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for overlap with low memory areas */
|
|
||||||
for (i = 0; preload_info[i].size; i++)
|
|
||||||
{
|
|
||||||
if ((char *)preload_info[i].addr > (char *)0x00110000) break;
|
|
||||||
if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
|
|
||||||
{
|
|
||||||
start = end = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
|
|
||||||
start = (char *)preload_info[i].addr + preload_info[i].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (preload_info[i].size) i++;
|
|
||||||
preload_info[i].addr = start;
|
|
||||||
preload_info[i].size = (char *)end - (char *)start;
|
|
||||||
return;
|
|
||||||
|
|
||||||
error:
|
|
||||||
fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* Definitions for Wine preloader
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 Mike McCormack for CodeWeavers
|
|
||||||
* Copyright (C) 2004 Alexandre Julliard
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __WINE_LOADER_PRELOADER_H
|
|
||||||
#define __WINE_LOADER_PRELOADER_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
static inline int wld_strcmp( const char *str1, const char *str2 )
|
|
||||||
{
|
|
||||||
while (*str1 && (*str1 == *str2)) { str1++; str2++; }
|
|
||||||
return *str1 - *str2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern int wld_vsprintf(char *buffer, const char *fmt, va_list args );
|
|
||||||
extern __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... );
|
|
||||||
extern __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... );
|
|
||||||
|
|
||||||
extern void preload_reserve( const char *str, struct wine_preload_info *preload_info, size_t page_mask );
|
|
||||||
|
|
||||||
/* remove a range from the preload list */
|
|
||||||
static inline void remove_preload_range( int i, struct wine_preload_info *preload_info )
|
|
||||||
{
|
|
||||||
while (preload_info[i].size)
|
|
||||||
{
|
|
||||||
preload_info[i].addr = preload_info[i+1].addr;
|
|
||||||
preload_info[i].size = preload_info[i+1].size;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __WINE_LOADER_PRELOADER_H */
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
#include <mach-o/loader.h>
|
#include <mach-o/loader.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "preloader.h"
|
#include "main.h"
|
||||||
|
|
||||||
#ifndef LC_MAIN
|
#ifndef LC_MAIN
|
||||||
#define LC_MAIN 0x80000028
|
#define LC_MAIN 0x80000028
|
||||||
|
@ -287,6 +288,159 @@ MAKE_FUNCPTR(dladdr);
|
||||||
|
|
||||||
extern int _dyld_func_lookup( const char *dyld_func_name, void **address );
|
extern int _dyld_func_lookup( const char *dyld_func_name, void **address );
|
||||||
|
|
||||||
|
/* replacement for libc functions */
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* wld_printf - just the basics
|
||||||
|
*
|
||||||
|
* %x prints a hex number
|
||||||
|
* %s prints a string
|
||||||
|
* %p prints a pointer
|
||||||
|
*/
|
||||||
|
static int wld_vsprintf(char *buffer, const char *fmt, va_list args )
|
||||||
|
{
|
||||||
|
static const char hex_chars[16] = "0123456789abcdef";
|
||||||
|
const char *p = fmt;
|
||||||
|
char *str = buffer;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
while( *p )
|
||||||
|
{
|
||||||
|
if( *p == '%' )
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
if( *p == 'x' )
|
||||||
|
{
|
||||||
|
unsigned int x = va_arg( args, unsigned int );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
}
|
||||||
|
else if (p[0] == 'l' && p[1] == 'x')
|
||||||
|
{
|
||||||
|
unsigned long x = va_arg( args, unsigned long );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
else if( *p == 'p' )
|
||||||
|
{
|
||||||
|
unsigned long x = (unsigned long)va_arg( args, void * );
|
||||||
|
for (i = 2*sizeof(x) - 1; i >= 0; i--)
|
||||||
|
*str++ = hex_chars[(x>>(i*4))&0xf];
|
||||||
|
}
|
||||||
|
else if( *p == 's' )
|
||||||
|
{
|
||||||
|
char *s = va_arg( args, char * );
|
||||||
|
while(*s)
|
||||||
|
*str++ = *s++;
|
||||||
|
}
|
||||||
|
else if( *p == 0 )
|
||||||
|
break;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
*str++ = *p++;
|
||||||
|
}
|
||||||
|
*str = 0;
|
||||||
|
return str - buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __attribute__((format(printf,1,2))) void wld_printf(const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char buffer[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
len = wld_vsprintf(buffer, fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
wld_write(2, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __attribute__((noreturn,format(printf,1,2))) void fatal_error(const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
char buffer[256];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
len = wld_vsprintf(buffer, fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
wld_write(2, buffer, len);
|
||||||
|
wld_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* preload_reserve
|
||||||
|
*
|
||||||
|
* Reserve a range specified in string format
|
||||||
|
*/
|
||||||
|
static void preload_reserve( const char *str )
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
unsigned long result = 0;
|
||||||
|
void *start = NULL, *end = NULL;
|
||||||
|
int i, first = 1;
|
||||||
|
|
||||||
|
for (p = str; *p; p++)
|
||||||
|
{
|
||||||
|
if (*p >= '0' && *p <= '9') result = result * 16 + *p - '0';
|
||||||
|
else if (*p >= 'a' && *p <= 'f') result = result * 16 + *p - 'a' + 10;
|
||||||
|
else if (*p >= 'A' && *p <= 'F') result = result * 16 + *p - 'A' + 10;
|
||||||
|
else if (*p == '-')
|
||||||
|
{
|
||||||
|
if (!first) goto error;
|
||||||
|
start = (void *)(result & ~page_mask);
|
||||||
|
result = 0;
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
else goto error;
|
||||||
|
}
|
||||||
|
if (!first) end = (void *)((result + page_mask) & ~page_mask);
|
||||||
|
else if (result) goto error; /* single value '0' is allowed */
|
||||||
|
|
||||||
|
/* sanity checks */
|
||||||
|
if (end <= start) start = end = NULL;
|
||||||
|
|
||||||
|
/* check for overlap with low memory areas */
|
||||||
|
for (i = 0; preload_info[i].size; i++)
|
||||||
|
{
|
||||||
|
if ((char *)preload_info[i].addr > (char *)0x00110000) break;
|
||||||
|
if ((char *)end <= (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
|
{
|
||||||
|
start = end = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((char *)start < (char *)preload_info[i].addr + preload_info[i].size)
|
||||||
|
start = (char *)preload_info[i].addr + preload_info[i].size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (preload_info[i].size) i++;
|
||||||
|
preload_info[i].addr = start;
|
||||||
|
preload_info[i].size = (char *)end - (char *)start;
|
||||||
|
return;
|
||||||
|
|
||||||
|
error:
|
||||||
|
fatal_error( "invalid WINEPRELOADRESERVE value '%s'\n", str );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove a range from the preload list */
|
||||||
|
static void remove_preload_range( int i )
|
||||||
|
{
|
||||||
|
while (preload_info[i].size)
|
||||||
|
{
|
||||||
|
preload_info[i].addr = preload_info[i+1].addr;
|
||||||
|
preload_info[i].size = preload_info[i+1].size;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void *get_entry_point( struct target_mach_header *mh, intptr_t slide, int *unix_thread )
|
static void *get_entry_point( struct target_mach_header *mh, intptr_t slide, int *unix_thread )
|
||||||
{
|
{
|
||||||
struct entry_point_command *entry;
|
struct entry_point_command *entry;
|
||||||
|
@ -409,12 +563,12 @@ void *wld_start( void *stack, int *is_unix_thread )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reserve memory that Wine needs */
|
/* reserve memory that Wine needs */
|
||||||
if (reserve) preload_reserve( reserve, preload_info, page_mask );
|
if (reserve) preload_reserve( reserve );
|
||||||
for (i = 0; preload_info[i].size; i++)
|
for (i = 0; preload_info[i].size; i++)
|
||||||
{
|
{
|
||||||
if (!map_region( &preload_info[i] ))
|
if (!map_region( &preload_info[i] ))
|
||||||
{
|
{
|
||||||
remove_preload_range( i, preload_info );
|
remove_preload_range( i );
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue