[1/2] loader: Build the preloader for ARM64

André Hentschel nerv at dawncrow.de
Fri Oct 20 14:14:43 CDT 2017


Signed-off-by: André Hentschel <nerv at dawncrow.de>
---
 configure.ac       |   2 +-
 loader/preloader.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 76c7af5..12462ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2004,7 +2004,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 5e6add7..3caae32 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -455,6 +455,122 @@ 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"
+                  "mov x19, #0\n\t"
+                  "mov x10, #0\n\t"
+                  "mov x20, #0\n\t"
+                  "mov x21, #0\n\t"
+                  "mov x22, #0\n\t"
+                  "mov x23, #0\n\t"
+                  "mov x24, #0\n\t"
+                  "mov x25, #0\n\t"
+                  "mov x26, #0\n\t"
+                  "mov x27, #0\n\t"
+                  "mov x28, #0\n\t"
+                  "mov x29, #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 +841,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]))
-- 
2.7.4





More information about the wine-patches mailing list