summaryrefslogtreecommitdiff
path: root/exec/loader-x86.s
blob: 216bc88f976498708b0411bb8687023249b2674b (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
196
197
198
199
200
201
202
203
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	movl	$162, %eax		CC SYS_nanosleep
dnl	leal	timespec, %ebx
dnl	xorl	%ecx, %ecx
dnl	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
	movl	%ebp, %ecx		CC char past separator
	decl	%ebp
.nextc:
	incl	%ebp
	movb	(%ebp), %dl		CC dl = *ebp
	cmpb	$47, %dl		CC dl == '\?'?
	jne	.nextc1
	leal	1(%ebp), %ecx		CC ecx = char past separator
.nextc1:
	cmpb	$0, %dl			CC dl == 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:
	pushl	%ebp
	xorl	%esi, %esi		CC arg3
	movl	%eax, 4(%esp)		CC primary fd = eax
	xorl	%edx, %edx		CC arg2
	movl	$15, %ebx		CC PR_SET_NAME, arg1 = ecx
	xorl	%edi, %edi		CC arg4
	movl	$172, %eax		CC SYS_prctl
	xorl	%ebp, %ebp		CC arg5
	int	$0x80			CC syscall
	popl	%ebp
	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]
	addl	$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
	je	.cleanup_1
	movl	4(%esp), %ebx
	int 	$0x80
	movl	$6, %eax		CC SYS_close
.cleanup_1:
	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