root/exec/loader-aarch64.s

/* [<][>][^][v][top][bottom][index][help] */
     1 // Copyright (C) 2023 Free Software Foundation, Inc.
     2 //
     3 // This file is part of GNU Emacs.
     4 //
     5 // GNU Emacs is free software: you can redistribute it and/or modify
     6 // it under the terms of the GNU General Public License as published
     7 // by the Free Software Foundation, either version 3 of the License,
     8 // or (at your option) any later version.
     9 //
    10 // GNU Emacs is distributed in the hope that it will be useful, but
    11 // WITHOUT ANY WARRANTY; without even the implied warranty of
    12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13 // General Public License for more details.
    14 //
    15 // You should have received a copy of the GNU General Public License
    16 // along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
    17 
    18 // Notice that aarch64 requires that sp be aligned to 16 bytes while
    19 // accessing memory from sp, so x20 is used to chase down the load
    20 // area.
    21 
    22         .section .text
    23         .global _start
    24 _start:
    25         //mov   x8, 101                 // SYS_nanosleep
    26         //adr   x0, timespec            // req
    27         //mov   x1, #0                  // rem
    28         //svc   #0                      // syscall
    29         mov     x20, sp                 // x20 = sp
    30         ldr     x10, [x20]              // x10 = original SP
    31         add     x20, x20, #16           // x20 = start of load area
    32         mov     x28, #-1                // x28 = secondary fd
    33 .next_action:
    34         ldr     x11, [x20]              // action number
    35         and     x12, x11, #-17          // actual action number
    36         cbz     x12, .open_file         // open file?
    37         cmp     x12, #3                 // jump?
    38         beq     .rest_of_exec
    39         cmp     x12, #4                 // anonymous mmap?
    40         beq     .do_mmap_anon
    41 .do_mmap:
    42         ldr     x0, [x20, 8]            // vm_address
    43         ldr     x1, [x20, 32]           // length
    44         ldr     x2, [x20, 24]           // protection
    45         ldr     x3, [x20, 40]           // flags
    46         tst     x11, #16                // primary fd?
    47         mov     x4, x29                 // primary fd
    48         beq     .do_mmap_1
    49         mov     x4, x28                 // secondary fd
    50 .do_mmap_1:
    51         mov     x8, #222                // SYS_mmap
    52         ldr     x5, [x20, 16]           // file_offset
    53         svc     #0                      // syscall
    54         ldr     x9, [x20, 8]            // length
    55         cmp     x0, x9                  // mmap result
    56         bne     .perror                 // print error
    57         ldr     x3, [x20, 48]           // clear
    58         add     x1, x1, x0              // x1 = vm_address + end
    59         sub     x3, x1, x3              // x3 = x1 - clear
    60         mov     x0, #0                  // x0 = 0
    61 .fill64:
    62         sub     x2, x1, x3              // x2 = x1 - x3
    63         cmp     x2, #63                 // x2 >= 64?
    64         ble     .fillb                  // start filling bytes
    65         stp     x0, x0, [x3]            // x3[0] = 0, x3[1] = 0
    66         stp     x0, x0, [x3, 16]        // x3[2] = 0, x3[3] = 0
    67         stp     x0, x0, [x3, 32]        // x3[4] = 0, x3[5] = 0
    68         stp     x0, x0, [x3, 48]        // x3[6] = 0, x3[7] = 0
    69         add     x3, x3, #64             // x3 += 8
    70         b       .fill64
    71 .fillb:
    72         cmp     x1, x3                  // x1 == x3?
    73         beq     .continue               // done
    74         strb    w0, [x3], #1            // ((char *) x3)++ = 0
    75         b       .fillb
    76 .continue:
    77         add     x20, x20, #56           // next action
    78         b       .next_action
    79 .do_mmap_anon:
    80         ldr     x0, [x20, 8]            // vm_address
    81         ldr     x1, [x20, 32]           // length
    82         ldr     x2, [x20, 24]           // protection
    83         ldr     x3, [x20, 40]           // flags
    84         mov     x4, #-1                 // fd
    85         b       .do_mmap_1
    86 .open_file:
    87         mov     x8, #56                 // SYS_openat
    88         mov     x0, #-100               // AT_FDCWD
    89         add     x1, x20, #8             // file name
    90         mov     x2, #0                  // O_RDONLY
    91         mov     x3, #0                  // mode
    92         svc     #0                      // syscall
    93         cmp     x0, #-1                 // rc < 0?
    94         ble     .perror
    95         mov     x19, x1                 // x19 == x1
    96 .nextc:
    97         ldrb    w2, [x1], #1            // b = *x1++
    98         cmp     w2, #47                 // dir separator?
    99         bne     .nextc1                 // not dir separator
   100         mov     x19, x1                 // x19 = char past separator
   101 .nextc1:
   102         cbnz    w2, .nextc              // b?
   103         add     x1, x1, #7              // round up x1
   104         and     x20, x1, #-8            // mask for round, set x20
   105         tst     x11, #16                // primary fd?
   106         bne     .secondary              // secondary fd
   107         mov     x29, x0                 // primary fd
   108         mov     x8, #167                // SYS_prctl
   109         mov     x0, #15                 // PR_SET_NAME
   110         mov     x1, x19                 // basename
   111         mov     x2, #0                  // arg2
   112         mov     x3, #0                  // arg3
   113         mov     x4, #0                  // arg4
   114         mov     x5, #0                  // arg5
   115         svc     #0                      // syscall
   116         b       .next_action            // next action
   117 .secondary:
   118         mov     x28, x0                 // secondary fd
   119         b       .next_action            // next action.
   120 .perror:
   121         mov     x8, #93                 // SYS_exit
   122         mvn     x0, x0                  // x1 = ~x0
   123         add     x0, x0, 1               // x1 += 1
   124         svc     #0                      // exit
   125 .rest_of_exec:
   126         mov     x7, x20                 // x7 = x20
   127         mov     x20, x10                // x20 = x10
   128         ldr     x9, [x20]               // argc
   129         add     x9, x9, #2              // x9 += 2
   130         lsl     x9, x9, #3              // argc * 8
   131         add     x20, x20, x9            // now past argv
   132 .skipenv:
   133         ldr     x9, [x20], #8           // x9 = *envp++
   134         cbnz    x9, .skipenv            // x9?
   135 .one_auxv:
   136         ldr     x9, [x20], #16          // x9 = *sp, sp += 2
   137         cbz     x9, .cleanup            // !x9?
   138         cmp     x9, #3                  // is AT_PHDR?
   139         beq     .replace_phdr           // replace
   140         cmp     x9, #4                  // is AT_PHENT?
   141         beq     .replace_phent          // replace
   142         cmp     x9, #5                  // is AT_PHNUM?
   143         beq     .replace_phnum          // replace
   144         cmp     x9, #9                  // is AT_ENTRY?
   145         beq     .replace_entry          // replace
   146         cmp     x9, #7                  // is AT_BASE?
   147         beq     .replace_base           // replace
   148         b       .one_auxv               // next auxv
   149 .replace_phdr:
   150         ldr     x9, [x7, 40]            // at_phdr
   151         str     x9, [x20, -8]           // store value
   152         b       .one_auxv
   153 .replace_phent:
   154         ldr     x9, [x7, 24]            // at_phent
   155         str     x9, [x20, -8]           // store value
   156         b       .one_auxv
   157 .replace_phnum:
   158         ldr     x9, [x7, 32]            // at_phnum
   159         str     x9, [x20, -8]           // store value
   160         b       .one_auxv
   161 .replace_entry:
   162         ldr     x9, [x7, 16]            // at_entry
   163         str     x9, [x20, -8]           // store value
   164         b       .one_auxv
   165 .replace_base:
   166         ldr     x9, [x7, 48]            // at_base
   167         str     x9, [x20, -8]           // store value
   168         b       .one_auxv
   169 .cleanup:
   170         cmp     x28, #-1                // is secondary fd set?
   171         bne     .cleanup1               // not set
   172         mov     x8, #57                 // SYS_close
   173         mov     x0, x28                 // secondary fd
   174         svc     #0                      // syscall
   175 .cleanup1:
   176         mov     x8, #57                 // SYS_close
   177         mov     x0, x29                 // primary fd
   178         svc     #0                      // syscall
   179 .enter:
   180         mov     sp, x10                 // restore original SP
   181         mov     x0, #0                  // clear rtld_fini
   182         ldr     x1, [x7, 8]             // branch to code
   183         br      x1
   184 
   185 timespec:
   186         .quad 10
   187         .quad 10

/* [<][>][^][v][top][bottom][index][help] */