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
|
/*
* i386 linux replacement vdso.
*
* Copyright 2023 Linaro, Ltd.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <asm/unistd.h>
#include "vdso-asmoffset.h"
.macro endf name
.globl \name
.type \name, @function
.size \name, . - \name
.endm
.macro vdso_syscall1 name, nr
\name:
.cfi_startproc
mov %ebx, %edx
.cfi_register %ebx, %edx
mov 4(%esp), %ebx
mov $\nr, %eax
int $0x80
mov %edx, %ebx
ret
.cfi_endproc
endf \name
.endm
.macro vdso_syscall2 name, nr
\name:
.cfi_startproc
mov %ebx, %edx
.cfi_register %ebx, %edx
mov 4(%esp), %ebx
mov 8(%esp), %ecx
mov $\nr, %eax
int $0x80
mov %edx, %ebx
ret
.cfi_endproc
endf \name
.endm
.macro vdso_syscall3 name, nr
\name:
.cfi_startproc
push %ebx
.cfi_adjust_cfa_offset 4
.cfi_rel_offset %ebx, 0
mov 8(%esp), %ebx
mov 12(%esp), %ecx
mov 16(%esp), %edx
mov $\nr, %eax
int $0x80
pop %ebx
.cfi_adjust_cfa_offset -4
.cfi_restore %ebx
ret
.cfi_endproc
endf \name
.endm
__kernel_vsyscall:
.cfi_startproc
int $0x80
ret
.cfi_endproc
endf __kernel_vsyscall
vdso_syscall2 __vdso_clock_gettime, __NR_clock_gettime
vdso_syscall2 __vdso_clock_gettime64, __NR_clock_gettime64
vdso_syscall2 __vdso_clock_getres, __NR_clock_getres
vdso_syscall2 __vdso_gettimeofday, __NR_gettimeofday
vdso_syscall1 __vdso_time, __NR_time
vdso_syscall3 __vdso_getcpu, __NR_gettimeofday
/*
* Signal return handlers.
*/
.cfi_startproc simple
.cfi_signal_frame
/*
* For convenience, put the cfa just above eip in sigcontext, and count
* offsets backward from there. Re-compute the cfa in the two contexts
* we have for signal unwinding. This is far simpler than the
* DW_CFA_expression form that the kernel uses, and is equally correct.
*/
.cfi_def_cfa %esp, SIGFRAME_SIGCONTEXT_eip + 4
.cfi_offset %eip, -4
/* err, -8 */
/* trapno, -12 */
.cfi_offset %eax, -16
.cfi_offset %ecx, -20
.cfi_offset %edx, -24
.cfi_offset %ebx, -28
.cfi_offset %esp, -32
.cfi_offset %ebp, -36
.cfi_offset %esi, -40
.cfi_offset %edi, -44
/*
* While this frame is marked as a signal frame, that only applies to how
* the return address is handled for the outer frame. The return address
* that arrived here, from the inner frame, is not marked as a signal frame
* and so the unwinder still tries to subtract 1 to examine the presumed
* call insn. Thus we must extend the unwind info to a nop before the start.
*/
nop
__kernel_sigreturn:
popl %eax /* pop sig */
.cfi_adjust_cfa_offset -4
movl $__NR_sigreturn, %eax
int $0x80
endf __kernel_sigreturn
.cfi_def_cfa_offset RT_SIGFRAME_SIGCONTEXT_eip + 4
nop
__kernel_rt_sigreturn:
movl $__NR_rt_sigreturn, %eax
int $0x80
endf __kernel_rt_sigreturn
.cfi_endproc
/*
* TODO: Add elf notes. E.g.
*
* #include <linux/elfnote.h>
* ELFNOTE_START(Linux, 0, "a")
* .long LINUX_VERSION_CODE
* ELFNOTE_END
*
* but what version number would we set for QEMU?
*/
|