mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-21 17:09:06 -07:00
loader: Add support for ARM linux in the preloader.
Since 28fe84da45
, the main exe image
must be mappable at its desired base address, which essentially
requires the preloader.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51539
Signed-off-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
adb4259aa9
commit
29922c2276
4 changed files with 128 additions and 10 deletions
4
configure
vendored
4
configure
vendored
|
@ -9473,7 +9473,7 @@ fi
|
|||
WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000"
|
||||
|
||||
case $host_cpu in
|
||||
*i[3456789]86* | x86_64 | *aarch64*)
|
||||
*i[3456789]86* | x86_64 | *aarch64* | arm*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,-Ttext-segment=0x7bc00000" >&5
|
||||
$as_echo_n "checking whether the compiler supports -Wl,-Ttext-segment=0x7bc00000... " >&6; }
|
||||
if ${ac_cv_cflags__Wl__Ttext_segment_0x7bc00000+:} false; then :
|
||||
|
@ -18025,7 +18025,7 @@ esac
|
|||
case $host_os in
|
||||
linux*)
|
||||
case $host_cpu in
|
||||
*i[3456789]86*|x86_64*|*aarch64*)
|
||||
*i[3456789]86*|x86_64*|*aarch64*|arm*)
|
||||
test "$wine_binary" = wine || wine_fn_append_file CONFIGURE_TARGETS "loader/wine-preloader"
|
||||
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
|
||||
;;
|
||||
|
|
|
@ -940,7 +940,7 @@ case $host_os in
|
|||
WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000"
|
||||
|
||||
case $host_cpu in
|
||||
*i[[3456789]]86* | x86_64 | *aarch64*)
|
||||
*i[[3456789]]86* | x86_64 | *aarch64* | arm*)
|
||||
WINE_TRY_CFLAGS([-Wl,-Ttext-segment=0x7bc00000],
|
||||
[case $host_os in
|
||||
freebsd* | kfreebsd*-gnu) WINELOADER_LDFLAGS="$WINELOADER_LDFLAGS -Wl,-Ttext-segment=0x60000000" ;;
|
||||
|
@ -2161,7 +2161,7 @@ esac
|
|||
case $host_os in
|
||||
linux*)
|
||||
case $host_cpu in
|
||||
*i[[3456789]]86*|x86_64*|*aarch64*)
|
||||
*i[[3456789]]86*|x86_64*|*aarch64*|arm*)
|
||||
test "$wine_binary" = wine || WINE_IGNORE_FILE("loader/wine-preloader")
|
||||
WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader"
|
||||
;;
|
||||
|
|
|
@ -2155,11 +2155,7 @@ static int pre_exec(void)
|
|||
int temp;
|
||||
|
||||
check_vmsplit( &temp );
|
||||
#ifdef __i386__
|
||||
return 1; /* we have a preloader on x86 */
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
return 1; /* we have a preloader on x86/arm */
|
||||
}
|
||||
|
||||
#elif defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
|
||||
static struct wine_preload_info preload_info[] =
|
||||
{
|
||||
#ifdef __i386__
|
||||
#if defined(__i386__) || defined(__arm__)
|
||||
{ (void *)0x00000000, 0x00010000 }, /* low 64k */
|
||||
{ (void *)0x00010000, 0x00100000 }, /* DOS area */
|
||||
{ (void *)0x00110000, 0x67ef0000 }, /* low memory area */
|
||||
|
@ -536,6 +536,125 @@ SYSCALL_NOERR( wld_geteuid, 175 /* SYS_geteuid */ );
|
|||
gid_t wld_getegid(void);
|
||||
SYSCALL_NOERR( wld_getegid, 177 /* SYS_getegid */ );
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
||||
void *thread_data[256];
|
||||
|
||||
/*
|
||||
* The _start function is the entry and exit point of this program
|
||||
*
|
||||
* It calls wld_start, passing a pointer to the args it receives
|
||||
* then jumps to the address wld_start returns.
|
||||
*/
|
||||
void _start(void);
|
||||
extern char _end[];
|
||||
__ASM_GLOBAL_FUNC(_start,
|
||||
"mov r0, sp\n\t"
|
||||
"sub sp, sp, #144\n\t" /* allocate some space for extra aux values */
|
||||
"str r0, [sp]\n\t" /* orig stack pointer */
|
||||
"ldr r0, =thread_data\n\t"
|
||||
"movw r7, #0x0005\n\t" /* __ARM_NR_set_tls */
|
||||
"movt r7, #0xf\n\t" /* __ARM_NR_set_tls */
|
||||
"svc #0\n\t"
|
||||
"mov r0, sp\n\t" /* ptr to orig stack pointer */
|
||||
"bl wld_start\n\t"
|
||||
"ldr r1, [sp]\n\t" /* new stack pointer */
|
||||
"mov sp, r1\n\t"
|
||||
"mov lr, r0\n\t"
|
||||
"mov r0, #0\n\t"
|
||||
"mov r1, #0\n\t"
|
||||
"mov r2, #0\n\t"
|
||||
"mov r3, #0\n\t"
|
||||
"mov r12, #0\n\t"
|
||||
"bx lr\n\t"
|
||||
".ltorg\n\t")
|
||||
|
||||
#define SYSCALL_FUNC( name, nr ) \
|
||||
__ASM_GLOBAL_FUNC( name, \
|
||||
"push {r4-r5,r7,lr}\n\t" \
|
||||
"ldr r4, [sp, #16]\n\t" \
|
||||
"ldr r5, [sp, #20]\n\t" \
|
||||
"mov r7, #" #nr "\n\t" \
|
||||
"svc #0\n\t" \
|
||||
"cmn r0, #4096\n\t" \
|
||||
"it hi\n\t" \
|
||||
"movhi r0, #-1\n\t" \
|
||||
"pop {r4-r5,r7,pc}\n\t" )
|
||||
|
||||
#define SYSCALL_NOERR( name, nr ) \
|
||||
__ASM_GLOBAL_FUNC( name, \
|
||||
"push {r7,lr}\n\t" \
|
||||
"mov r7, #" #nr "\n\t" \
|
||||
"svc #0\n\t" \
|
||||
"pop {r7,pc}\n\t" )
|
||||
|
||||
void wld_exit( int code ) __attribute__((noreturn));
|
||||
SYSCALL_NOERR( wld_exit, 1 /* SYS_exit */ );
|
||||
|
||||
ssize_t wld_read( int fd, void *buffer, size_t len );
|
||||
SYSCALL_FUNC( wld_read, 3 /* SYS_read */ );
|
||||
|
||||
ssize_t wld_write( int fd, const void *buffer, size_t len );
|
||||
SYSCALL_FUNC( wld_write, 4 /* SYS_write */ );
|
||||
|
||||
int wld_openat( int dirfd, const char *name, int flags );
|
||||
SYSCALL_FUNC( wld_openat, 322 /* SYS_openat */ );
|
||||
|
||||
int wld_open( const char *name, int flags )
|
||||
{
|
||||
return wld_openat(-100 /* AT_FDCWD */, name, flags);
|
||||
}
|
||||
|
||||
int wld_close( int fd );
|
||||
SYSCALL_FUNC( wld_close, 6 /* SYS_close */ );
|
||||
|
||||
void *wld_mmap2( void *start, size_t len, int prot, int flags, int fd, int offset );
|
||||
SYSCALL_FUNC( wld_mmap2, 192 /* SYS_mmap2 */ );
|
||||
|
||||
void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset )
|
||||
{
|
||||
return wld_mmap2(start, len, prot, flags, fd, offset >> 12);
|
||||
}
|
||||
|
||||
int wld_mprotect( const void *addr, size_t len, int prot );
|
||||
SYSCALL_FUNC( wld_mprotect, 125 /* SYS_mprotect */ );
|
||||
|
||||
int wld_prctl( int code, long arg );
|
||||
SYSCALL_FUNC( wld_prctl, 172 /* SYS_prctl */ );
|
||||
|
||||
uid_t wld_getuid(void);
|
||||
SYSCALL_NOERR( wld_getuid, 24 /* SYS_getuid */ );
|
||||
|
||||
gid_t wld_getgid(void);
|
||||
SYSCALL_NOERR( wld_getgid, 47 /* SYS_getgid */ );
|
||||
|
||||
uid_t wld_geteuid(void);
|
||||
SYSCALL_NOERR( wld_geteuid, 49 /* SYS_geteuid */ );
|
||||
|
||||
gid_t wld_getegid(void);
|
||||
SYSCALL_NOERR( wld_getegid, 50 /* SYS_getegid */ );
|
||||
|
||||
unsigned long long __aeabi_uidivmod(unsigned int num, unsigned int den)
|
||||
{
|
||||
unsigned int bit = 1;
|
||||
unsigned int quota = 0;
|
||||
if (!den)
|
||||
wld_exit(1);
|
||||
while (den < num && !(den & 0x80000000)) {
|
||||
den <<= 1;
|
||||
bit <<= 1;
|
||||
}
|
||||
do {
|
||||
if (den <= num) {
|
||||
quota |= bit;
|
||||
num -= den;
|
||||
}
|
||||
bit >>= 1;
|
||||
den >>= 1;
|
||||
} while (bit);
|
||||
return ((unsigned long long)num << 32) | quota;
|
||||
}
|
||||
|
||||
#else
|
||||
#error preloader not implemented for this CPU
|
||||
#endif
|
||||
|
@ -809,6 +928,9 @@ static void map_so_lib( const char *name, struct wld_link_map *l)
|
|||
#elif defined(__aarch64__)
|
||||
if( header->e_machine != EM_AARCH64 )
|
||||
fatal_error("%s: not an aarch64 ELF binary... don't know how to load it\n", name );
|
||||
#elif defined(__arm__)
|
||||
if( header->e_machine != EM_ARM )
|
||||
fatal_error("%s: not an arm ELF binary... don't know how to load it\n", name );
|
||||
#endif
|
||||
|
||||
if (header->e_phnum > sizeof(loadcmds)/sizeof(loadcmds[0]))
|
||||
|
|
Loading…
Reference in a new issue