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 .section .text
19 .global _start
20 _start:
21 @mov r7, #162 @ SYS_nanosleep
22 @adr r0, timespec @ req
23 @mov r1, #0 @ rem
24 @swi #0 @ syscall
25 mov r8, sp @ r8 = sp
26 ldr r9, [r8], #8 @ r9 = original sp, r8 += 8
27 mov r14, #-1 @ r14 = secondary fd
28 .next_action:
29 ldr r11, [r8] @ r11 = action number
30 and r12, r11, #-17 @ actual action number
31 cmp r12, #0 @ open file?
32 beq .open_file @ open file.
33 cmp r12, #3 @ jump?
34 beq .rest_of_exec @ jump to code.
35 cmp r12, #4 @ anonymous mmap?
36 beq .do_mmap_anon @ anonymous mmap.
37 .do_mmap:
38 add r6, r8, #4 @ r6 = r8 + 4
39 ldm r6!, {r0, r5} @ vm_address, file_offset
40 ldm r6!, {r1, r2} @ protection, length
41 mov r3, r1 @ swap
42 lsr r5, #12 @ divide file offset by page size
43 mov r1, r2 @ swap
44 mov r2, r3 @ swap
45 ldm r6!, {r3, r12} @ flags, clear
46 tst r11, #16 @ primary fd?
47 mov r4, r10 @ primary fd
48 beq .do_mmap_1
49 mov r4, r14 @ secondary fd
50 .do_mmap_1:
51 mov r7, #192 @ SYS_mmap2
52 swi #0 @ syscall
53 ldr r2, [r8, #4] @ vm_address
54 cmp r2, r0 @ rc == vm_address?
55 bne .perror
56 add r0, r1, r2 @ r0 = length + vm_address
57 sub r3, r0, r12 @ r3 = r0 - clear
58 mov r1, #0 @ r1 = 0
59 .align:
60 cmp r0, r3 @ r0 == r3?
61 beq .continue @ continue
62 tst r3, #3 @ r3 & 3?
63 bne .fill32 @ fill aligned
64 strb r1, [r3], #1 @ fill byte
65 b .align @ align again
66 .fill32:
67 sub r2, r0, r3 @ r2 = r0 - r3
68 cmp r2, #31 @ r2 >= 32?
69 ble .fillb @ start filling bytes
70 str r1, [r3], #4 @ *r3++ = 0
71 str r1, [r3], #4 @ *r3++ = 0
72 str r1, [r3], #4 @ *r3++ = 0
73 str r1, [r3], #4 @ *r3++ = 0
74 str r1, [r3], #4 @ *r3++ = 0
75 str r1, [r3], #4 @ *r3++ = 0
76 str r1, [r3], #4 @ *r3++ = 0
77 str r1, [r3], #4 @ *r3++ = 0
78 b .fill32
79 .fillb:
80 cmp r0, r3 @ r0 == r3
81 beq .continue @ done
82 strb r1, [r3], #1 @ ((char *) r3)++ = 0
83 b .fillb
84 .continue:
85 add r8, r8, #28 @ next action
86 b .next_action
87 .do_mmap_anon:
88 add r6, r8, #4 @ r6 = r8 + 4
89 ldm r6!, {r0, r5} @ vm_address, file_offset
90 ldm r6!, {r1, r2} @ protection, length
91 mov r3, r1 @ swap
92 lsr r5, #12 @ divide file offset by page size
93 mov r1, r2 @ swap
94 mov r2, r3 @ swap
95 ldm r6!, {r3, r12} @ flags, clear
96 mov r4, #-1 @ fd
97 b .do_mmap_1
98 .open_file:
99 mov r7, #5 @ SYS_open
100 add r0, r8, #4 @ file name
101 mov r1, #0 @ O_RDONLY
102 mov r2, #0 @ mode
103 swi #0 @ syscall
104 cmp r0, #-1 @ r0 <= -1?
105 ble .perror
106 add r8, r8, #4 @ r8 = start of string
107 mov r1, r8 @ r1 = r8
108 .nextc:
109 ldrb r2, [r8], #1 @ b = *r0++
110 cmp r2, #47 @ dir separator?
111 bne .nextc1 @ not dir separator
112 mov r1, r8 @ r1 = char past separator
113 .nextc1:
114 cmp r2, #0 @ b?
115 bne .nextc @ next character
116 add r8, r8, #3 @ round up r8
117 and r8, r8, #-4 @ mask for round, set r8
118 tst r11, #16 @ primary fd?
119 bne .secondary @ secondary fd
120 mov r10, r0 @ primary fd
121 mov r7, #172 @ SYS_prctl
122 mov r0, #15 @ PR_SET_NAME, r1 = name
123 mov r2, #0 @ arg2
124 mov r3, #0 @ arg3
125 mov r4, #0 @ arg4
126 mov r5, #0 @ arg5
127 swi #0 @ syscall
128 b .next_action @ next action
129 .secondary:
130 mov r14, r0 @ secondary fd
131 b .next_action @ next action
132 .perror:
133 mov r7, #1 @ SYS_exit
134 mvn r0, r0 @ r0 = ~r0
135 add r0, r0, #1 @ r0 += 1
136 swi #0
137 .rest_of_exec:
138 mov r7, r9 @ r7 = original SP
139 ldr r6, [r7] @ argc
140 add r6, r6, #2 @ argc + 2
141 lsl r6, r6, #2 @ argc *= 4
142 add r7, r7, r6 @ now past argv
143 .skipenv:
144 ldr r6, [r7], #4 @ r6 = *r7++
145 cmp r6, #0 @ r6?
146 bne .skipenv @ r6?
147 .one_auxv:
148 ldr r6, [r7], #8 @ r6 = *r7, r7 += 2
149 cmp r6, #0 @ !r6?
150 beq .cleanup @ r6?
151 cmp r6, #3 @ is AT_PHDR?
152 beq .replace_phdr @ replace
153 cmp r6, #4 @ is AT_PHENT?
154 beq .replace_phent @ replace
155 cmp r6, #5 @ is AT_PHNUM?
156 beq .replace_phnum @ replace
157 cmp r6, #9 @ is AT_ENTRY?
158 beq .replace_entry @ replace
159 cmp r6, #7 @ is AT_BASE?
160 beq .replace_base @ replace
161 b .one_auxv @ next auxv
162 .replace_phdr:
163 ldr r6, [r8, #20] @ at_phdr
164 str r6, [r7, #-4] @ store value
165 b .one_auxv
166 .replace_phent:
167 ldr r6, [r8, #12] @ at_phent
168 str r6, [r7, #-4] @ store value
169 b .one_auxv
170 .replace_phnum:
171 ldr r6, [r8, #16] @ at_phnum
172 str r6, [r7, #-4] @ store value
173 b .one_auxv
174 .replace_entry:
175 ldr r6, [r8, #8] @ at_entry
176 str r6, [r7, #-4] @ store value
177 b .one_auxv
178 .replace_base:
179 ldr r6, [r8, #24] @ at_base
180 str r6, [r7, #-4] @ store value
181 b .one_auxv
182 .cleanup:
183 cmp r14, #-1 @ secondary fd set?
184 bne .cleanup1 @ not set
185 mov r7, #6 @ SYS_close
186 mov r0, r14 @ secondary fd
187 swi #0 @ syscall
188 .cleanup1:
189 mov r7, #6 @ SYS_close
190 mov r0, r10 @ primary fd
191 swi #0 @ syscall
192 .enter:
193 mov sp, r9 @ restore original SP
194 mov r0, #0 @ clear rtld_fini
195 ldr r1, [r8, #4] @ branch to code
196 bx r1
197
198 timespec:
199 .long 10
200 .long 10
201
202 @ Local Variables:
203 @ asm-comment-char: 64
204 @ End: