summaryrefslogtreecommitdiff
path: root/exec/loader-x86_64.s
blob: 2ef779e45044433707542b59689838c31aafc1b1 (plain)
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