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
|
define(`CC', `
dnl')
CC Copyright (C) 2023-2024 Free Software Foundation, Inc.
CC
CC This file is part of GNU Emacs.
CC
CC GNU Emacs is free software: you can redistribute it and/or modify
CC it under the terms of the GNU General Public License as published
CC by the Free Software Foundation, either version 3 of the License,
CC or (at your option) any later version.
CC
CC GNU Emacs is distributed in the hope that it will be useful, but
CC WITHOUT ANY WARRANTY; without even the implied warranty of
CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
CC General Public License for more details.
CC
CC You should have received a copy of the GNU General Public License
CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
.section .text
.global _start
_start:
dnl movq $35, %rax CC SYS_nanosleep
dnl leaq timespec(%rip), %rdi
dnl xorq %rsi, %rsi
dnl syscall
popq %r13 CC original SP
popq %r15 CC size of load area.
movq $-1, %r12 CC r12 is the interpreter fd
.next_action:
movq (%rsp), %r14 CC action number
movq %r14, %r15 CC original action number
andq $-17, %r14
cmpq $0, %r14 CC open file?
je .open_file
cmpq $3, %r14 CC jump?
je .rest_of_exec
cmpq $4, %r14 CC anonymous mmap?
je .do_mmap_anon
.do_mmap:
movq $9, %rax CC SYS_mmap
movq 8(%rsp), %rdi CC address
movq 16(%rsp), %r9 CC offset
movq 24(%rsp), %rdx CC protection
movq 32(%rsp), %rsi CC length
movq 40(%rsp), %r10 CC flags
CC set r8 to the primary fd unless r15 & 16
testq $16, %r15
movq %r12, %r8
cmovzq %rbx, %r8
.do_mmap_1:
syscall
cmpq $-1, %rax CC mmap failed
je .perror
movq 48(%rsp), %r9 CC clear
testq %r9, %r9
jz .continue
movq 8(%rsp), %r10 CC start of mapping
addq 32(%rsp), %r10 CC end of mapping
subq %r9, %r10 CC start of clear area
.again:
testq %r9, %r9
jz .continue
subq $1, %r9
movb $0, (%r10, %r9, 1)
jmp .again
.continue:
leaq 56(%rsp), %rsp
jmp .next_action
.do_mmap_anon:
movq $9, %rax CC SYS_mmap
movq 8(%rsp), %rdi CC address
movq 16(%rsp), %r9 CC offset
movq 24(%rsp), %rdx CC protection
movq 32(%rsp), %rsi CC length
movq 40(%rsp), %r10 CC flags
movq $-1, %r8 CC -1
jmp .do_mmap_1
.open_file:
movq $2, %rax CC SYS_open
leaq 8(%rsp), %rdi CC rdi = %rsp + 8
xorq %rsi, %rsi CC flags = O_RDONLY
xorq %rdx, %rdx CC mode = 0
syscall
cmpq $-1, %rax CC open failed
jle .perror
movq %rdi, %rsp CC rsp = start of string
subq $1, %rsp
movq %rsp, %r14 CC r14 = start of string
.nextc:
addq $1, %rsp
movb (%rsp), %dil CC rdi = *rsp
cmpb $47, %dil CC *rsp == '/'?
jne .nextc1
movq %rsp, %r14 CC r14 = rsp
addq $1, %r14 CC r14 = char past separator
.nextc1:
cmpb $0, %dil CC *rsp == 0?
jne .nextc
addq $8, %rsp CC adjust past rsp prior to rounding
andq $-8, %rsp CC round rsp up to the next quad
testq $16, %r15 CC r15 & 16?
jz .primary
movq %rax, %r12 CC otherwise, move fd to r12
jmp .next_action
.primary:
movq %rax, %rbx CC if not, move fd to rbx
movq $157, %rax CC SYS_prctl
movq $15, %rdi CC PR_SET_NAME
movq %r14, %rsi CC arg1
xorq %rdx, %rdx CC arg2
xorq %r10, %r10 CC arg3
xorq %r8, %r8 CC arg4
xorq %r9, %r9 CC arg5
syscall
jmp .next_action
.perror:
movq %rax, %r12 CC error code
negq %r12
movq $1, %rax CC SYS_write
movq $1, %rdi CC stdout
leaq error(%rip), %rsi CC buffer
movq $23, %rdx CC count
syscall
movq $60, %rax CC SYS_exit
movq %r12, %rdi CC code
syscall
.rest_of_exec: CC rsp now points to six quads:
movq %rsp, %r8 CC now, they are r8
movq %r13, %rsp CC restore SP
popq %r10 CC argc
leaq 8(%rsp,%r10,8), %rsp CC now at start of environ
.skip_environ:
popq %r10 CC envp[N]
testq %r10, %r10 CC envp[n]?
jnz .skip_environ CC otherwise, rsp is now at the start of auxv
.one_auxv:
popq %rcx CC auxv type
addq $8, %rsp CC skip value
testq %rcx, %rcx CC is 0?
jz .cleanup
cmpq $3, %rcx CC is AT_PHDR?
je .replace_phdr
cmpq $4, %rcx CC is AT_PHENT?
je .replace_phent
cmpq $5, %rcx CC is AT_PHNUM?
je .replace_phnum
cmpq $9, %rcx CC is AT_ENTRY?
je .replace_entry
cmpq $7, %rcx CC is AT_BASE?
je .replace_base
jmp .one_auxv
.replace_phdr:
movq 40(%r8), %r9
movq %r9, -8(%rsp) CC set at_phdr
jmp .one_auxv
.replace_phent:
movq 24(%r8), %r9
movq %r9, -8(%rsp) CC set at_phent
jmp .one_auxv
.replace_phnum:
movq 32(%r8), %r9
movq %r9, -8(%rsp) CC set at_phnum
jmp .one_auxv
.replace_entry:
movq 16(%r8), %r9
movq %r9, -8(%rsp) CC set at_entry
jmp .one_auxv
.replace_base:
movq 48(%r8), %r9
movq %r9, -8(%rsp) CC set at_base
jmp .one_auxv
.cleanup:
movq $3, %rax CC SYS_close
cmpq $-1, %r12 CC see if interpreter fd is set
je .cleanup_1
movq %r12, %rdi
syscall
movq $3, %rax CC SYS_close
.cleanup_1:
movq %rbx, %rdi
syscall
.enter:
pushq $0
popfq CC clear FP state
movq %r13, %rsp CC restore SP
xorq %rdx, %rdx CC clear rtld_fini
jmpq *8(%r8) CC entry
error:
.ascii "_start: internal error."
timespec:
.quad 10
.quad 10
|