blob: a0bb4eab79497b70379b7361059e9661999b5d6f [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
sewardjde4a1d02002-03-22 01:27:54 +0000107VG_(shutdown):
sewardj7e87e382002-05-03 19:09:05 +0000108 # Just return, and ignore any attempt by ld.so to call
109 # valgrind.sos exit function. We just run the client all
110 # the way to the final exit() syscall. This sidesteps
111 # problems caused by ld.so calling the finalisation code
112 # of other .sos *after* it shuts down valgrind, which
113 # was causing big problems with threads.
sewardjde4a1d02002-03-22 01:27:54 +0000114 ret
sewardj7e87e382002-05-03 19:09:05 +0000115
116
sewardj54cacf02002-04-12 23:24:59 +0000117
sewardjde4a1d02002-03-22 01:27:54 +0000118.global VG_(switch_to_real_CPU)
119VG_(switch_to_real_CPU):
sewardj7e87e382002-05-03 19:09:05 +0000120 # Once Valgrind has decided it needs to exit,
sewardjde4a1d02002-03-22 01:27:54 +0000121 # because the specified number of insns have been completed
122 # during a debugging run, it jumps here, which copies the
123 # simulators state into the real machine state. Execution
124 # of the rest of the program continues on the real CPU,
125 # and there is no way for the simulator to regain control
126 # after this point.
127 frstor VG_(m_state_static)+40
128 movl VG_(m_state_static)+32, %eax
129 pushl %eax
130 popfl
131 movl VG_(m_state_static)+0, %eax
132 movl VG_(m_state_static)+4, %ecx
133 movl VG_(m_state_static)+8, %edx
134 movl VG_(m_state_static)+12, %ebx
135 movl VG_(m_state_static)+16, %esp
136 movl VG_(m_state_static)+20, %ebp
137 movl VG_(m_state_static)+24, %esi
138 movl VG_(m_state_static)+28, %edi
139
140 pushal
141 pushfl
142 # We hope that vg_sigshutdown_actions does not alter
143 # the FPU state.
144 call VG_(sigshutdown_actions)
145 popfl
146 popal
147 # re-restore the FPU state anyway ...
148 frstor VG_(m_state_static)+40
149 jmp *VG_(m_state_static)+36
150
151
152
153/*------------------------------------------------------------*/
154/*--- A function to temporarily copy %ESP/%EBP into ---*/
155/*--- %esp/%ebp and then start up GDB. ---*/
156/*------------------------------------------------------------*/
157
sewardj35805422002-04-21 13:05:34 +0000158/*
159extern void VG_(swizzle_esp_then_start_GDB) ( Addr m_eip_at_error,
160 Addr m_esp_at_error,
161 Addr m_ebp_at_error );
162*/
163
sewardjde4a1d02002-03-22 01:27:54 +0000164/*--- This is clearly not re-entrant! ---*/
165.data
166vg_ebp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000167 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000168vg_esp_saved_over_GDB_start:
sewardj783f0f52002-04-21 20:26:06 +0000169 .long 0
sewardjde4a1d02002-03-22 01:27:54 +0000170.text
171
172.global VG_(swizzle_esp_then_start_GDB)
173VG_(swizzle_esp_then_start_GDB):
174 pushal
175
176 # remember the simulators current stack/frame pointers
177 movl %ebp, vg_ebp_saved_over_GDB_start
178 movl %esp, vg_esp_saved_over_GDB_start
sewardjde4a1d02002-03-22 01:27:54 +0000179
sewardj35805422002-04-21 13:05:34 +0000180 # get args into regs
181 movl 44(%esp), %eax # client %EBP
182 movl 40(%esp), %ebx # client %ESP
183 movl 36(%esp), %ecx # client %EIP
184
sewardj783f0f52002-04-21 20:26:06 +0000185 # Now that we dont need to refer to simulators stack any more,
sewardj35805422002-04-21 13:05:34 +0000186 # put %ESP into %esp
187 movl %ebx, %esp
sewardjde4a1d02002-03-22 01:27:54 +0000188
189 ### %esp now refers to clients stack
190 ### mess with the clients stack to make it look as if it
191 ### called this procedure, since otherwise it will look to gdb
192 ### as if the top (currently executing) stack frame of the
193 ### client is missing.
194
sewardj35805422002-04-21 13:05:34 +0000195 # push %EIP. This is a faked-up return address.
196 pushl %ecx
sewardjde4a1d02002-03-22 01:27:54 +0000197
sewardj35805422002-04-21 13:05:34 +0000198 # push %EBP. This is a faked %ebp-chain pointer.
sewardjde4a1d02002-03-22 01:27:54 +0000199 pushl %eax
200
201 movl %esp, %ebp
202
203 call VG_(start_GDB_whilst_on_client_stack)
204
205 # restore the simulators stack/frame pointer
206 movl vg_ebp_saved_over_GDB_start, %ebp
207 movl vg_esp_saved_over_GDB_start, %esp
208
209 popal
210 ret
211
212# gcc puts this construction at the end of every function. I think it
213# allows the linker to figure out the size of the function. So we do
214# the same, in the vague hope that it might help GDBs navigation.
215.Lend_of_swizzle:
216 .size VG_(swizzle_esp_then_start_GDB), .Lend_of_swizzle-VG_(swizzle_esp_then_start_GDB)
217
sewardj54cacf02002-04-12 23:24:59 +0000218
sewardjde4a1d02002-03-22 01:27:54 +0000219##--------------------------------------------------------------------##
220##--- end vg_startup.S ---##
221##--------------------------------------------------------------------##