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