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
|
# Copyright (C) 2023-2024 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#
# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# GNU Emacs is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
.section .text
.global _start
_start:
# movl $162, %eax # SYS_nanosleep
# leal timespec, %ebx
# xorl %ecx, %ecx
# int $0x80
leal 8(%esp), %ebp # ebp = start of load area
subl $8, %esp # (%esp) = primary fd, 4(%esp) = secondary fd
movl $-1, 4(%esp)
.next_action:
movl (%ebp), %edx # edx = action number
andl $-17, %edx
cmpl $0, %edx # open file?
je .open_file
cmpl $3, %edx # jump?
je .rest_of_exec
cmpl $4, %edx # anonymous mmap?
je .do_mmap_anon
.do_mmap:
subl $24, %esp
movl $90, %eax # SYS_old_mmap
movl %esp, %ebx
movl 4(%ebp), %ecx # address
movl %ecx, (%esp)
movl 16(%ebp), %ecx # length
movl %ecx, 4(%esp)
movl 12(%ebp), %ecx # protection
movl %ecx, 8(%esp)
movl 20(%ebp), %ecx # flags
movl %ecx, 12(%esp)
testl $16, (%ebp) # primary?
movl 28(%esp), %ecx
cmovzl 24(%esp), %ecx
movl %ecx, 16(%esp) # fd
movl 8(%ebp), %ecx # offset
movl %ecx, 20(%esp)
.do_mmap_1:
int $0x80
addl $24, %esp # restore esp
cmpl $-1, %eax # mmap failed?
je .perror
movl 24(%ebp), %ecx # clear
testl %ecx, %ecx
jz .continue
movl 4(%ebp), %esi # start of mapping
addl 16(%ebp), %esi # end of mapping
subl %ecx, %esi # 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 # SYS_old_mmap
movl %esp, %ebx
movl 4(%ebp), %ecx # address
movl %ecx, (%esp)
movl 16(%ebp), %ecx # length
movl %ecx, 4(%esp)
movl 12(%ebp), %ecx # protection
movl %ecx, 8(%esp)
movl 20(%ebp), %ecx # flags
movl %ecx, 12(%esp)
movl $-1, 16(%esp) # fd
movl 8(%ebp), %ecx # offset
movl %ecx, 20(%esp)
jmp .do_mmap_1
.open_file:
movl $5, %eax # SYS_open
leal 4(%ebp), %ebx # ebx = %esp + 8
pushl %ebx
xorl %ecx, %ecx # flags = O_RDONLY
xorl %edx, %edx # mode = 0
int $0x80
cmpl $-1, %eax # open failed?
jle .perror
movl %ebp, %esi # (esi) = original action number
popl %ebp # ebp = start of string
movl %ebp, %ecx # char past separator
decl %ebp
.nextc:
incl %ebp
movb (%ebp), %dl # dl = *ebp
cmpb $47, %dl # dl == '\?'?
jne .nextc1
leal 1(%ebp), %ecx # ecx = char past separator
.nextc1:
cmpb $0, %dl # dl == 0?
jne .nextc
addl $4, %ebp # adjust past ebp prior to rounding
andl $-4, %ebp # round ebp up to the next long
testl $16, (%esi) # original action number & 16?
jz .primary
movl %eax, 4(%esp) # secondary fd = eax
jmp .next_action
.primary:
pushl %ebp
xorl %esi, %esi # arg3
movl %eax, 4(%esp) # primary fd = eax
xorl %edx, %edx # arg2
movl $15, %ebx # PR_SET_NAME, arg1 = ecx
xorl %edi, %edi # arg4
movl $172, %eax # SYS_prctl
xorl %ebp, %ebp # arg5
int $0x80 # syscall
popl %ebp
jmp .next_action
.perror:
movl %eax, %ebx
negl %ebx
movl $1, %eax
int $0x80
.rest_of_exec:
movl 8(%esp), %ecx # ecx = original stack pointer
movl (%ecx), %esi # esi = argc
leal 8(%ecx, %esi, 4), %ecx # ecx = start of environ
.skip_environ:
movl (%ecx), %esi # envp[N]
addl $4, %ecx
testl %esi, %esi # envp[n] ?
jnz .skip_environ # otherwise, esi is now at the start of auxv
.one_auxv:
movl (%ecx), %esi # auxv type
leal 8(%ecx), %ecx # skip to next auxv
testl %esi, %esi # is 0?
jz .cleanup
cmpl $3, %esi # is AT_PHDR
je .replace_phdr
cmpl $4, %esi # is AT_PHENT?
je .replace_phent
cmpl $5, %esi # is AT_PHNUM?
je .replace_phnum
cmpl $9, %esi # is AT_ENTRY?
je .replace_entry
cmpl $7, %esi # 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 # SYS_close
cmpl $-1, 4(%esp) # see if interpreter fd is set
je .cleanup_1
movl 4(%esp), %ebx
int $0x80
movl $6, %eax # SYS_close
.cleanup_1:
movl (%esp), %ebx
int $0x80
.enter:
pushl $0
popfl # restore floating point state
movl 8(%esp), %esp # restore initial stack pointer
xorl %edx, %edx # clear rtld_fini
jmpl *4(%ebp) # entry
timespec:
.long 10
.long 10
|