summaryrefslogtreecommitdiff
path: root/exec/loader-x86.s
blob: ee69b26d78bab159040f43c2a10b8aa76e083e2d (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
define(`CC', `
dnl')

CC Copyright (C) 2023 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:
	#movl	$162, %eax		CC SYS_nanosleep
	#leal	timespec, %ebx
	#xorl	%ecx, %ecx
	#int	$0x80
	leal	8(%esp), %ebp		CC ebp = start of load area
	subl	$8, %esp		CC (%esp) = primary fd, 4(%esp) = secondary fd
	movl	$-1, 4(%esp)
.next_action:
	movl	(%ebp), %edx		CC edx = action number
	andl	$-17, %edx
	cmpl	$0, %edx		CC open file?
	je	.open_file
	cmpl	$3, %edx		CC jump?
	je	.rest_of_exec
	cmpl	$4, %edx		CC anonymous mmap?
	je	.do_mmap_anon
.do_mmap:
	subl	$24, %esp
	movl	$90, %eax		CC SYS_old_mmap
	movl	%esp, %ebx
	movl	4(%ebp), %ecx		CC address
	movl	%ecx, (%esp)
	movl	16(%ebp), %ecx		CC length
	movl	%ecx, 4(%esp)
	movl	12(%ebp), %ecx		CC protection
	movl	%ecx, 8(%esp)
	movl	20(%ebp), %ecx		CC flags
	movl	%ecx, 12(%esp)
	testl	$16, (%ebp)		CC primary?
	movl	28(%esp), %ecx
	cmovzl	24(%esp), %ecx
	movl	%ecx, 16(%esp)		CC fd
	movl	8(%ebp), %ecx		CC offset
	movl	%ecx, 20(%esp)
.do_mmap_1:
	int	$0x80
	addl	$24, %esp		CC restore esp
	cmpl	$-1, %eax		CC mmap failed?
	je	.perror
	movl	24(%ebp), %ecx		CC clear
	testl	%ecx, %ecx
	jz	.continue
	movl	4(%ebp), %esi		CC start of mapping
	addl	16(%ebp), %esi		CC end of mapping
	subl	%ecx, %esi		CC start of clear area
.again:
	testl	%ecx, %ecx
	jz	.continue
	subl	$1, %ecx
	movb	$0, (%esi, %ecx, 1)
	jmp	.again
.continue:
	leal	28(%ebp), %ebp
	jmp	.next_action
.do_mmap_anon:
	subl	$24, %esp
	movl	$90, %eax		CC SYS_old_mmap
	movl	%esp, %ebx
	movl	4(%ebp), %ecx		CC address
	movl	%ecx, (%esp)
	movl	16(%ebp), %ecx		CC length
	movl	%ecx, 4(%esp)
	movl	12(%ebp), %ecx		CC protection
	movl	%ecx, 8(%esp)
	movl	20(%ebp), %ecx		CC flags
	movl	%ecx, 12(%esp)
	movl	$-1, 16(%esp)		CC fd
	movl	8(%ebp), %ecx		CC offset
	movl	%ecx, 20(%esp)
	jmp	.do_mmap_1
.open_file:
	movl	$5, %eax		CC SYS_open
	leal	4(%ebp), %ebx		CC ebx = %esp + 8
	pushl	%ebx
	xorl	%ecx, %ecx		CC flags = O_RDONLY
	xorl	%edx, %edx		CC mode = 0
	int	$0x80
	cmpl	$-1, %eax		CC open failed?
	jle	.perror
	movl	%ebp, %esi		CC (esi) = original action number
	popl	%ebp			CC ebp = start of string
	decl	%ebp
.nextc:
	incl	%ebp
	cmpb	$0, (%ebp)		CC *ebp == 0?
	jne	.nextc
	addl	$4, %ebp		CC adjust past ebp prior to rounding
	andl	$-4, %ebp		CC round ebp up to the next long
	testl	$16, (%esi)		CC original action number & 16?
	jz	.primary
	movl	%eax, 4(%esp)		CC secondary fd = eax
	jmp	.next_action
.primary:
	movl	%eax, (%esp)		CC primary fd = eax
	jmp	.next_action
.perror:
	movl	%eax, %ebx
	negl	%ebx
	movl	$1, %eax
	int	$0x80
.rest_of_exec:
	movl	8(%esp), %ecx		CC ecx = original stack pointer
	movl	(%ecx), %esi		CC esi = argc
	leal	8(%ecx, %esi, 4), %ecx	CC ecx = start of environ
.skip_environ:
	movl	(%ecx), %esi		CC envp[N]
	subl	$4, %ecx
	testl	%esi, %esi		CC envp[n] ?
	jnz	.skip_environ		CC otherwise, esi is now at the start of auxv
.one_auxv:
	movl	(%ecx), %esi		CC auxv type
	leal	8(%ecx), %ecx		CC skip to next auxv
	testl	%esi, %esi		CC is 0?
	jz	.cleanup
	cmpl	$3, %esi		CC is AT_PHDR
	je	.replace_phdr
	cmpl	$4, %esi		CC is AT_PHENT?
	je	.replace_phent
	cmpl	$5, %esi		CC is AT_PHNUM?
	je	.replace_phnum
	cmpl	$9, %esi		CC is AT_ENTRY?
	je	.replace_entry
	cmpl	$7, %esi		CC is AT_BASE
	je	.replace_base
	jmp	.one_auxv
.replace_phdr:
	movl	20(%ebp), %esi
	movl	%esi, -4(%ecx)
	jmp	.one_auxv
.replace_phent:
	movl	12(%ebp), %esi
	movl	%esi, -4(%ecx)
	jmp	.one_auxv
.replace_phnum:
	movl	16(%ebp), %esi
	movl	%esi, -4(%ecx)
	jmp	.one_auxv
.replace_entry:
	movl	8(%ebp), %esi
	movl	%esi, -4(%ecx)
	jmp	.one_auxv
.replace_base:
	movl	24(%ebp), %esi
	movl	%esi, -4(%ecx)
	jmp	.one_auxv
.cleanup:
	movl	$6, %eax		CC SYS_close
	cmpl	$1, -4(%esp)		CC see if interpreter fd is set
	jne	.cleanup_1
	movl	-4(%esp), %ebx
	int 	$0x80
.cleanup_1:
	movl	$6, %eax		CC SYS_close
	movl	(%esp), %ebx
	int	$0x80
.enter:
	pushl	$0
	popfl				CC restore floating point state
	movl	8(%esp), %esp		CC restore initial stack pointer
	xorl	%edx, %edx		CC clear rtld_fini
	jmpl	*4(%ebp)		CC entry

timespec:
	.long	10
	.long	10