1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
// Copyright (C) 2023-2025 Free Software Foundation, Inc.
//
// This file is part of GNU Emacs.
//
// GNU Emacs is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// GNU Emacs is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
// Notice that aarch64 requires that sp be aligned to 16 bytes while
// accessing memory from sp, so x20 is used to chase down the load
// area.
.section .text
.global _start
_start:
// mov x8, 101 // SYS_nanosleep
// adr x0, timespec // req
// mov x1, #0 // rem
// svc #0 // syscall
mov x20, sp // x20 = sp
ldr x10, [x20] // x10 = original SP
add x20, x20, #16 // x20 = start of load area
mov x28, #-1 // x28 = secondary fd
next_action:
ldr x11, [x20] // action number
and x12, x11, #-17 // actual action number
cbz x12, open_file // open file?
cmp x12, #3 // jump?
beq rest_of_exec
cmp x12, #4 // anonymous mmap?
beq do_mmap_anon
do_mmap:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
tst x11, #16 // primary fd?
mov x4, x29 // primary fd
beq do_mmap_1
mov x4, x28 // secondary fd
do_mmap_1:
mov x8, #222 // SYS_mmap
ldr x5, [x20, 16] // file_offset
svc #0 // syscall
ldr x9, [x20, 8] // length
cmp x0, x9 // mmap result
bne perror // print error
ldr x3, [x20, 48] // clear
add x1, x1, x0 // x1 = vm_address + end
sub x3, x1, x3 // x3 = x1 - clear
mov x0, #0 // x0 = 0
fill64:
sub x2, x1, x3 // x2 = x1 - x3
cmp x2, #63 // x2 >= 64?
ble fillb // start filling bytes
stp x0, x0, [x3] // x3[0] = 0, x3[1] = 0
stp x0, x0, [x3, 16] // x3[2] = 0, x3[3] = 0
stp x0, x0, [x3, 32] // x3[4] = 0, x3[5] = 0
stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0
add x3, x3, #64 // x3 += 8
b fill64
fillb:
cmp x1, x3 // x1 == x3?
beq continue // done
strb w0, [x3], #1 // ((char *) x3)++ = 0
b fillb
continue:
add x20, x20, #56 // next action
b next_action
do_mmap_anon:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
mov x4, #-1 // fd
b do_mmap_1
open_file:
mov x8, #56 // SYS_openat
mov x0, #-100 // AT_FDCWD
add x1, x20, #8 // file name
mov x2, #0 // O_RDONLY
mov x3, #0 // mode
svc #0 // syscall
cmp x0, #-1 // rc < 0?
ble perror
mov x19, x1 // x19 == x1
nextc:
ldrb w2, [x1], #1 // b = *x1++
cmp w2, #47 // dir separator?
bne nextc1 // not dir separator
mov x19, x1 // x19 = char past separator
nextc1:
cbnz w2, nextc // b?
add x1, x1, #7 // round up x1
and x20, x1, #-8 // mask for round, set x20
tst x11, #16 // primary fd?
bne secondary // secondary fd
mov x29, x0 // primary fd
mov x8, #167 // SYS_prctl
mov x0, #15 // PR_SET_NAME
mov x1, x19 // basename
mov x2, #0 // arg2
mov x3, #0 // arg3
mov x4, #0 // arg4
mov x5, #0 // arg5
svc #0 // syscall
b next_action // next action
secondary:
mov x28, x0 // secondary fd
b next_action // next action.
perror:
mov x8, #93 // SYS_exit
mvn x0, x0 // x1 = ~x0
add x0, x0, 1 // x1 += 1
svc #0 // exit
rest_of_exec:
mov x7, x20 // x7 = x20
mov x8, x10 // x8 = x10
ldr x9, [x8], #16 // (void *) x8 += 2
lsl x9, x9, #3 // argc * 8
add x8, x8, x9 // now past argv
skip_environ:
ldr x9, [x8], #8 // x9 = *envp++
cbnz x9, skip_environ // x9?
// Skip the auxiliary vector.
1: ldp x11, x12, [x8], #16 // a_type, a_un.a_val
cbnz x11, 1b // a_type != NULL
// Prepare sufficient space at x20 for the file name string.
// Load the aforesaid string, and its length.
ldr x6, [x7, 56] // string length
add x6, x6, 1
add x5, x7, 64 // string pointer
sub x4, x10, x8 // number of elements to copy
sub x7, x8, x6 // AT_EXECFN location
and x7, x7, -8 // align value
add x4, x7, x4 // destination argc
and x4, x4, -16 // align destination argc
// Load values that must be preserved into registers x14-x19.
// x14 = cmd->entry
// x15 = cmd->at_entry
// x16 = cmd->at_phent
// x17 = cmd->at_phnum
// x18 = cmd->at_phdr
// x19 = cmd->at_base
ldp x14, x15, [x20, 8]
ldp x16, x17, [x20, 24]
ldp x18, x19, [x20, 40]
// Move the string to a safe location, if necessary.
sub x3, x4, x5 // distance from dest to string
cmp x3, x6 // distance > length
bge copy_env_and_args // not necessary
mov x2, x5 // src
sub x5, x4, x6 // backup string
mov x1, x5 // dst
add x9, x2, x6 // src end
cmp x2, x9
bcs copy_env_and_args
1: ldrb w3, [x2], #1
strb w3, [x1], #1
cmp x2, x9
blo 1b
copy_env_and_args:
// Copy argc and the environment array.
mov x8, x10
mov x10, x4
1: ldr x9, [x8], #8 // envp
str x9, [x4], #8
cbnz x9, 1b
1: ldr x9, [x8], #8 // environ
str x9, [x4], #8
cbnz x9, 1b
copy_auxv:
ldp x11, x12, [x8], #16 // a_type, a_un.a_val
stp x11, x12, [x4], #16 // write value
cbz x11, cleanup // AT_NULL
cmp x11, #3 // AT_PHDR
csel x12, x18, x12, eq
cmp x11, #4 // AT_PHENT
csel x12, x16, x12, eq
cmp x11, #5 // AT_PHNUM
csel x12, x17, x12, eq
cmp x11, #9 // AT_ENTRY
csel x12, x15, x12, eq
cmp x11, #7 // AT_BASE
csel x12, x19, x12, eq
cmp x11, #31 // AT_EXECFN
csel x12, x7, x12, eq
str x12, [x4, -8] // replace value
b copy_auxv
cleanup:
// Copy the filename.
add x9, x5, x6 // end
cmp x5, x9
bcs 2f
1: ldrb w3, [x5], #1
strb w3, [x7], #1
cmp x5, x9
blo 1b
// Close file descriptors.
2: cmp x28, #-1 // is secondary fd set?
beq cleanup1 // not set
mov x8, #57 // SYS_close
mov x0, x28 // secondary fd
svc #0 // syscall
cleanup1:
mov x8, #57 // SYS_close
mov x0, x29 // primary fd
svc #0 // syscall
enter:
mov sp, x10 // restore original SP
mov x0, #0 // clear rtld_fini
br x14
// timespec:
// .quad 10
// .quad 10
// Local Variables:
// asm-comment-char: ?/
// End:
|