blob: d6c202ec92b7aec0018e46cf6442415f3632db90 [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
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.
88 movl %eax, VG_(m_state_static)+0
89 movl %ecx, VG_(m_state_static)+4
90 movl %edx, VG_(m_state_static)+8
91 movl %ebx, VG_(m_state_static)+12
92 movl %esp, VG_(m_state_static)+16
93 movl %ebp, VG_(m_state_static)+20
94 movl %esi, VG_(m_state_static)+24
95 movl %edi, VG_(m_state_static)+28
96 pushfl
97 popl %eax
98 movl %eax, VG_(m_state_static)+32
99 fwait
100 fnsave VG_(m_state_static)+40
101 frstor VG_(m_state_static)+40
102
103 # keep the first and last 10 words free to check for overruns
104 movl $VG_(stack)+39996 -40, %esp
105
106 # Now some real magic. We need this procedure to return,
107 # since thats what ld.so expects, but running on the
108 # simulator. So vg_main starts the simulator running at
109 # the insn labelled first_insn_to_simulate.
110
111 movl $first_insn_to_simulate, VG_(m_state_static)+36
112 jmp VG_(main)
113first_insn_to_simulate:
114 # Nothing else to do -- just return in the "normal" way.
115 ret
116
117
118
sewardjde4a1d02002-03-22 01:27:54 +0000119VG_(shutdown):
sewardj7e87e382002-05-03 19:09:05 +0000120 # Just return, and ignore any attempt by ld.so to call
121 # valgrind.sos exit function. We just run the client all
122 # the way to the final exit() syscall. This sidesteps
123 # problems caused by ld.so calling the finalisation code
124 # of other .sos *after* it shuts down valgrind, which
125 # was causing big problems with threads.
sewardjde4a1d02002-03-22 01:27:54 +0000126 ret
sewardj7e87e382002-05-03 19:09:05 +0000127
128
sewardj54cacf02002-04-12 23:24:59 +0000129
sewardjde4a1d02002-03-22 01:27:54 +0000130.global VG_(switch_to_real_CPU)
131VG_(switch_to_real_CPU):
sewardj7e87e382002-05-03 19:09:05 +0000132 # Once Valgrind has decided it needs to exit,
sewardjde4a1d02002-03-22 01:27:54 +0000133 # because the specified number of insns have been completed
134 # during a debugging run, it jumps here, which copies the
135 # simulators state into the real machine state. Execution
136 # of the rest of the program continues on the real CPU,
137 # and there is no way for the simulator to regain control
138 # after this point.
139 frstor VG_(m_state_static)+40
140 movl VG_(m_state_static)+32, %eax
141 pushl %eax
142 popfl
143 movl VG_(m_state_static)+0, %eax
144 movl VG_(m_state_static)+4, %ecx
145 movl VG_(m_state_static)+8, %edx
146 movl VG_(m_state_static)+12, %ebx
147 movl VG_(m_state_static)+16, %esp
148 movl VG_(m_state_static)+20, %ebp
149 movl VG_(m_state_static)+24, %esi
150 movl VG_(m_state_static)+28, %edi
151
152 pushal
153 pushfl
154 # We hope that vg_sigshutdown_actions does not alter
155 # the FPU state.
156 call VG_(sigshutdown_actions)
157 popfl
158 popal
159 # re-restore the FPU state anyway ...
160 frstor VG_(m_state_static)+40
161 jmp *VG_(m_state_static)+36
162
163
164
165/*------------------------------------------------------------*/
166/*--- A function to temporarily copy %ESP/%EBP into ---*/
167/*--- %esp/%ebp and then start up GDB. ---*/
168/*------------------------------------------------------------*/
169
sewardj35805422002-04-21 13:05:34 +0000170/*
171extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
172 Addr m_esp_at_error,
173 Addr m_ebp_at_error );
174*/
175
sewardjde4a1d02002-03-22 01:27:54 +0000176/*--- This is clearly not re-entrant! ---*/
177.data
178vg_ebp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000179 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000180vg_esp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000181 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000182.text
183
184.global VG_(swizzle_esp_then_start_GDB)
185VG_(swizzle_esp_then_start_GDB):
186 pushal
187
188 # remember the simulators current stack/frame pointers
189 movl %ebp, vg_ebp_saved_over_GDB_start
190 movl %esp, vg_esp_saved_over_GDB_start
sewardjde4a1d02002-03-22 01:27:54 +0000191
sewardj35805422002-04-21 13:05:34 +0000192 # get args into regs
193 movl 44(%esp), %eax # client %EBP
194 movl 40(%esp), %ebx # client %ESP
195 movl 36(%esp), %ecx # client %EIP
196
sewardj783f0f52002-04-21 20:26:06 +0000197 # Now that we dont need to refer to simulators stack any more,
sewardj35805422002-04-21 13:05:34 +0000198 # put %ESP into %esp
199 movl %ebx, %esp
sewardjde4a1d02002-03-22 01:27:54 +0000200
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
sewardj35805422002-04-21 13:05:34 +0000207 # push %EIP. This is a faked-up return address.
208 pushl %ecx
sewardjde4a1d02002-03-22 01:27:54 +0000209
sewardj35805422002-04-21 13:05:34 +0000210 # push %EBP. This is a faked %ebp-chain pointer.
sewardjde4a1d02002-03-22 01:27:54 +0000211 pushl %eax
212
213 movl %esp, %ebp
214
215 call VG_(start_GDB_whilst_on_client_stack)
216
217 # restore the simulators stack/frame pointer
218 movl vg_ebp_saved_over_GDB_start, %ebp
219 movl vg_esp_saved_over_GDB_start, %esp
220
221 popal
222 ret
223
224# gcc puts this construction at the end of every function. I think it
225# allows the linker to figure out the size of the function. So we do
226# the same, in the vague hope that it might help GDBs navigation.
227.Lend_of_swizzle:
228 .size VG_(swizzle_esp_then_start_GDB), .Lend_of_swizzle-VG_(swizzle_esp_then_start_GDB)
229
sewardj54cacf02002-04-12 23:24:59 +0000230
sewardjde4a1d02002-03-22 01:27:54 +0000231##--------------------------------------------------------------------##
232##--- end vg_startup.S ---##
233##--------------------------------------------------------------------##