From 27e92e550c2b86d5ebd4966926c1fcde03838dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= Date: Fri, 20 Oct 2017 21:14:43 +0200 Subject: [PATCH] loader: Build the preloader for ARM64. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Hentschel Signed-off-by: Alexandre Julliard --- configure | 2 +- configure.ac | 2 +- loader/preloader.c | 107 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 7a7d26a3249..c8a508be3e5 100755 --- a/configure +++ b/configure @@ -15627,7 +15627,7 @@ esac case $host_os in linux*) case $host_cpu in - *i[3456789]86*|x86_64*) + *i[3456789]86*|x86_64*|*aarch64*) test "$wine_binary" = wine || wine_fn_append_file CONFIGURE_TARGETS "loader/wine-preloader" WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader" ;; diff --git a/configure.ac b/configure.ac index cff4b8f108d..3039c941656 100644 --- a/configure.ac +++ b/configure.ac @@ -2022,7 +2022,7 @@ esac case $host_os in linux*) case $host_cpu in - *i[[3456789]]86*|x86_64*) + *i[[3456789]]86*|x86_64*|*aarch64*) test "$wine_binary" = wine || WINE_IGNORE_FILE("loader/wine-preloader") WINELOADER_PROGRAMS="$WINELOADER_PROGRAMS $wine_binary-preloader" ;; diff --git a/loader/preloader.c b/loader/preloader.c index 5e6add7830f..5068a60c20a 100644 --- a/loader/preloader.c +++ b/loader/preloader.c @@ -455,6 +455,110 @@ SYSCALL_NOERR( wld_geteuid, 107 /* SYS_geteuid */ ); gid_t wld_getegid(void); SYSCALL_NOERR( wld_getegid, 108 /* SYS_getegid */ ); +#elif defined(__aarch64__) + +/* + * 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 x0, SP\n\t" + "sub SP, SP, #144\n\t" /* allocate some space for extra aux values */ + "str x0, [SP]\n\t" /* orig stack pointer */ + "str x30, [SP, #8]\n\t" + "mov x0, SP\n\t" /* ptr to orig stack pointer */ + "bl wld_start\n\t" + "ldr x30, [SP, #8]\n\t" + "ldr x1, [SP]\n\t" /* new stack pointer */ + "mov SP, x1\n\t" + "mov x30, x0\n\t" + "mov x0, #0\n\t" + "mov x1, #0\n\t" + "mov x2, #0\n\t" + "mov x3, #0\n\t" + "mov x4, #0\n\t" + "mov x5, #0\n\t" + "mov x6, #0\n\t" + "mov x7, #0\n\t" + "mov x8, #0\n\t" + "mov x9, #0\n\t" + "mov x10, #0\n\t" + "mov x11, #0\n\t" + "mov x12, #0\n\t" + "mov x13, #0\n\t" + "mov x14, #0\n\t" + "mov x15, #0\n\t" + "mov x16, #0\n\t" + "mov x17, #0\n\t" + "mov x18, #0\n\t" + "ret") + +#define SYSCALL_FUNC( name, nr ) \ + __ASM_GLOBAL_FUNC( name, \ + "stp x8, x9, [SP, #-16]!\n\t" \ + "mov x8, #" #nr "\n\t" \ + "svc #0\n\t" \ + "ldp x8, x9, [SP], #16\n\t" \ + "cmn x0, #1, lsl#12\n\t" \ + "cinv x0, x0, hi\n\t" \ + "b.hi 1f\n\t" \ + "ret\n\t" \ + "1: mov x0, #-1\n\t" \ + "ret" ) + +#define SYSCALL_NOERR( name, nr ) \ + __ASM_GLOBAL_FUNC( name, \ + "stp x8, x9, [SP, #-16]!\n\t" \ + "mov x8, #" #nr "\n\t" \ + "svc #0\n\t" \ + "ldp x8, x9, [SP], #16\n\t" \ + "ret" ) + +void wld_exit( int code ) __attribute__((noreturn)); +SYSCALL_NOERR( wld_exit, 93 /* SYS_exit */ ); + +ssize_t wld_read( int fd, void *buffer, size_t len ); +SYSCALL_FUNC( wld_read, 63 /* SYS_read */ ); + +ssize_t wld_write( int fd, const void *buffer, size_t len ); +SYSCALL_FUNC( wld_write, 64 /* SYS_write */ ); + +int wld_openat( int dirfd, const char *name, int flags ); +SYSCALL_FUNC( wld_openat, 56 /* 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, 57 /* SYS_close */ ); + +void *wld_mmap( void *start, size_t len, int prot, int flags, int fd, off_t offset ); +SYSCALL_FUNC( wld_mmap, 222 /* SYS_mmap */ ); + +int wld_mprotect( const void *addr, size_t len, int prot ); +SYSCALL_FUNC( wld_mprotect, 226 /* SYS_mprotect */ ); + +int wld_prctl( int code, long arg ); +SYSCALL_FUNC( wld_prctl, 167 /* SYS_prctl */ ); + +uid_t wld_getuid(void); +SYSCALL_NOERR( wld_getuid, 174 /* SYS_getuid */ ); + +gid_t wld_getgid(void); +SYSCALL_NOERR( wld_getgid, 176 /* SYS_getgid */ ); + +uid_t wld_geteuid(void); +SYSCALL_NOERR( wld_geteuid, 175 /* SYS_geteuid */ ); + +gid_t wld_getegid(void); +SYSCALL_NOERR( wld_getegid, 177 /* SYS_getegid */ ); + #else #error preloader not implemented for this CPU #endif @@ -725,6 +829,9 @@ static void map_so_lib( const char *name, struct wld_link_map *l) #elif defined(__x86_64__) if( header->e_machine != EM_X86_64 ) fatal_error("%s: not an x86-64 ELF binary... don't know how to load it\n", name ); +#elif defined(__aarch64__) + if( header->e_machine != EM_AARCH64 ) + fatal_error("%s: not an aarchs64 ELF binary... don't know how to load it\n", name ); #endif if (header->e_phnum > sizeof(loadcmds)/sizeof(loadcmds[0]))