blob: 1a3b60fcb0f8c08855abfe7886ea433e924cd443 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2##--------------------------------------------------------------------##
3##--- Startup and shutdown code for Valgrind. ---##
4##--- vg_startup.S ---##
5##--------------------------------------------------------------------##
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_constants.h"
33
34
35#---------------------------------------------------------------------
36#
37# Startup and shutdown code for Valgrind. Particularly hairy.
38#
39# The dynamic linker, ld.so, will run the contents of the .init
40# section, once it has located, mmap-d and and linked the shared
41# libraries needed by the program. Valgrind is itself a shared
42# library. ld.so then runs code in the .init sections of each
43# library in turn, in order to give them a chance to initialise
44# themselves. We hijack this mechanism. Our startup routine
45# does return -- and execution continues -- except on the
46# synthetic CPU, not the real one. But ld.so, and the program
47# it is starting, cant tell the difference.
48#
49# The management apologise for the lack of apostrophes in these
50# comments. GNU as seems to object to them, for some reason.
51
52
53.section .init
54 call VG_(startup)
55.section .fini
56 call VG_(shutdown)
57.section .text
58
59
60
61VG_(startup):
62 # Record %esp as it was when we got here. This is because argv/c
63 # and envp[] are passed as args to this function, and we need to see
64 # envp so we can get at the env var VG_ARGS without help from libc.
65 # The stack layout at this point depends on the version of glibc in
66 # use. See process_cmd_line_options() in vg_main.c for details.
67 movl %esp, VG_(esp_at_startup)
68
69 # We have control! Save the state of the machine in
70 # the simulators state, and switch stacks.
71 # Except ... we cant copy the machines registers into their
72 # final places in vg_baseBlock, because the offsets to them
73 # have not yet been set up. Instead, they are copied to a
74 # temporary place (m_state_static). In vg_main.c, once the
75 # baseBlock offsets are set up, values are copied into baseBlock.
76 movl %eax, VG_(m_state_static)+0
77 movl %ecx, VG_(m_state_static)+4
78 movl %edx, VG_(m_state_static)+8
79 movl %ebx, VG_(m_state_static)+12
80 movl %esp, VG_(m_state_static)+16
81 movl %ebp, VG_(m_state_static)+20
82 movl %esi, VG_(m_state_static)+24
83 movl %edi, VG_(m_state_static)+28
84 pushfl
85 popl %eax
86 movl %eax, VG_(m_state_static)+32
87 fwait
88 fnsave VG_(m_state_static)+40
89 frstor VG_(m_state_static)+40
90
91 # keep the first and last 10 words free to check for overruns
92 movl $VG_(stack)+39996 -40, %esp
93
94 # Now some real magic. We need this procedure to return,
95 # since thats what ld.so expects, but running on the
96 # simulator. So vg_main starts the simulator running at
97 # the insn labelled first_insn_to_simulate.
98
99 movl $first_insn_to_simulate, VG_(m_state_static)+36
100 jmp VG_(main)
101first_insn_to_simulate:
102 # Nothing else to do -- just return in the "normal" way.
103 ret
104
105
106
107.global VG_(shutdown)
108VG_(shutdown):
109 # ld.so will call here after execution of the program proper
110 # is complete, to allow libraries to close down cleanly.
111 # Note that we will enter here on the synthetic CPU, not
112 # the real one! So the interpreter must notice when this
113 # procedure is called, and use that as its cue to switch
sewardj54cacf02002-04-12 23:24:59 +0000114 # back to the real CPU. As usual we have a client request
115 # to do this. To make sense of this you need to read the
116 # definition of VALGRIND_MAGIC_SEQUENCE in valgrind.h.
117 pushl %eax
118 pushl %edx
119 subl $20, %esp # allocate arg block
120 movl %esp, %eax # %eax == &_zzq_args[0]
121 movl $VG_USERREQ__SHUTDOWN_VALGRIND, 0(%eax) # request
122 # dont bother to fill in arg1 .. 4, not important
123 # and now the magic sequence itself:
124 roll $29, %eax
125 roll $3, %eax
126 rorl $27, %eax
127 rorl $5, %eax
128 roll $13, %eax
129 roll $19, %eax
130 # valgrind now exits. the following insns are
131 # executed on the real CPU.
132 addl $20, %esp
133 popl %edx
134 popl %eax
sewardjde4a1d02002-03-22 01:27:54 +0000135 ret
sewardj54cacf02002-04-12 23:24:59 +0000136
sewardjde4a1d02002-03-22 01:27:54 +0000137.global VG_(switch_to_real_CPU)
138VG_(switch_to_real_CPU):
139 # Once Valgrind has decided it needs to exit, either
140 # because it has detected a call to vg_shutdown, or
141 # because the specified number of insns have been completed
142 # during a debugging run, it jumps here, which copies the
143 # simulators state into the real machine state. Execution
144 # of the rest of the program continues on the real CPU,
145 # and there is no way for the simulator to regain control
146 # after this point.
147 frstor VG_(m_state_static)+40
148 movl VG_(m_state_static)+32, %eax
149 pushl %eax
150 popfl
151 movl VG_(m_state_static)+0, %eax
152 movl VG_(m_state_static)+4, %ecx
153 movl VG_(m_state_static)+8, %edx
154 movl VG_(m_state_static)+12, %ebx
155 movl VG_(m_state_static)+16, %esp
156 movl VG_(m_state_static)+20, %ebp
157 movl VG_(m_state_static)+24, %esi
158 movl VG_(m_state_static)+28, %edi
159
160 pushal
161 pushfl
162 # We hope that vg_sigshutdown_actions does not alter
163 # the FPU state.
164 call VG_(sigshutdown_actions)
165 popfl
166 popal
167 # re-restore the FPU state anyway ...
168 frstor VG_(m_state_static)+40
169 jmp *VG_(m_state_static)+36
170
171
172
173/*------------------------------------------------------------*/
174/*--- A function to temporarily copy %ESP/%EBP into ---*/
175/*--- %esp/%ebp and then start up GDB. ---*/
176/*------------------------------------------------------------*/
177
sewardj35805422002-04-21 13:05:34 +0000178/*
179extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
180 Addr m_esp_at_error,
181 Addr m_ebp_at_error );
182*/
183
sewardjde4a1d02002-03-22 01:27:54 +0000184/*--- This is clearly not re-entrant! ---*/
185.data
186vg_ebp_saved_over_GDB_start:
187 .word 0
188vg_esp_saved_over_GDB_start:
189 .word 0
190.text
191
192.global VG_(swizzle_esp_then_start_GDB)
193VG_(swizzle_esp_then_start_GDB):
194 pushal
195
196 # remember the simulators current stack/frame pointers
197 movl %ebp, vg_ebp_saved_over_GDB_start
198 movl %esp, vg_esp_saved_over_GDB_start
sewardjde4a1d02002-03-22 01:27:54 +0000199
sewardj35805422002-04-21 13:05:34 +0000200 # get args into regs
201 movl 44(%esp), %eax # client %EBP
202 movl 40(%esp), %ebx # client %ESP
203 movl 36(%esp), %ecx # client %EIP
204
205 # Now thatn we don't need to refer to simulators stack any more,
206 # put %ESP into %esp
207 movl %ebx, %esp
sewardjde4a1d02002-03-22 01:27:54 +0000208
209 ### %esp now refers to clients stack
210 ### mess with the clients stack to make it look as if it
211 ### called this procedure, since otherwise it will look to gdb
212 ### as if the top (currently executing) stack frame of the
213 ### client is missing.
214
sewardj35805422002-04-21 13:05:34 +0000215 # push %EIP. This is a faked-up return address.
216 pushl %ecx
sewardjde4a1d02002-03-22 01:27:54 +0000217
sewardj35805422002-04-21 13:05:34 +0000218 # push %EBP. This is a faked %ebp-chain pointer.
sewardjde4a1d02002-03-22 01:27:54 +0000219 pushl %eax
220
221 movl %esp, %ebp
222
223 call VG_(start_GDB_whilst_on_client_stack)
224
225 # restore the simulators stack/frame pointer
226 movl vg_ebp_saved_over_GDB_start, %ebp
227 movl vg_esp_saved_over_GDB_start, %esp
228
229 popal
230 ret
231
232# gcc puts this construction at the end of every function. I think it
233# allows the linker to figure out the size of the function. So we do
234# the same, in the vague hope that it might help GDBs navigation.
235.Lend_of_swizzle:
236 .size VG_(swizzle_esp_then_start_GDB), .Lend_of_swizzle-VG_(swizzle_esp_then_start_GDB)
237
sewardj54cacf02002-04-12 23:24:59 +0000238
sewardjde4a1d02002-03-22 01:27:54 +0000239##--------------------------------------------------------------------##
240##--- end vg_startup.S ---##
241##--------------------------------------------------------------------##