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
204
205
206
207
208
209
210
211
212
|
##--------------------------------------------------------------------##
##--- The core dispatch loop, for jumping to a code address. ---##
##--- vg_dispatch.S ---##
##--------------------------------------------------------------------##
/*
This file is part of Valgrind, an x86 protected-mode emulator
designed for debugging and profiling binaries on x86-Unixes.
Copyright (C) 2000-2002 Julian Seward
jseward@acm.org
This program 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 2 of the
License, or (at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file LICENSE.
*/
#include "vg_constants.h"
/*------------------------------------------------------------*/
/*--- The normal-case dispatch machinery. ---*/
/*------------------------------------------------------------*/
/* To transfer to an (original) code address, load it into %eax and
jump to vg_dispatch. This fragment of code tries to find the
address of the corresponding translation by searching the translation
table. If it fails, a new translation is made, added to the
translation table, and then jumped to. Almost all the hard
work is done by C routines; this code simply handles the
common case fast -- when the translation address is found in
the translation cache.
At entry, %eax is the only live (real-machine) register; the
entire simulated state is tidily saved in vg_m_state.
*/
/* The C world needs a way to get started simulating. So we provide
a function void vg_run_innerloop ( void ), which starts running
from vg_m_eip, and exits when the counter reaches zero. This loop
can also exit if vg_oursignalhandler() catches a non-resumable
signal, for example SIGSEGV. It then longjmp()s back past here.
*/
.globl VG_(run_innerloop)
VG_(run_innerloop):
#OYNK(1000)
# ----- entry point to VG_(run_innerloop) -----
pushl %ebx
pushl %ecx
pushl %edx
pushl %esi
pushl %edi
pushl %ebp
# Set up the baseBlock pointer
movl $VG_(baseBlock), %ebp
# fetch m_eip into %eax
movl VGOFF_(m_eip), %esi
movl (%ebp, %esi, 4), %eax
# Start off dispatching paranoically, since we no longer have
# any indication whether or not this might be a special call/ret
# transfer.
jmp dispatch_stkadj
dispatch_main:
# Jump here to do a new dispatch.
# %eax holds destination (original) address.
# %ebp indicates further details of the control transfer
# requested to the address in %eax.
#
# If ebp == & VG_(baseBlock), just jump next to %eax.
#
# If ebp == VG_EBP_JMP_SYSCALL, do a system call before
# continuing at eax.
#
# If ebp == VG_EBP_JMP_CLIENTREQ, do a client request before
# continuing at eax.
#
# If %ebp has any other value, we panic.
cmpl $VG_(baseBlock), %ebp
jnz dispatch_exceptional
dispatch_boring:
# save the jump address at VG_(baseBlock)[VGOFF_(m_eip)],
movl VGOFF_(m_eip), %esi
movl %eax, (%ebp, %esi, 4)
# do a timeslice check.
# are we out of timeslice? If yes, defer to scheduler.
#OYNK(1001)
decl VG_(dispatch_ctr)
jz counter_is_zero
#OYNK(1002)
# try a fast lookup in the translation cache
movl %eax, %ebx
andl $VG_TT_FAST_MASK, %ebx
# ebx = tt_fast index
movl VG_(tt_fast)(,%ebx,4), %ebx
# ebx points at a tt entry
# now compare target with the tte.orig_addr field (+0)
cmpl %eax, (%ebx)
jnz fast_lookup_failed
# Found a match. Set the tte.mru_epoch field (+8)
# and call the tte.trans_addr field (+4)
movl VG_(current_epoch), %ecx
movl %ecx, 8(%ebx)
call *4(%ebx)
jmp dispatch_main
fast_lookup_failed:
# %EIP is up to date here since dispatch_boring dominates
movl $VG_TRC_INNER_FASTMISS, %eax
jmp run_innerloop_exit
counter_is_zero:
# %EIP is up to date here since dispatch_boring dominates
movl $VG_TRC_INNER_COUNTERZERO, %eax
jmp run_innerloop_exit
run_innerloop_exit:
popl %ebp
popl %edi
popl %esi
popl %edx
popl %ecx
popl %ebx
ret
/* Other ways of getting out of the inner loop. Placed out-of-line to
make it look cleaner.
*/
dispatch_exceptional:
# this is jumped to only, not fallen-through from above
cmpl $VG_TRC_EBP_JMP_STKADJ, %ebp
jz dispatch_stkadj
cmpl $VG_TRC_EBP_JMP_SYSCALL, %ebp
jz dispatch_syscall
cmpl $VG_TRC_EBP_JMP_CLIENTREQ, %ebp
jz dispatch_clientreq
# ebp has an invalid value ... crap out.
pushl $panic_msg_ebp
call VG_(panic)
# (never returns)
dispatch_syscall:
# save %eax in %EIP and defer to sched
movl $VG_(baseBlock), %ebp
movl VGOFF_(m_eip), %esi
movl %eax, (%ebp, %esi, 4)
movl $VG_TRC_EBP_JMP_SYSCALL, %eax
jmp run_innerloop_exit
dispatch_clientreq:
# save %eax in %EIP and defer to sched
movl $VG_(baseBlock), %ebp
movl VGOFF_(m_eip), %esi
movl %eax, (%ebp, %esi, 4)
movl $VG_TRC_EBP_JMP_CLIENTREQ, %eax
jmp run_innerloop_exit
dispatch_stkadj:
# save %eax in %EIP
movl $VG_(baseBlock), %ebp
movl VGOFF_(m_eip), %esi
movl %eax, (%ebp, %esi, 4)
# see if we need to mess with stack blocks
pushl %eax
call VG_(delete_client_stack_blocks_following_ESP_change)
popl %eax
movl $VG_(baseBlock), %ebp
# ok, its not interesting. Handle the normal way.
jmp dispatch_boring
.data
panic_msg_ebp:
.ascii "vg_dispatch: %ebp has invalid value!"
.byte 0
.text
##--------------------------------------------------------------------##
##--- end vg_dispatch.S ---##
##--------------------------------------------------------------------##
|