blob: 0cf5e877ba9d31b449706a1854a51d537e833372 [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/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
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
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
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)
sewardj68b2dd92002-05-10 21:03:56 +000057
58.section .data
59valgrind_already_initted:
60 .word 0
61
sewardjde4a1d02002-03-22 01:27:54 +000062.section .text
63
64
sewardj68b2dd92002-05-10 21:03:56 +000065.global VG_(startup)
sewardjde4a1d02002-03-22 01:27:54 +000066VG_(startup):
sewardj68b2dd92002-05-10 21:03:56 +000067 cmpl $0, valgrind_already_initted
68 je really_start_up
69 ret
70
71really_start_up:
72 movl $1, valgrind_already_initted
73
sewardjde4a1d02002-03-22 01:27:54 +000074 # Record %esp as it was when we got here. This is because argv/c
75 # and envp[] are passed as args to this function, and we need to see
76 # envp so we can get at the env var VG_ARGS without help from libc.
77 # The stack layout at this point depends on the version of glibc in
78 # use. See process_cmd_line_options() in vg_main.c for details.
79 movl %esp, VG_(esp_at_startup)
80
81 # We have control! Save the state of the machine in
82 # the simulators state, and switch stacks.
83 # Except ... we cant copy the machines registers into their
84 # final places in vg_baseBlock, because the offsets to them
85 # have not yet been set up. Instead, they are copied to a
86 # temporary place (m_state_static). In vg_main.c, once the
87 # baseBlock offsets are set up, values are copied into baseBlock.
sewardj92a59562002-09-30 00:53:10 +000088 movw %cs, VG_(m_state_static)+0
89 movw %ss, VG_(m_state_static)+4
90 movw %ds, VG_(m_state_static)+8
91 movw %es, VG_(m_state_static)+12
92 movw %fs, VG_(m_state_static)+16
93 movw %gs, VG_(m_state_static)+20
94 movl %eax, VG_(m_state_static)+24
95 movl %ecx, VG_(m_state_static)+28
96 movl %edx, VG_(m_state_static)+32
97 movl %ebx, VG_(m_state_static)+36
98 movl %esp, VG_(m_state_static)+40
99 movl %ebp, VG_(m_state_static)+44
100 movl %esi, VG_(m_state_static)+48
101 movl %edi, VG_(m_state_static)+52
sewardjde4a1d02002-03-22 01:27:54 +0000102 pushfl
103 popl %eax
sewardj92a59562002-09-30 00:53:10 +0000104 movl %eax, VG_(m_state_static)+56
sewardjde4a1d02002-03-22 01:27:54 +0000105 fwait
sewardj92a59562002-09-30 00:53:10 +0000106 fnsave VG_(m_state_static)+64
107 frstor VG_(m_state_static)+64
108
sewardjde4a1d02002-03-22 01:27:54 +0000109 # keep the first and last 10 words free to check for overruns
110 movl $VG_(stack)+39996 -40, %esp
111
112 # Now some real magic. We need this procedure to return,
113 # since thats what ld.so expects, but running on the
114 # simulator. So vg_main starts the simulator running at
115 # the insn labelled first_insn_to_simulate.
116
sewardj92a59562002-09-30 00:53:10 +0000117 movl $first_insn_to_simulate, VG_(m_state_static)+60
sewardjde4a1d02002-03-22 01:27:54 +0000118 jmp VG_(main)
119first_insn_to_simulate:
120 # Nothing else to do -- just return in the "normal" way.
121 ret
122
123
124
sewardjde4a1d02002-03-22 01:27:54 +0000125VG_(shutdown):
sewardj7e87e382002-05-03 19:09:05 +0000126 # Just return, and ignore any attempt by ld.so to call
127 # valgrind.sos exit function. We just run the client all
128 # the way to the final exit() syscall. This sidesteps
129 # problems caused by ld.so calling the finalisation code
130 # of other .sos *after* it shuts down valgrind, which
131 # was causing big problems with threads.
sewardjde4a1d02002-03-22 01:27:54 +0000132 ret
sewardj7e87e382002-05-03 19:09:05 +0000133
134
sewardj54cacf02002-04-12 23:24:59 +0000135
sewardjde4a1d02002-03-22 01:27:54 +0000136.global VG_(switch_to_real_CPU)
137VG_(switch_to_real_CPU):
sewardj7e87e382002-05-03 19:09:05 +0000138 # Once Valgrind has decided it needs to exit,
sewardjde4a1d02002-03-22 01:27:54 +0000139 # because the specified number of insns have been completed
140 # during a debugging run, it jumps here, which copies the
141 # simulators state into the real machine state. Execution
142 # of the rest of the program continues on the real CPU,
143 # and there is no way for the simulator to regain control
144 # after this point.
sewardj92a59562002-09-30 00:53:10 +0000145 frstor VG_(m_state_static)+64
146 movl VG_(m_state_static)+56, %eax
sewardjde4a1d02002-03-22 01:27:54 +0000147 pushl %eax
148 popfl
sewardj92a59562002-09-30 00:53:10 +0000149 movw VG_(m_state_static)+0, %cs
150 movw VG_(m_state_static)+4, %ss
151 movw VG_(m_state_static)+8, %ds
152 movw VG_(m_state_static)+12, %es
153 movw VG_(m_state_static)+16, %fs
154 movw VG_(m_state_static)+20, %gs
155 movl VG_(m_state_static)+24, %eax
156 movl VG_(m_state_static)+28, %ecx
157 movl VG_(m_state_static)+32, %edx
158 movl VG_(m_state_static)+36, %ebx
159 movl VG_(m_state_static)+40, %esp
160 movl VG_(m_state_static)+44, %ebp
161 movl VG_(m_state_static)+48, %esi
162 movl VG_(m_state_static)+52, %edi
sewardjde4a1d02002-03-22 01:27:54 +0000163
164 pushal
165 pushfl
166 # We hope that vg_sigshutdown_actions does not alter
167 # the FPU state.
168 call VG_(sigshutdown_actions)
169 popfl
170 popal
171 # re-restore the FPU state anyway ...
sewardj92a59562002-09-30 00:53:10 +0000172 frstor VG_(m_state_static)+64
173 jmp *VG_(m_state_static)+60
sewardjde4a1d02002-03-22 01:27:54 +0000174
175
176
177/*------------------------------------------------------------*/
178/*--- A function to temporarily copy %ESP/%EBP into ---*/
179/*--- %esp/%ebp and then start up GDB. ---*/
180/*------------------------------------------------------------*/
181
sewardj35805422002-04-21 13:05:34 +0000182/*
183extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
184 Addr m_esp_at_error,
185 Addr m_ebp_at_error );
186*/
187
sewardjde4a1d02002-03-22 01:27:54 +0000188/*--- This is clearly not re-entrant! ---*/
189.data
190vg_ebp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000191 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000192vg_esp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000193 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000194.text
195
196.global VG_(swizzle_esp_then_start_GDB)
197VG_(swizzle_esp_then_start_GDB):
198 pushal
199
200 # remember the simulators current stack/frame pointers
201 movl %ebp, vg_ebp_saved_over_GDB_start
202 movl %esp, vg_esp_saved_over_GDB_start
sewardjde4a1d02002-03-22 01:27:54 +0000203
sewardj35805422002-04-21 13:05:34 +0000204 # get args into regs
205 movl 44(%esp), %eax # client %EBP
206 movl 40(%esp), %ebx # client %ESP
207 movl 36(%esp), %ecx # client %EIP
208
sewardj783f0f52002-04-21 20:26:06 +0000209 # Now that we dont need to refer to simulators stack any more,
sewardj35805422002-04-21 13:05:34 +0000210 # put %ESP into %esp
211 movl %ebx, %esp
sewardjde4a1d02002-03-22 01:27:54 +0000212
213 ### %esp now refers to clients stack
214 ### mess with the clients stack to make it look as if it
215 ### called this procedure, since otherwise it will look to gdb
216 ### as if the top (currently executing) stack frame of the
217 ### client is missing.
218
sewardj35805422002-04-21 13:05:34 +0000219 # push %EIP. This is a faked-up return address.
220 pushl %ecx
sewardjde4a1d02002-03-22 01:27:54 +0000221
sewardj35805422002-04-21 13:05:34 +0000222 # push %EBP. This is a faked %ebp-chain pointer.
sewardjde4a1d02002-03-22 01:27:54 +0000223 pushl %eax
224
225 movl %esp, %ebp
226
227 call VG_(start_GDB_whilst_on_client_stack)
228
229 # restore the simulators stack/frame pointer
230 movl vg_ebp_saved_over_GDB_start, %ebp
231 movl vg_esp_saved_over_GDB_start, %esp
232
233 popal
234 ret
235
236# gcc puts this construction at the end of every function. I think it
237# allows the linker to figure out the size of the function. So we do
238# the same, in the vague hope that it might help GDBs navigation.
239.Lend_of_swizzle:
240 .size VG_(swizzle_esp_then_start_GDB), .Lend_of_swizzle-VG_(swizzle_esp_then_start_GDB)
241
sewardj54cacf02002-04-12 23:24:59 +0000242
sewardjde4a1d02002-03-22 01:27:54 +0000243##--------------------------------------------------------------------##
244##--- end vg_startup.S ---##
245##--------------------------------------------------------------------##