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