blob: 72e7a79ef047fdc9b21b4038aeb190ad42e4fc38 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
39#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000040#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000041#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000042
43#include <dirent.h>
44#include <dlfcn.h>
45#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000046#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000047#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000048#include <string.h>
49#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000050#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000051#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000052#include <sys/wait.h>
53#include <unistd.h>
54
sewardjb5f6f512005-03-10 23:59:00 +000055#include "memcheck/memcheck.h"
56
thughes74b8de22004-04-22 18:12:31 +000057#ifndef AT_DCACHEBSIZE
58#define AT_DCACHEBSIZE 19
59#endif /* AT_DCACHEBSIZE */
60
61#ifndef AT_ICACHEBSIZE
62#define AT_ICACHEBSIZE 20
63#endif /* AT_ICACHEBSIZE */
64
65#ifndef AT_UCACHEBSIZE
66#define AT_UCACHEBSIZE 21
67#endif /* AT_UCACHEBSIZE */
68
nethercote71980f02004-01-24 18:18:54 +000069#ifndef AT_SYSINFO
70#define AT_SYSINFO 32
71#endif /* AT_SYSINFO */
72
73#ifndef AT_SYSINFO_EHDR
74#define AT_SYSINFO_EHDR 33
75#endif /* AT_SYSINFO_EHDR */
76
77#ifndef AT_SECURE
78#define AT_SECURE 23 /* secure mode boolean */
79#endif /* AT_SECURE */
80
nethercote71980f02004-01-24 18:18:54 +000081/* redzone gap between client address space and shadow */
82#define REDZONE_SIZE (1 * 1024*1024)
83
84/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000085#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000086
nethercotee2097312004-06-27 12:29:56 +000087/* Proportion of client space for its heap (rest is for mmaps + stack) */
88#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000089
njn14319cc2005-03-13 06:26:22 +000090/* Number of file descriptors that Valgrind tries to reserve for
91 it's own use - just a small constant. */
92#define N_RESERVED_FDS (10)
93
94/* Default debugger command. */
95#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
96
nethercote71980f02004-01-24 18:18:54 +000097/*====================================================================*/
98/*=== Global entities not referenced from generated code ===*/
99/*====================================================================*/
100
sewardjde4a1d02002-03-22 01:27:54 +0000101/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000102 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000103 ------------------------------------------------------------------ */
104
nethercote71980f02004-01-24 18:18:54 +0000105/* Client address space, lowest to highest (see top of ume.c) */
106Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000107Addr VG_(client_end);
108Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000109Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000110Addr VG_(clstk_base);
111Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000112
113Addr VG_(brk_base); /* start of brk */
114Addr VG_(brk_limit); /* current brk */
115
nethercote996901a2004-08-03 13:29:09 +0000116Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000117Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000118
119Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000120
nethercote820bd8c2004-09-07 23:04:49 +0000121// Note that VG_(valgrind_last) names the last byte of the section, whereas
122// the VG_(*_end) vars name the byte one past the end of the section.
123Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
nethercote73b526f2004-10-31 18:48:21 +0000125struct vki_rlimit VG_(client_rlimit_data);
126struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000127
fitzhardinge98abfc72003-12-16 02:05:15 +0000128/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000129static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000130
131/* client executable */
132Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000133
134/* Path to library directory */
135const Char *VG_(libdir) = VG_LIBDIR;
136
137/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000138static Int vg_argc;
139static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000140
sewardjb5f6f512005-03-10 23:59:00 +0000141/* The master thread the one which will be responsible for mopping
142 everything up at exit. Normally it is tid 1, since that's the
143 first thread created, but it may be something else after a
144 fork(). */
145ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000146
thughesad1c9562004-06-26 11:27:52 +0000147/* Application-visible file descriptor limits */
148Int VG_(fd_soft_limit) = -1;
149Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000150
nethercote4ad74312004-10-26 09:59:49 +0000151/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000152 envp[] as extracted from the client's stack at startup-time. */
153Int VG_(client_argc);
154Char** VG_(client_argv);
155Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000156
sewardj51ac0872004-12-21 01:20:49 +0000157
sewardjde4a1d02002-03-22 01:27:54 +0000158/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000159 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000160 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000161
sewardjde4a1d02002-03-22 01:27:54 +0000162/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000163ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000164
nethercote71980f02004-01-24 18:18:54 +0000165/* Tell the logging mechanism whether we are logging to a file
166 descriptor or a socket descriptor. */
167Bool VG_(logging_to_filedes) = True;
168
sewardj73cf3bc2002-11-03 03:20:15 +0000169
nethercote71980f02004-01-24 18:18:54 +0000170/*====================================================================*/
171/*=== Counters, for profiling purposes only ===*/
172/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000173
sewardjde4a1d02002-03-22 01:27:54 +0000174/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000175static UInt sanity_fast_count = 0;
176static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000177
nethercote3a42fb82004-08-03 18:08:50 +0000178static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000179{
nethercote3a42fb82004-08-03 18:08:50 +0000180 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000181 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000183 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000184
nethercote3a42fb82004-08-03 18:08:50 +0000185 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000186 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000187
nethercote71980f02004-01-24 18:18:54 +0000188 VG_(message)(Vg_DebugMsg,
189 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000190 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000191
njn9271cbc2005-03-13 05:38:25 +0000192 VG_(print_ExeContext_stats)();
193
nethercote3a42fb82004-08-03 18:08:50 +0000194 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000195 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000196 VG_(message)(Vg_DebugMsg, "");
197 VG_(message)(Vg_DebugMsg,
198 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000199 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000200 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000201 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000202 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000203 }
nethercote71980f02004-01-24 18:18:54 +0000204}
205
206
207/*====================================================================*/
208/*=== Miscellaneous global functions ===*/
209/*====================================================================*/
210
nethercotecf97ffb2004-09-09 13:40:31 +0000211static Int ptrace_setregs(Int pid, ThreadId tid)
212{
sewardj2a99cf62004-11-24 10:44:19 +0000213 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000214}
215
nethercote04d0fbc2004-01-26 16:48:06 +0000216/* Start debugger and get it to attach to this process. Called if the
217 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000218 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000219 meaningfully get the debugger to continue the program, though; to
220 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000221void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000222{
223 Int pid;
224
225 if ((pid = fork()) == 0) {
226 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000227 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000228
229 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000230 Int status;
231 Int res;
232
nethercote71980f02004-01-24 18:18:54 +0000233 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
234 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000235 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000236 kill(pid, SIGSTOP) == 0 &&
237 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000238 Char pidbuf[15];
239 Char file[30];
240 Char buf[100];
241 Char *bufptr;
242 Char *cmdptr;
243
244 VG_(sprintf)(pidbuf, "%d", pid);
245 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
246
247 bufptr = buf;
248 cmdptr = VG_(clo_db_command);
249
250 while (*cmdptr) {
251 switch (*cmdptr) {
252 case '%':
253 switch (*++cmdptr) {
254 case 'f':
255 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
256 bufptr += VG_(strlen)(file);
257 cmdptr++;
258 break;
259 case 'p':
260 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
261 bufptr += VG_(strlen)(pidbuf);
262 cmdptr++;
263 break;
264 default:
265 *bufptr++ = *cmdptr++;
266 break;
267 }
268 break;
269 default:
270 *bufptr++ = *cmdptr++;
271 break;
272 }
273 }
274
275 *bufptr++ = '\0';
276
277 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000278 res = VG_(system)(buf);
279 if (res == 0) {
280 VG_(message)(Vg_UserMsg, "");
281 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000282 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000283 } else {
284 VG_(message)(Vg_UserMsg, "Apparently failed!");
285 VG_(message)(Vg_UserMsg, "");
286 }
287 }
288
nethercote73b526f2004-10-31 18:48:21 +0000289 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000290 VG_(waitpid)(pid, &status, 0);
291 }
292}
293
294
295/* Print some helpful-ish text about unimplemented things, and give
296 up. */
297void VG_(unimplemented) ( Char* msg )
298{
299 VG_(message)(Vg_UserMsg, "");
300 VG_(message)(Vg_UserMsg,
301 "Valgrind detected that your program requires");
302 VG_(message)(Vg_UserMsg,
303 "the following unimplemented functionality:");
304 VG_(message)(Vg_UserMsg, " %s", msg);
305 VG_(message)(Vg_UserMsg,
306 "This may be because the functionality is hard to implement,");
307 VG_(message)(Vg_UserMsg,
308 "or because no reasonable program would behave this way,");
309 VG_(message)(Vg_UserMsg,
310 "or because nobody has yet needed it. In any case, let us know at");
311 VG_(message)(Vg_UserMsg,
312 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
313 VG_(message)(Vg_UserMsg,
314 "");
315 VG_(message)(Vg_UserMsg,
316 "Valgrind has to exit now. Sorry. Bye!");
317 VG_(message)(Vg_UserMsg,
318 "");
319 VG_(pp_sched_status)();
320 VG_(exit)(1);
321}
322
sewardj2a99cf62004-11-24 10:44:19 +0000323/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000324Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000325{
njncf45fd42004-11-24 16:30:22 +0000326 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000327}
328
njn67516132005-03-22 04:02:43 +0000329Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000330{
331 return INSTR_PTR( VG_(threads)[tid].arch );
332}
333
njnea4b28c2004-11-30 16:04:58 +0000334
nethercote71980f02004-01-24 18:18:54 +0000335/*====================================================================*/
336/*=== Check we were launched by stage 1 ===*/
337/*====================================================================*/
338
339/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000340static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000341{
nethercoteebf1d862004-11-01 18:22:05 +0000342 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000343 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000344
345 for (; auxv->a_type != AT_NULL; auxv++)
346 switch(auxv->a_type) {
347 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000348 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000349 found |= 1;
350 break;
351
352 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000353 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000354 found |= 2;
355 break;
nethercote7f390022004-10-25 17:18:24 +0000356
357 case AT_PHDR:
358 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
359 break;
nethercote71980f02004-01-24 18:18:54 +0000360 }
361
nethercote361a14e2004-07-26 11:11:56 +0000362 if ( found != (1|2) ) {
363 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000364 exit(127);
365 }
nethercote31779c72004-07-30 21:50:15 +0000366 vg_assert(padfile >= 0);
367 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000368}
369
370
371/*====================================================================*/
372/*=== Address space determination ===*/
373/*====================================================================*/
374
nethercote7f390022004-10-25 17:18:24 +0000375extern char _start[];
376
nethercote31779c72004-07-30 21:50:15 +0000377static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000378{
nethercotea3c3cf22004-11-01 18:38:00 +0000379 Int ires;
380 void* vres;
381 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000382
nethercote7f390022004-10-25 17:18:24 +0000383 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
384 // this is a workable approximation
385 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000386 VG_(valgrind_base) = PGROUNDDN(&_start);
387 }
388
nethercote820bd8c2004-09-07 23:04:49 +0000389 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000390
nethercote31779c72004-07-30 21:50:15 +0000391 // This gives the client the largest possible address space while
392 // taking into account the tool's shadow needs.
393 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000394 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000395 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000396 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000397 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000398 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000399 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000400
nethercote31779c72004-07-30 21:50:15 +0000401 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000402 VG_(shadow_end) = VG_(valgrind_base);
403 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000404
nethercotee2097312004-06-27 12:29:56 +0000405#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
406
nethercote71980f02004-01-24 18:18:54 +0000407 if (0)
nethercotee2097312004-06-27 12:29:56 +0000408 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000409 "client_base %p (%dMB)\n"
410 "client_mapbase %p (%dMB)\n"
411 "client_end %p (%dMB)\n"
412 "shadow_base %p (%dMB)\n"
413 "shadow_end %p\n"
414 "valgrind_base %p (%dMB)\n"
415 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000416 VG_(client_base), SEGSIZE(client_base, client_mapbase),
417 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
418 VG_(client_end), SEGSIZE(client_end, shadow_base),
419 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000420 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000421 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
422 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000423 );
424
425#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000426
427 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000428 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000429 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000430 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000431
432 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000433 ires = munmap((void*)VG_(client_base), client_size);
434 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000435
436 // Map shadow memory.
437 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000438 if (shadow_size != 0) {
439 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000440 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000441 if ((void*)-1 == vres) {
442 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000443 "valgrind: Could not allocate address space (%p bytes)\n"
444 "valgrind: for shadow memory\n"
445 "valgrind: Possible causes:\n"
446 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
447 "valgrind: needs at least 1.5GB swap space.\n"
448 "valgrind: - Or, your virtual memory size may be limited (check\n"
449 "valgrind: with 'ulimit -v').\n"
450 "valgrind: - Or, your system may use a kernel that provides only a\n"
451 "valgrind: too-small (eg. 2GB) user address space.\n"
452 , (void*)shadow_size
453 );
nethercoted4722622004-08-30 19:36:42 +0000454 exit(1);
455 }
nethercotee567e702004-07-10 17:49:17 +0000456 }
nethercote71980f02004-01-24 18:18:54 +0000457}
458
459/*====================================================================*/
460/*=== Command line setup ===*/
461/*====================================================================*/
462
463/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
464static char* get_file_clo(char* dir)
465{
466# define FLEN 512
467 Int fd, n;
468 struct stat s1;
469 char* f_clo = NULL;
470 char filename[FLEN];
471
472 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
473 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
474 if ( fd > 0 ) {
475 if ( 0 == fstat(fd, &s1) ) {
476 f_clo = malloc(s1.st_size+1);
477 vg_assert(f_clo);
478 n = read(fd, f_clo, s1.st_size);
479 if (n == -1) n = 0;
480 f_clo[n] = '\0';
481 }
482 close(fd);
483 }
484 return f_clo;
485# undef FLEN
486}
487
488static Int count_args(char* s)
489{
490 Int n = 0;
491 if (s) {
492 char* cp = s;
493 while (True) {
494 // We have alternating sequences: blanks, non-blanks, blanks...
495 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000496 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000497 if ( !*cp ) break;
498 n++;
njn0c0f32a2005-03-26 04:14:01 +0000499 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000500 }
501 }
502 return n;
503}
504
505/* add args out of environment, skipping multiple spaces and -- args */
506static char** copy_args( char* s, char** to )
507{
508 if (s) {
509 char* cp = s;
510 while (True) {
511 // We have alternating sequences: blanks, non-blanks, blanks...
512 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000513 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000514 if ( !*cp ) break;
515 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000516 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000517 if ( *cp ) *cp++ = '\0'; // terminate if necessary
518 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
519 }
520 }
521 return to;
522}
523
524// Augment command line with arguments from environment and .valgrindrc
525// files.
526static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
527{
nethercotef6a1d502004-08-09 12:21:57 +0000528 int vg_argc0 = *vg_argc_inout;
529 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000530
531 char* env_clo = getenv(VALGRINDOPTS);
532 char* f1_clo = get_file_clo( getenv("HOME") );
533 char* f2_clo = get_file_clo(".");
534
535 /* copy any extra args from file or environment, if present */
536 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
537 /* ' ' separated extra options */
538 char **from;
539 char **to;
thughescaca0022004-09-13 10:20:34 +0000540 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
541
542 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
543
nethercote71980f02004-01-24 18:18:54 +0000544 env_arg_count = count_args(env_clo);
545 f1_arg_count = count_args(f1_clo);
546 f2_arg_count = count_args(f2_clo);
547
548 if (0)
549 printf("extra-argc=%d %d %d\n",
550 env_arg_count, f1_arg_count, f2_arg_count);
551
552 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000553 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000554 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000555 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000556 vg_assert(vg_argv0);
557 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000558
559 /* copy argv[0] */
560 *to++ = *from++;
561
562 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
563 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
564 * to override less local ones. */
565 to = copy_args(f1_clo, to);
566 to = copy_args(env_clo, to);
567 to = copy_args(f2_clo, to);
568
569 /* copy original arguments, stopping at command or -- */
570 while (*from) {
571 if (**from != '-')
572 break;
573 if (VG_STREQ(*from, "--")) {
574 from++; /* skip -- */
575 break;
576 }
577 *to++ = *from++;
578 }
579
580 /* add -- */
581 *to++ = "--";
582
nethercotef6a1d502004-08-09 12:21:57 +0000583 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000584
585 /* copy rest of original command line, then NULL */
586 while (*from) *to++ = *from++;
587 *to = NULL;
588 }
589
nethercotef6a1d502004-08-09 12:21:57 +0000590 *vg_argc_inout = vg_argc0;
591 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000592}
593
nethercotef6a1d502004-08-09 12:21:57 +0000594#define VG_CLO_SEP '\01'
595
nethercote71980f02004-01-24 18:18:54 +0000596static void get_command_line( int argc, char** argv,
597 Int* vg_argc_out, Char*** vg_argv_out,
598 char*** cl_argv_out )
599{
nethercotef6a1d502004-08-09 12:21:57 +0000600 int vg_argc0;
601 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000602 char** cl_argv;
603 char* env_clo = getenv(VALGRINDCLO);
604
605 if (env_clo != NULL && *env_clo != '\0') {
606 char *cp;
607 char **cpp;
608
nethercotef6a1d502004-08-09 12:21:57 +0000609 /* OK, VALGRINDCLO is set, which means we must be a child of another
610 Valgrind process using --trace-children, so we're getting all our
611 arguments from VALGRINDCLO, and the entire command line belongs to
612 the client (including argv[0]) */
613 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000614 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000615 if (*cp == VG_CLO_SEP)
616 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000617
nethercotef6a1d502004-08-09 12:21:57 +0000618 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
619 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000620
nethercotef6a1d502004-08-09 12:21:57 +0000621 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000622
623 *cpp++ = "valgrind"; /* nominal argv[0] */
624 *cpp++ = env_clo;
625
nethercotef6a1d502004-08-09 12:21:57 +0000626 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000627 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000628 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000629 *cp++ = '\0'; /* chop it up in place */
630 *cpp++ = cp;
631 }
632 }
633 *cpp = NULL;
634 cl_argv = argv;
635
636 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000637 Bool noaugment = False;
638
nethercote71980f02004-01-24 18:18:54 +0000639 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000640 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000641
nethercotef6a1d502004-08-09 12:21:57 +0000642 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000643 Char* arg = argv[vg_argc0];
644 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000645 break;
sewardjb5f6f512005-03-10 23:59:00 +0000646 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000647 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000648 break;
649 }
njn45270a22005-03-27 01:00:11 +0000650 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000651 }
nethercotef6a1d502004-08-09 12:21:57 +0000652 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000653
654 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000655 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000656 those extra args will already be present in VALGRINDCLO.
657 (We also don't do it when --command-line-only=yes.) */
658 if (!noaugment)
659 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000660 }
661
662 if (0) {
663 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000664 for (i = 0; i < vg_argc0; i++)
665 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000666 }
667
nethercotef6a1d502004-08-09 12:21:57 +0000668 *vg_argc_out = vg_argc0;
669 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000670 *cl_argv_out = cl_argv;
671}
672
673
674/*====================================================================*/
675/*=== Environment and stack setup ===*/
676/*====================================================================*/
677
678/* Scan a colon-separated list, and call a function on each element.
679 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000680 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000681 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000682
683 This routine will return True if (*func) returns True and False if
684 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000685*/
thughes4ad52d02004-06-27 17:37:21 +0000686static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000687{
688 char *cp, *entry;
689 int end;
690
691 if (colsep == NULL ||
692 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000693 return False;
nethercote71980f02004-01-24 18:18:54 +0000694
695 entry = cp = colsep;
696
697 do {
698 end = (*cp == '\0');
699
700 if (*cp == ':' || *cp == '\0') {
701 char save = *cp;
702
703 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000704 if ((*func)(entry)) {
705 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000706 return True;
thughes21942d92004-07-12 09:35:37 +0000707 }
nethercote71980f02004-01-24 18:18:54 +0000708 *cp = save;
709 entry = cp+1;
710 }
711 cp++;
712 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000713
714 return False;
715}
716
nethercote71980f02004-01-24 18:18:54 +0000717/* Prepare the client's environment. This is basically a copy of our
718 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000719 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000720
sewardjb5f6f512005-03-10 23:59:00 +0000721 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000722
723 Yummy. String hacking in C.
724
725 If this needs to handle any more variables it should be hacked
726 into something table driven.
727 */
728static char **fix_environment(char **origenv, const char *preload)
729{
730 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000731 static const char ld_preload[] = "LD_PRELOAD=";
732 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000733 static const int ld_preload_len = sizeof(ld_preload)-1;
734 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
735 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000736 char *inject_path;
737 int inject_path_len;
738 int vgliblen = strlen(VG_(libdir));
739 char **cpp;
740 char **ret;
741 int envc;
742 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
743
744 /* Find the vg_inject.so; also make room for the tool preload
745 library */
746 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
747 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000748 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000749
750 if (preload)
751 snprintf(inject_path, inject_path_len, "%s/%s:%s",
752 VG_(libdir), inject_so, preload);
753 else
754 snprintf(inject_path, inject_path_len, "%s/%s",
755 VG_(libdir), inject_so);
756
757 /* Count the original size of the env */
758 envc = 0; /* trailing NULL */
759 for (cpp = origenv; cpp && *cpp; cpp++)
760 envc++;
761
762 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000763 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000764 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000765
766 /* copy it over */
767 for (cpp = ret; *origenv; )
768 *cpp++ = *origenv++;
769 *cpp = NULL;
770
771 vg_assert(envc == (cpp - ret));
772
773 /* Walk over the new environment, mashing as we go */
774 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000775 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000776 int len = strlen(*cpp) + inject_path_len;
777 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000778 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000779
780 snprintf(cp, len, "%s%s:%s",
781 ld_preload, inject_path, (*cpp)+ld_preload_len);
782
783 *cpp = cp;
784
785 ld_preload_done = 1;
786 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
787 *cpp = "";
788 }
789 }
790
791 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000792 if (!ld_preload_done) {
793 int len = ld_preload_len + inject_path_len;
794 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000795 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000796
797 snprintf(cp, len, "%s%s",
798 ld_preload, inject_path);
799
800 ret[envc++] = cp;
801 }
802
sewardjb5f6f512005-03-10 23:59:00 +0000803 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000804 ret[envc] = NULL;
805
806 return ret;
807}
808
809extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000810
811/* Add a string onto the string table, and return its address */
812static char *copy_str(char **tab, const char *str)
813{
814 char *cp = *tab;
815 char *orig = cp;
816
817 while(*str)
818 *cp++ = *str++;
819 *cp++ = '\0';
820
821 if (0)
nethercote545fe672004-11-01 16:52:43 +0000822 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000823
824 *tab = cp;
825
826 return orig;
827}
828
829/*
830 This sets up the client's initial stack, containing the args,
831 environment and aux vector.
832
833 The format of the stack is:
834
835 higher address +-----------------+
836 | Trampoline code |
837 +-----------------+
838 | |
839 : string table :
840 | |
841 +-----------------+
842 | AT_NULL |
843 - -
844 | auxv |
845 +-----------------+
846 | NULL |
847 - -
848 | envp |
849 +-----------------+
850 | NULL |
851 - -
852 | argv |
853 +-----------------+
854 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000855 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000856 | undefined |
857 : :
858 */
nethercotec25c4492004-10-18 11:52:17 +0000859static Addr setup_client_stack(void* init_sp,
860 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000861 const struct exeinfo *info,
862 UInt** client_auxv)
863{
nethercotee567e702004-07-10 17:49:17 +0000864 void* res;
nethercote71980f02004-01-24 18:18:54 +0000865 char **cpp;
866 char *strtab; /* string table */
867 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000868 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000869 struct ume_auxv *auxv;
870 const struct ume_auxv *orig_auxv;
871 const struct ume_auxv *cauxv;
872 unsigned stringsize; /* total size of strings in bytes */
873 unsigned auxsize; /* total size of auxv in bytes */
874 int argc; /* total argc */
875 int envc; /* total number of env vars */
876 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000877 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000878
879 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000880 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000881
882 /* ==================== compute sizes ==================== */
883
884 /* first of all, work out how big the client stack will be */
885 stringsize = 0;
886
887 /* paste on the extra args if the loader needs them (ie, the #!
888 interpreter and its argument) */
889 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000890 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000891 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000892 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000893 }
nethercoted6a56872004-07-26 15:32:47 +0000894 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000895 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000896 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000897 }
898
899 /* now scan the args we're given... */
900 for (cpp = orig_argv; *cpp; cpp++) {
901 argc++;
902 stringsize += strlen(*cpp) + 1;
903 }
904
905 /* ...and the environment */
906 envc = 0;
907 for (cpp = orig_envp; cpp && *cpp; cpp++) {
908 envc++;
909 stringsize += strlen(*cpp) + 1;
910 }
911
912 /* now, how big is the auxv? */
913 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
914 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
915 if (cauxv->a_type == AT_PLATFORM)
916 stringsize += strlen(cauxv->u.a_ptr) + 1;
917 auxsize += sizeof(*cauxv);
918 }
919
920 /* OK, now we know how big the client stack is */
921 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000922 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000923 sizeof(char **)*argc + /* argv */
924 sizeof(char **) + /* terminal NULL */
925 sizeof(char **)*envc + /* envp */
926 sizeof(char **) + /* terminal NULL */
927 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000928 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000929 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000930
sewardj79048ce2005-02-18 08:28:32 +0000931 if (0) VG_(printf)("stacksize = %d\n", stacksize);
932
nethercotef84f6952004-07-15 14:58:33 +0000933 // decide where stack goes!
934 VG_(clstk_end) = VG_(client_end);
935
nethercote73b526f2004-10-31 18:48:21 +0000936 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000937
nethercote71980f02004-01-24 18:18:54 +0000938 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000939 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000940 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
941
nethercote71980f02004-01-24 18:18:54 +0000942 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000943 stringbase = strtab = (char *)(VG_(client_trampoline_code)
944 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000945
946 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000947
sewardj79048ce2005-02-18 08:28:32 +0000948 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000949 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000950 "clstk_base %p\n"
951 "clstk_end %p\n",
952 stringsize, auxsize, stacksize,
953 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000954
nethercote71980f02004-01-24 18:18:54 +0000955 /* ==================== allocate space ==================== */
956
957 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000958 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000959 PROT_READ | PROT_WRITE | PROT_EXEC,
960 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
961 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000962
963 /* ==================== copy client stack ==================== */
964
nethercotea3c3cf22004-11-01 18:38:00 +0000965 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000966
967 /* --- argc --- */
968 *ptr++ = argc; /* client argc */
969
970 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000971 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000972 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000973 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000974 }
nethercoted6a56872004-07-26 15:32:47 +0000975 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000976 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000977 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000978 }
979 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000980 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000981 }
982 *ptr++ = 0;
983
984 /* --- envp --- */
985 VG_(client_envp) = (Char **)ptr;
986 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000987 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000988 *ptr++ = 0;
989
990 /* --- auxv --- */
991 auxv = (struct ume_auxv *)ptr;
992 *client_auxv = (UInt *)auxv;
993
994 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
995 /* copy the entry... */
996 *auxv = *orig_auxv;
997
998 /* ...and fix up the copy */
999 switch(auxv->a_type) {
1000 case AT_PHDR:
1001 if (info->phdr == 0)
1002 auxv->a_type = AT_IGNORE;
1003 else
1004 auxv->u.a_val = info->phdr;
1005 break;
1006
1007 case AT_PHNUM:
1008 if (info->phdr == 0)
1009 auxv->a_type = AT_IGNORE;
1010 else
1011 auxv->u.a_val = info->phnum;
1012 break;
1013
1014 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001015 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001016 break;
1017
1018 case AT_PLATFORM: /* points to a platform description string */
1019 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1020 break;
1021
1022 case AT_ENTRY:
1023 auxv->u.a_val = info->entry;
1024 break;
1025
1026 case AT_IGNORE:
1027 case AT_EXECFD:
1028 case AT_PHENT:
1029 case AT_PAGESZ:
1030 case AT_FLAGS:
1031 case AT_NOTELF:
1032 case AT_UID:
1033 case AT_EUID:
1034 case AT_GID:
1035 case AT_EGID:
1036 case AT_CLKTCK:
1037 case AT_HWCAP:
1038 case AT_FPUCW:
1039 case AT_DCACHEBSIZE:
1040 case AT_ICACHEBSIZE:
1041 case AT_UCACHEBSIZE:
1042 /* All these are pointerless, so we don't need to do anything
1043 about them. */
1044 break;
1045
1046 case AT_SECURE:
1047 /* If this is 1, then it means that this program is running
1048 suid, and therefore the dynamic linker should be careful
1049 about LD_PRELOAD, etc. However, since stage1 (the thing
1050 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001051 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001052 set AT_SECURE to 0. */
1053 auxv->u.a_val = 0;
1054 break;
1055
1056 case AT_SYSINFO:
1057 /* Leave this unmolested for now, but we'll update it later
1058 when we set up the client trampoline code page */
1059 break;
1060
1061 case AT_SYSINFO_EHDR:
1062 /* Trash this, because we don't reproduce it */
1063 auxv->a_type = AT_IGNORE;
1064 break;
1065
1066 default:
1067 /* stomp out anything we don't know about */
1068 if (0)
nethercote545fe672004-11-01 16:52:43 +00001069 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001070 auxv->a_type = AT_IGNORE;
1071 break;
1072
1073 }
1074 }
1075 *auxv = *orig_auxv;
1076 vg_assert(auxv->a_type == AT_NULL);
1077
njnc6168192004-11-29 13:54:10 +00001078// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1079// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001080#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001081 /* --- trampoline page --- */
1082 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1083 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001084#endif
nethercotef84f6952004-07-15 14:58:33 +00001085
nethercote71980f02004-01-24 18:18:54 +00001086 vg_assert((strtab-stringbase) == stringsize);
1087
nethercote5ee67ca2004-06-22 14:00:09 +00001088 /* We know the initial ESP is pointing at argc/argv */
1089 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001090 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001091
sewardj79048ce2005-02-18 08:28:32 +00001092 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001093 return cl_esp;
1094}
1095
1096/*====================================================================*/
1097/*=== Find executable ===*/
1098/*====================================================================*/
1099
thughes4ad52d02004-06-27 17:37:21 +00001100static const char* executable_name;
1101
1102static Bool match_executable(const char *entry) {
1103 char buf[strlen(entry) + strlen(executable_name) + 2];
1104
1105 /* empty PATH element means . */
1106 if (*entry == '\0')
1107 entry = ".";
1108
1109 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1110
1111 if (access(buf, R_OK|X_OK) == 0) {
1112 executable_name = strdup(buf);
1113 vg_assert(NULL != executable_name);
1114 return True;
1115 }
1116 return False;
1117}
1118
nethercote71980f02004-01-24 18:18:54 +00001119static const char* find_executable(const char* exec)
1120{
1121 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001122 executable_name = exec;
1123 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001124 /* no '/' - we need to search the path */
1125 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001126 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001127 }
thughes4ad52d02004-06-27 17:37:21 +00001128 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001129}
1130
1131
1132/*====================================================================*/
1133/*=== Loading tools ===*/
1134/*====================================================================*/
1135
1136static void list_tools(void)
1137{
1138 DIR *dir = opendir(VG_(libdir));
1139 struct dirent *de;
1140 int first = 1;
1141
1142 if (dir == NULL) {
1143 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001144 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001145 return;
1146 }
1147
nethercotef4928da2004-06-15 10:54:40 +00001148 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001149 int len = strlen(de->d_name);
1150
njn063c5402004-11-22 16:58:05 +00001151 /* look for vgtool_TOOL.so names */
1152 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1153 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001154 VG_STREQ(de->d_name + len - 3, ".so")) {
1155 if (first) {
1156 fprintf(stderr, "Available tools:\n");
1157 first = 0;
1158 }
1159 de->d_name[len-3] = '\0';
1160 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001161 }
1162 }
1163
1164 closedir(dir);
1165
1166 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001167 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1168 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001169}
1170
1171
1172/* Find and load a tool, and check it looks ok. Also looks to see if there's
1173 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001174static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001175 ToolInfo** toolinfo_out, char **preloadpath_out )
1176{
1177 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001178 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001179 char buf[len];
1180 void* handle;
1181 ToolInfo* toolinfo;
1182 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001183
1184 // XXX: allowing full paths for --tool option -- does it make sense?
1185 // Doesn't allow for vgpreload_<tool>.so.
1186
1187 if (strchr(toolname, '/') != 0) {
1188 /* toolname contains '/', and so must be a pathname */
1189 handle = dlopen(toolname, RTLD_NOW);
1190 } else {
1191 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001192 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001193 handle = dlopen(buf, RTLD_NOW);
1194
1195 if (handle != NULL) {
1196 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1197 if (access(buf, R_OK) == 0) {
1198 preloadpath = strdup(buf);
1199 vg_assert(NULL != preloadpath);
1200 }
1201 }
1202 }
1203
1204 ok = (NULL != handle);
1205 if (!ok) {
1206 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1207 goto bad_load;
1208 }
1209
njn51d827b2005-05-09 01:02:08 +00001210 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001211 ok = (NULL != toolinfo);
1212 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001213 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001214 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1215 goto bad_load;
1216 }
1217
1218 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001219 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1220 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001221 if (!ok) {
1222 fprintf(stderr, "Error:\n"
1223 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001224 " Interface version used by core is: %d (size %d)\n"
1225 " Interface version used by tool is: %d (size %d)\n"
1226 " The version numbers must match.\n",
1227 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001228 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001229 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001230 toolinfo->sizeof_ToolInfo);
1231 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001232 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001233 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001234 else
nethercote996901a2004-08-03 13:29:09 +00001235 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001236 goto bad_load;
1237 }
1238
njn8a97c6d2005-03-31 04:37:24 +00001239 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001240 *toolinfo_out = toolinfo;
1241 *preloadpath_out = preloadpath;
1242 return;
1243
1244
1245 bad_load:
1246 if (handle != NULL)
1247 dlclose(handle);
1248
nethercotef4928da2004-06-15 10:54:40 +00001249 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001250 list_tools();
1251 exit(127);
1252}
1253
nethercotef4928da2004-06-15 10:54:40 +00001254
1255/*====================================================================*/
1256/*=== Command line errors ===*/
1257/*====================================================================*/
1258
1259static void abort_msg ( void )
1260{
nethercotef8548672004-06-21 12:42:35 +00001261 VG_(clo_log_to) = VgLogTo_Fd;
1262 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001263}
1264
1265void VG_(bad_option) ( Char* opt )
1266{
1267 abort_msg();
1268 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1269 VG_(printf)("valgrind: Use --help for more information.\n");
1270 VG_(exit)(1);
1271}
1272
nethercotef4928da2004-06-15 10:54:40 +00001273static void missing_prog ( void )
1274{
1275 abort_msg();
1276 VG_(printf)("valgrind: no program specified\n");
1277 VG_(printf)("valgrind: Use --help for more information.\n");
1278 VG_(exit)(1);
1279}
1280
1281static void config_error ( Char* msg )
1282{
1283 abort_msg();
1284 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1285 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1286 VG_(exit)(1);
1287}
1288
1289
nethercote71980f02004-01-24 18:18:54 +00001290/*====================================================================*/
1291/*=== Loading the client ===*/
1292/*====================================================================*/
1293
nethercotef4928da2004-06-15 10:54:40 +00001294static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001295 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1296{
1297 // If they didn't specify an executable with --exec, and didn't specify
1298 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001299 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001300 if (cl_argv[0] == NULL ||
1301 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1302 {
nethercotef4928da2004-06-15 10:54:40 +00001303 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001304 }
1305 }
1306
1307 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001308 info->exe_base = VG_(client_base);
1309 info->exe_end = VG_(client_end);
1310 info->argv = cl_argv;
1311
nethercotef4928da2004-06-15 10:54:40 +00001312 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001313 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001314 // Totally zero 'info' before continuing.
1315 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001316 } else {
1317 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001318 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001319 ret = do_exec(exec, info);
1320 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001321 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1322 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001323 exit(127);
1324 }
1325 }
1326
1327 /* Copy necessary bits of 'info' that were filled in */
1328 *client_eip = info->init_eip;
1329 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1330}
1331
nethercote969ecf12004-10-13 17:29:01 +00001332/*====================================================================*/
1333/*=== Address space unpadding ===*/
1334/*====================================================================*/
1335
1336typedef struct {
1337 char* killpad_start;
1338 char* killpad_end;
1339 struct stat* killpad_padstat;
1340} killpad_extra;
1341
1342static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1343 int maj, int min, int ino, void* ex)
1344{
1345 killpad_extra* extra = ex;
1346 void *b, *e;
1347 int res;
1348
1349 vg_assert(NULL != extra->killpad_padstat);
1350
1351 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1352 extra->killpad_padstat->st_ino != ino)
1353 return 1;
1354
1355 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1356 return 1;
1357
1358 if (segstart <= extra->killpad_start)
1359 b = extra->killpad_start;
1360 else
1361 b = segstart;
1362
1363 if (segend >= extra->killpad_end)
1364 e = extra->killpad_end;
1365 else
1366 e = segend;
1367
1368 res = munmap(b, (char *)e-(char *)b);
1369 vg_assert(0 == res);
1370
1371 return 1;
1372}
1373
1374// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001375static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001376{
1377 static struct stat padstat;
1378 killpad_extra extra;
1379 int res;
1380
sewardjb5f6f512005-03-10 23:59:00 +00001381 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001382
1383 res = fstat(padfile, &padstat);
1384 vg_assert(0 == res);
1385 extra.killpad_padstat = &padstat;
1386 extra.killpad_start = start;
1387 extra.killpad_end = end;
1388 foreach_map(killpad, &extra);
1389}
1390
sewardj2c5ffbe2005-03-12 13:32:06 +00001391static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001392{
1393 int res = close(padfile);
1394 vg_assert(0 == res);
1395}
1396
nethercote71980f02004-01-24 18:18:54 +00001397
1398/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001399/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001400/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001401
njn25e49d8e72002-09-23 09:36:25 +00001402/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001403VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001404Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001405Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001406Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001407Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001408Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001409Int VG_(clo_verbosity) = 1;
1410Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001411Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001412
nethercotef1e5e152004-09-01 23:58:16 +00001413/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001414 fd is initially stdout, for --help, but gets moved to stderr by default
1415 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001416VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001417Int VG_(clo_log_fd) = 1;
1418Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001419
thughes6233a382004-08-21 11:10:44 +00001420Bool VG_(clo_time_stamp) = False;
1421
sewardj6024b212003-07-13 10:54:33 +00001422Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001423Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001424Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001425Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001426UChar VG_(clo_trace_flags) = 0; // 00000000b
1427UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001428Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001429Bool VG_(clo_trace_syscalls) = False;
1430Bool VG_(clo_trace_signals) = False;
1431Bool VG_(clo_trace_symtab) = False;
sewardjce058b02005-05-01 08:55:38 +00001432Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001433Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001434Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001435Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001436Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001437Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001438Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001439Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001440Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001441Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001442Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001443Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001444Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001445Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001446Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001447Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001448
jsgf855d93d2003-10-13 22:26:55 +00001449static Bool VG_(clo_wait_for_gdb) = False;
1450
sewardjde4a1d02002-03-22 01:27:54 +00001451
sewardj2c5ffbe2005-03-12 13:32:06 +00001452static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001453{
njn25e49d8e72002-09-23 09:36:25 +00001454 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001455"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001456"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001457" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001458" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001459" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001460" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001461" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001462" -q --quiet run silently; only print error msgs\n"
1463" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001464" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001465" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001466" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001467"\n"
1468" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001469" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001470" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001471" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001472" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001473" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001474"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001475" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001476" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1477" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001478" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001479" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001480" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001481" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001482" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1483" --show-below-main=no|yes continue stack traces below main() [no]\n"
1484" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001485" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001486" --db-attach=no|yes start debugger when errors detected? [no]\n"
1487" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1488" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001489" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1490" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001491"\n";
njn7cf0bd32002-06-08 13:36:03 +00001492
njn25e49d8e72002-09-23 09:36:25 +00001493 Char* usage2 =
1494"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001495" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001496" --sanity-level=<number> level of sanity checking to do [1]\n"
1497" --single-step=no|yes translate each instr separately? [no]\n"
1498" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001499" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001500" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001501" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1502" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001503" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001504" --trace-syscalls=no|yes show all system calls? [no]\n"
1505" --trace-signals=no|yes show signal handling details? [no]\n"
1506" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001507" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001508" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001509" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001510#if 0
1511" --model-pthreads=yes|no model the pthreads library [no]\n"
1512#endif
1513" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001514"\n"
1515" --vex-iropt-verbosity 0 .. 9 [0]\n"
1516" --vex-iropt-level 0 .. 2 [2]\n"
1517" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001518" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1519" --vex-guest-max-insns 1 .. 100 [50]\n"
1520" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1521"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001522" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001523" 1000 0000 show conversion into IR\n"
1524" 0100 0000 show after initial opt\n"
1525" 0010 0000 show after instrumentation\n"
1526" 0001 0000 show after second opt\n"
1527" 0000 1000 show after tree building\n"
1528" 0000 0100 show selecting insns\n"
1529" 0000 0010 show after reg-alloc\n"
1530" 0000 0001 show final assembly\n"
1531"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001532" debugging options for Valgrind tools that report errors\n"
1533" --dump-error=<number> show translation for basic block associated\n"
1534" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001535"\n";
njn3e884182003-04-15 13:03:23 +00001536
1537 Char* usage3 =
1538"\n"
nethercote71980f02004-01-24 18:18:54 +00001539" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001540"\n"
njn53612422005-03-12 16:22:54 +00001541" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" and licensed under the GNU General Public License, version 2.\n"
1543" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001544"\n"
nethercote137bc552003-11-14 17:47:54 +00001545" Tools are copyright and licensed by their authors. See each\n"
1546" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n";
njn7cf0bd32002-06-08 13:36:03 +00001548
fitzhardinge98abfc72003-12-16 02:05:15 +00001549 VG_(printf)(usage1);
1550 if (VG_(details).name) {
1551 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001552 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001553 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001554 else
1555 VG_(printf)(" (none)\n");
1556 }
nethercote6c999f22004-01-31 22:55:15 +00001557 if (debug_help) {
1558 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559
nethercote6c999f22004-01-31 22:55:15 +00001560 if (VG_(details).name) {
1561 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1562
1563 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001564 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001565 else
1566 VG_(printf)(" (none)\n");
1567 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001568 }
nethercote421281e2003-11-20 16:20:55 +00001569 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001570 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001571}
sewardjde4a1d02002-03-22 01:27:54 +00001572
nethercote71980f02004-01-24 18:18:54 +00001573static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001574 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001575{
nethercote71980f02004-01-24 18:18:54 +00001576 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001577
sewardj8b635a42004-11-22 19:01:47 +00001578 LibVEX_default_VexControl(& VG_(clo_vex_control));
1579
nethercote71980f02004-01-24 18:18:54 +00001580 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001581 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001582
nethercotef6a1d502004-08-09 12:21:57 +00001583 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001584 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001585 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001586
nethercotef6a1d502004-08-09 12:21:57 +00001587 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1588 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001589 *need_help = 1;
1590
nethercotef6a1d502004-08-09 12:21:57 +00001591 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001592 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001593
nethercotef6c99d72004-11-09 14:35:43 +00001594 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001595 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001596
nethercotef6a1d502004-08-09 12:21:57 +00001597 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1598 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001599 }
1600 }
nethercote71980f02004-01-24 18:18:54 +00001601}
1602
nethercote5ee67ca2004-06-22 14:00:09 +00001603static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001604{
nethercotef8548672004-06-21 12:42:35 +00001605 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001606 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001607
nethercotee1730692003-11-20 10:38:07 +00001608 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001609 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001610
sewardj19d81412002-06-03 01:10:40 +00001611 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001612 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001613 config_error("Please use absolute paths in "
1614 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001615
njnc6168192004-11-29 13:54:10 +00001616// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001617#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001618 {
sewardjb5f6f512005-03-10 23:59:00 +00001619 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001620 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1621 switch(auxp[0]) {
1622 case AT_SYSINFO:
1623 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1624 break;
1625 }
1626 }
1627 }
1628#endif
sewardjde4a1d02002-03-22 01:27:54 +00001629
nethercotef6a1d502004-08-09 12:21:57 +00001630 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001631
nethercotef6a1d502004-08-09 12:21:57 +00001632 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001633 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001634
thughes3bfd5a02004-07-18 08:05:44 +00001635 /* Look for a colon in the switch name */
1636 while (*colon && *colon != ':' && *colon != '=')
1637 colon++;
nethercote71980f02004-01-24 18:18:54 +00001638
1639 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001640 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001641 if (VG_CLO_STREQN(2, arg, "--") &&
1642 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1643 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1644 {
1645 // prefix matches, convert "--toolname:foo" to "--foo"
1646 if (0)
1647 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001648 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001649 arg[0] = '-';
1650 arg[1] = '-';
1651
1652 } else {
1653 // prefix doesn't match, skip to next arg
1654 continue;
1655 }
1656 }
1657
fitzhardinge98abfc72003-12-16 02:05:15 +00001658 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001659 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1660 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1661 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001662
njn45270a22005-03-27 01:00:11 +00001663 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001664
nethercote71980f02004-01-24 18:18:54 +00001665 else if (VG_CLO_STREQ(arg, "-v") ||
1666 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001667 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001668
nethercote71980f02004-01-24 18:18:54 +00001669 else if (VG_CLO_STREQ(arg, "-q") ||
1670 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001671 VG_(clo_verbosity)--;
1672
sewardj1cf558c2005-04-25 01:36:56 +00001673 else if (VG_CLO_STREQ(arg, "-d")) {
1674 /* do nothing */
1675 }
1676
njn45270a22005-03-27 01:00:11 +00001677 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1678 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1679 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1680 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1681 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1682 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1683 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001684 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001685 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1686 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1687 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1688 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1689 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1690 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1691 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1692 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1693 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001694 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001695 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1696 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1697 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1698 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1699 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001700
njn45270a22005-03-27 01:00:11 +00001701 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1702 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001703
njn45270a22005-03-27 01:00:11 +00001704 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1705 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1706 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1707 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1708 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001709
njn45270a22005-03-27 01:00:11 +00001710 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001711 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001712 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001713 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001714 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001715 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001716 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001717 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001718 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001719 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001720 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001721 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1722
nethercotef8548672004-06-21 12:42:35 +00001723 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1724 VG_(clo_log_to) = VgLogTo_Fd;
1725 VG_(clo_log_name) = NULL;
1726 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001727 }
1728
nethercotef8548672004-06-21 12:42:35 +00001729 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1730 VG_(clo_log_to) = VgLogTo_File;
1731 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001732 }
njnd6bc3c32005-03-27 00:44:31 +00001733
sewardj603d4102005-01-11 14:01:02 +00001734 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1735 VG_(clo_log_to) = VgLogTo_FileExactly;
1736 VG_(clo_log_name) = &arg[19];
1737 }
sewardjde4a1d02002-03-22 01:27:54 +00001738
nethercotef8548672004-06-21 12:42:35 +00001739 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1740 VG_(clo_log_to) = VgLogTo_Socket;
1741 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001742 }
1743
nethercote71980f02004-01-24 18:18:54 +00001744 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001745 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001746 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001747 VG_(message)(Vg_UserMsg,
1748 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001749 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001750 }
nethercote71980f02004-01-24 18:18:54 +00001751 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001752 VG_(clo_n_suppressions)++;
1753 }
sewardjde4a1d02002-03-22 01:27:54 +00001754
sewardjfa8ec112005-01-19 11:55:34 +00001755 /* "stuvwxyz" --> stuvwxyz (binary) */
1756 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1757 Int j;
1758 char* opt = & arg[14];
1759
1760 if (8 != VG_(strlen)(opt)) {
1761 VG_(message)(Vg_UserMsg,
1762 "--trace-flags argument must have 8 digits");
1763 VG_(bad_option)(arg);
1764 }
1765 for (j = 0; j < 8; j++) {
1766 if ('0' == opt[j]) { /* do nothing */ }
1767 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1768 else {
1769 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1770 "contain 0s and 1s");
1771 VG_(bad_option)(arg);
1772 }
1773 }
1774 }
1775
1776 /* "stuvwxyz" --> stuvwxyz (binary) */
1777 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001778 Int j;
nethercote71980f02004-01-24 18:18:54 +00001779 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001780
sewardj2a99cf62004-11-24 10:44:19 +00001781 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001782 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001783 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001784 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001785 }
sewardj8b635a42004-11-22 19:01:47 +00001786 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001787 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001788 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001789 else {
sewardjfa8ec112005-01-19 11:55:34 +00001790 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001791 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001792 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001793 }
1794 }
1795 }
sewardjde4a1d02002-03-22 01:27:54 +00001796
njn45270a22005-03-27 01:00:11 +00001797 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001798
sewardjd153fae2005-01-10 17:24:47 +00001799 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1800 VG_(clo_gen_suppressions) = 0;
1801 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1802 VG_(clo_gen_suppressions) = 1;
1803 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1804 VG_(clo_gen_suppressions) = 2;
1805
nethercote71980f02004-01-24 18:18:54 +00001806 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001807 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001808 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001809 }
njn8c0b3bb2005-03-12 21:20:39 +00001810 skip_arg:
1811 if (arg != vg_argv[i])
1812 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001813 }
1814
sewardj998d40d2004-12-06 14:24:52 +00001815 /* Make VEX control parameters sane */
1816
1817 if (VG_(clo_vex_control).guest_chase_thresh
1818 >= VG_(clo_vex_control).guest_max_insns)
1819 VG_(clo_vex_control).guest_chase_thresh
1820 = VG_(clo_vex_control).guest_max_insns - 1;
1821
1822 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1823 VG_(clo_vex_control).guest_chase_thresh = 0;
1824
1825 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001826
njnf9ebf672003-05-12 21:41:30 +00001827 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001828 VG_(clo_verbosity) = 0;
1829
nethercote04d0fbc2004-01-26 16:48:06 +00001830 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(message)(Vg_UserMsg, "");
1832 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001833 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001834 VG_(message)(Vg_UserMsg,
1835 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001836 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001837 }
1838
nethercotef8548672004-06-21 12:42:35 +00001839 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001840 should be connected to whatever sink has been selected, and we
1841 indiscriminately chuck stuff into it without worrying what the
1842 nature of it is. Oh the wonder of Unix streams. */
1843
nethercotee1730692003-11-20 10:38:07 +00001844 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001845 the terminal any problems to do with processing command line
1846 opts. */
nethercotef8548672004-06-21 12:42:35 +00001847 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001848 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001849
1850 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001851
sewardj4cf05692002-10-27 20:28:29 +00001852 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001853 vg_assert(VG_(clo_log_name) == NULL);
1854 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001855 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001856
sewardj4cf05692002-10-27 20:28:29 +00001857 case VgLogTo_File: {
1858 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001859 Int seq = 0;
1860 Int pid = VG_(getpid)();
1861
nethercotef8548672004-06-21 12:42:35 +00001862 vg_assert(VG_(clo_log_name) != NULL);
1863 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001864
nethercote71980f02004-01-24 18:18:54 +00001865 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001866 if (seq == 0)
1867 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001868 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001869 else
1870 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001871 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001872 seq++;
1873
nethercotef8548672004-06-21 12:42:35 +00001874 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001875 = VG_(open)(logfilename,
1876 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1877 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001878 if (eventually_log_fd >= 0) {
1879 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001880 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001881 } else {
nethercotef8548672004-06-21 12:42:35 +00001882 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001883 VG_(message)(Vg_UserMsg,
1884 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001885 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001886 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001887 "--log-file=<file> (didn't work out for some reason.)");
1888 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001889 }
1890 }
1891 }
sewardj603d4102005-01-11 14:01:02 +00001892 break; /* switch (VG_(clo_log_to)) */
1893 }
1894
1895 case VgLogTo_FileExactly: {
1896 Char logfilename[1000];
1897
1898 vg_assert(VG_(clo_log_name) != NULL);
1899 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1900 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1901
1902 eventually_log_fd
1903 = VG_(open)(logfilename,
1904 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1905 VKI_S_IRUSR|VKI_S_IWUSR);
1906 if (eventually_log_fd >= 0) {
1907 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1908 }
1909 else if (eventually_log_fd != -VKI_EEXIST) {
1910 VG_(message)(Vg_UserMsg,
1911 "Can't create/open log file `%s'; giving up!",
1912 VG_(clo_log_name));
1913 VG_(bad_option)(
1914 "--log-file-exactly=<file> (didn't work out for some reason.)");
1915 /*NOTREACHED*/
1916 }
1917 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001918 }
1919
1920 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001921 vg_assert(VG_(clo_log_name) != NULL);
1922 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1923 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1924 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001925 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001926 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001927 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001928 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001929 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001930 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001931 }
nethercotef8548672004-06-21 12:42:35 +00001932 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001933 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001934 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001935 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001936 VG_(message)(Vg_UserMsg,
1937 "Log messages will sent to stderr instead." );
1938 VG_(message)(Vg_UserMsg,
1939 "" );
1940 /* We don't change anything here. */
1941 } else {
nethercotef8548672004-06-21 12:42:35 +00001942 vg_assert(eventually_log_fd > 0);
1943 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001944 VG_(logging_to_filedes) = False;
1945 }
sewardj73cf3bc2002-11-03 03:20:15 +00001946 break;
1947 }
1948
sewardj4cf05692002-10-27 20:28:29 +00001949 }
1950
nethercotef8548672004-06-21 12:42:35 +00001951 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001952 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001953 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001954 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1955 else {
nethercotef8548672004-06-21 12:42:35 +00001956 VG_(clo_log_fd) = eventually_log_fd;
1957 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001958 }
1959
sewardj4cf05692002-10-27 20:28:29 +00001960 /* Ok, the logging sink is running now. Print a suitable preamble.
1961 If logging to file or a socket, write details of parent PID and
1962 command line args, to help people trying to interpret the
1963 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001964
sewardj83adf412002-05-01 01:25:45 +00001965 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001966 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001967 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001968 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001969 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001970 NULL == VG_(details).version
1971 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001972 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001973 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001974
njnd04b7c62002-10-03 14:05:52 +00001975 /* Core details */
1976 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001977 "Using LibVEX rev %s, a library for dynamic binary translation.",
1978 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001979 VG_(message)(Vg_UserMsg,
1980 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1981 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001982 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001983 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001984 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001985 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001986 }
1987
nethercotec1e395d2003-11-10 13:26:49 +00001988 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001989 VG_(message)(Vg_UserMsg, "");
1990 VG_(message)(Vg_UserMsg,
1991 "My PID = %d, parent PID = %d. Prog and args are:",
1992 VG_(getpid)(), VG_(getppid)() );
1993 for (i = 0; i < VG_(client_argc); i++)
1994 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1995 }
1996
sewardjde4a1d02002-03-22 01:27:54 +00001997 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001998 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001999 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002000 VG_(message)(Vg_DebugMsg, "");
2001 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2002 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002003 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002004 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002005
njn1fd5eb22005-03-13 05:43:23 +00002006 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002007 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002008 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002009 }
nethercotea70f7352004-04-18 12:08:46 +00002010
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002012 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2013 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002014 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002015 } else {
2016 #define BUF_LEN 256
2017 Char version_buf[BUF_LEN];
2018 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2019 vg_assert(n <= 256);
2020 if (n > 0) {
2021 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002022 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002023 } else {
njn1fd5eb22005-03-13 05:43:23 +00002024 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002025 }
2026 VG_(close)(fd);
2027 #undef BUF_LEN
2028 }
sewardjde4a1d02002-03-22 01:27:54 +00002029 }
2030
fitzhardinge98abfc72003-12-16 02:05:15 +00002031 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002032 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002033 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002034 needs one, load the default */
2035 static const Char default_supp[] = "default.supp";
2036 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2037 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2038 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2039 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2040 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002041 }
sewardj4cf05692002-10-27 20:28:29 +00002042
sewardjd153fae2005-01-10 17:24:47 +00002043 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002044 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002045 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002046 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002047 VG_(message)(Vg_UserMsg,
2048 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002049 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002050 }
sewardjde4a1d02002-03-22 01:27:54 +00002051}
2052
nethercotef6a1d502004-08-09 12:21:57 +00002053// Build the string for VALGRINDCLO.
2054Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2055{
2056 /* If we're tracing the children, then we need to start it
2057 with our starter+arguments, which are copied into VALGRINDCLO,
2058 except the --exec= option is changed if present.
2059 */
2060 Int i;
2061 Char *exec;
2062 Char *cp;
2063 Char *optvar;
2064 Int optlen, execlen;
2065
2066 // All these allocated blocks are not free - because we're either
2067 // going to exec, or panic when we fail.
2068
2069 // Create --exec= option: "--exec=<exename>"
2070 exec = VG_(arena_malloc)(VG_AR_CORE,
2071 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2072 vg_assert(NULL != exec);
2073 VG_(sprintf)(exec, "--exec=%s", exename);
2074
2075 // Allocate space for optvar (may overestimate by counting --exec twice,
2076 // no matter)
2077 optlen = 1;
2078 for (i = 0; i < vg_argc; i++)
2079 optlen += VG_(strlen)(vg_argv[i]) + 1;
2080 optlen += VG_(strlen)(exec)+1;
2081 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2082
2083 // Copy all valgrind args except the old --exec (if present)
2084 // VG_CLO_SEP is the separator.
2085 cp = optvar;
2086 for (i = 1; i < vg_argc; i++) {
2087 Char *arg = vg_argv[i];
2088
2089 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2090 // don't copy existing --exec= arg
2091 } else if (VG_(strcmp)(arg, "--") == 0) {
2092 // stop at "--"
2093 break;
2094 } else {
2095 // copy non "--exec" arg
2096 Int len = VG_(strlen)(arg);
2097 VG_(memcpy)(cp, arg, len);
2098 cp += len;
2099 *cp++ = VG_CLO_SEP;
2100 }
2101 }
2102 // Add the new --exec= option
2103 execlen = VG_(strlen)(exec);
2104 VG_(memcpy)(cp, exec, execlen);
2105 cp += execlen;
2106 *cp++ = VG_CLO_SEP;
2107
2108 *cp = '\0';
2109
2110 return optvar;
2111}
2112
2113// Build "/proc/self/fd/<execfd>".
2114Char* VG_(build_child_exename)( void )
2115{
2116 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2117 vg_assert(NULL != exename);
2118 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2119 return exename;
2120}
2121
sewardjde4a1d02002-03-22 01:27:54 +00002122
nethercote71980f02004-01-24 18:18:54 +00002123/*====================================================================*/
2124/*=== File descriptor setup ===*/
2125/*====================================================================*/
2126
2127static void setup_file_descriptors(void)
2128{
2129 struct vki_rlimit rl;
2130
2131 /* Get the current file descriptor limits. */
2132 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2133 rl.rlim_cur = 1024;
2134 rl.rlim_max = 1024;
2135 }
2136
2137 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002138 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2139 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002140 } else {
2141 rl.rlim_cur = rl.rlim_max;
2142 }
2143
2144 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002145 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2146 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002147
2148 /* Update the soft limit. */
2149 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2150
nethercotef6a1d502004-08-09 12:21:57 +00002151 if (vgexecfd != -1)
2152 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002153 if (VG_(clexecfd) != -1)
2154 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2155}
2156
nethercote71980f02004-01-24 18:18:54 +00002157/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002158/*=== Initialise program data/text, etc. ===*/
2159/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002160
sewardjb5f6f512005-03-10 23:59:00 +00002161static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2162 UInt dev, UInt ino, ULong foffset,
2163 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002164{
nethercote71980f02004-01-24 18:18:54 +00002165 /* Only record valgrind mappings for now, without loading any
2166 symbols. This is so we know where the free space is before we
2167 start allocating more memory (note: heap is OK, it's just mmap
2168 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002169 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002170 VG_(debugLog)(2, "main",
2171 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002172 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002173 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002174 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2175 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002176 /* update VG_(valgrind_last) if it looks wrong */
2177 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002178 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002179 }
sewardjde4a1d02002-03-22 01:27:54 +00002180}
2181
nethercote71980f02004-01-24 18:18:54 +00002182// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002183Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002184
sewardjb5f6f512005-03-10 23:59:00 +00002185/*
2186 This second pass adds in client mappings, and loads symbol tables
2187 for all interesting mappings. The trouble is that things can
2188 change as we go, because we're calling the Tool to track memory as
2189 we find it.
2190
2191 So for Valgrind mappings, we don't replace any mappings which
2192 aren't still identical (which will include the .so mappings, so we
2193 will load their symtabs)>
2194 */
2195static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2196 UInt dev, UInt ino, ULong foffset,
2197 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002198{
nethercote71980f02004-01-24 18:18:54 +00002199 UInt flags;
2200 Bool is_stack_segment;
2201 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002202
nethercote71980f02004-01-24 18:18:54 +00002203 is_stack_segment
2204 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002205
sewardj8c615892005-04-25 02:38:28 +00002206 VG_(debugLog)(2, "main",
2207 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002208 (void*)start, (void*)(start+size), prot, is_stack_segment,
2209 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002210
nethercote71980f02004-01-24 18:18:54 +00002211 if (is_stack_segment)
2212 flags = SF_STACK | SF_GROWDOWN;
2213 else
2214 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
nethercote71980f02004-01-24 18:18:54 +00002216 if (filename != NULL)
2217 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002218
sewardjb5f6f512005-03-10 23:59:00 +00002219#if 0
2220 // This needs to be fixed properly. jrs 20050307
2221 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2222 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002223
sewardjb5f6f512005-03-10 23:59:00 +00002224 /* We have to be a bit careful about inserting new mappings into
2225 the Valgrind part of the address space. We're actively
2226 changing things as we parse these mappings, particularly in
2227 shadow memory, and so we don't want to overwrite those
2228 changes. Therefore, we only insert/update a mapping if it is
2229 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002230
sewardjb5f6f512005-03-10 23:59:00 +00002231 NOTE: we're only talking about the Segment list mapping
2232 metadata; this doesn't actually mmap anything more. */
2233 if (filename || (s && s->addr == start && s->len == size)) {
2234 flags |= SF_VALGRIND;
2235 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2236 } else {
2237 /* assert range is already mapped */
2238 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2239 }
2240 } else
2241#endif
2242 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2243
2244 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2245 VG_TRACK( new_mem_startup, start, size,
2246 !!(prot & VKI_PROT_READ),
2247 !!(prot & VKI_PROT_WRITE),
2248 !!(prot & VKI_PROT_EXEC));
2249 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002250
nethercote71980f02004-01-24 18:18:54 +00002251 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002252 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002253 vg_assert(0 != r_esp);
2254 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002255 if (0) {
2256 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002257 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002258 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2259 r_esp, start+size);
2260 }
nethercote71980f02004-01-24 18:18:54 +00002261 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002262 // what's this for?
2263 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002264 }
sewardjde4a1d02002-03-22 01:27:54 +00002265}
2266
2267
nethercote71980f02004-01-24 18:18:54 +00002268/*====================================================================*/
2269/*=== Sanity check machinery (permanently engaged) ===*/
2270/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002271
2272/* A fast sanity check -- suitable for calling circa once per
2273 millisecond. */
2274
nethercote885dd912004-08-03 23:14:00 +00002275void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002276{
sewardjb5f6f512005-03-10 23:59:00 +00002277 ThreadId tid;
2278
njn37cea302002-09-30 11:24:00 +00002279 VGP_PUSHCC(VgpCoreCheapSanity);
2280
nethercote27fec902004-06-16 21:26:32 +00002281 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002282
2283 /* --- First do all the tests that we can do quickly. ---*/
2284
nethercote297effd2004-08-02 15:07:57 +00002285 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002286
njn25e49d8e72002-09-23 09:36:25 +00002287 /* Check stuff pertaining to the memory check system. */
2288
2289 /* Check that nobody has spuriously claimed that the first or
2290 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002291 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002292 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002293 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002294 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002295 }
njn25e49d8e72002-09-23 09:36:25 +00002296
2297 /* --- Now some more expensive checks. ---*/
2298
2299 /* Once every 25 times, check some more expensive stuff. */
2300 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002301 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002302 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002303
njn37cea302002-09-30 11:24:00 +00002304 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002305 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002306
2307# if 0
2308 { void zzzmemscan(void); zzzmemscan(); }
2309# endif
2310
nethercote297effd2004-08-02 15:07:57 +00002311 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002312 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002313
2314 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002315 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002316 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002317 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002318 }
sewardjb5f6f512005-03-10 23:59:00 +00002319
2320 /* Check that Segments and /proc/self/maps match up */
2321 //vg_assert(VG_(sanity_check_memory)());
2322
2323 /* Look for stack overruns. Visit all threads. */
2324 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002325 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002326
2327 if (VG_(threads)[tid].status == VgTs_Empty ||
2328 VG_(threads)[tid].status == VgTs_Zombie)
2329 continue;
2330
2331 remains = VGA_(stack_unused)(tid);
2332 if (remains < VKI_PAGE_SIZE)
2333 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2334 tid, remains);
2335 }
2336
njn25e49d8e72002-09-23 09:36:25 +00002337 /*
nethercote297effd2004-08-02 15:07:57 +00002338 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002339 */
njn37cea302002-09-30 11:24:00 +00002340 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002341 }
2342
nethercote27fec902004-06-16 21:26:32 +00002343 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002344 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002345 /* Check sanity of the low-level memory manager. Note that bugs
2346 in the client's code can cause this to fail, so we don't do
2347 this check unless specially asked for. And because it's
2348 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002349 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002350 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002351 }
njn37cea302002-09-30 11:24:00 +00002352 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002353}
nethercote71980f02004-01-24 18:18:54 +00002354
2355
2356/*====================================================================*/
2357/*=== main() ===*/
2358/*====================================================================*/
2359
nethercotec314eba2004-07-15 12:59:41 +00002360/*
2361 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002362 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002363 loads the client executable (and the dynamic linker, if necessary)
2364 into the client part, and calls into Valgrind proper.
2365
2366 The code is careful not to allow spurious mappings to appear in the
2367 wrong parts of the address space. In particular, to make sure
2368 dlopen puts things in the right place, it will pad out the forbidden
2369 chunks of address space so that dlopen is forced to put things where
2370 we want them.
2371
2372 The memory map it creates is:
2373
njn80950732005-03-26 00:18:45 +00002374 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002375 | client address space |
2376 : :
2377 : :
2378 | client stack |
2379 client_end +-------------------------+
2380 | redzone |
2381 shadow_base +-------------------------+
2382 | |
nethercote996901a2004-08-03 13:29:09 +00002383 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002384 | (may be 0 sized) |
2385 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002386 valgrind_base +-------------------------+
2387 | kickstart executable |
2388 | valgrind heap vvvvvvvvv| (barely used)
2389 - -
2390 | valgrind .so files |
2391 | and mappings |
2392 - -
2393 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002394 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002395 : kernel :
2396
2397 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2398 VG_(mmap)(), we need to build the segment skip-list, so we know where
2399 we can put things. However, building that structure requires
2400 allocating memory. So we need to a bootstrapping process. It's done
2401 by making VG_(arena_malloc)() have a special static superblock that's
2402 used for the first 1MB's worth of allocations. This is enough to
2403 build the segment skip-list.
2404*/
2405
thughes4ad52d02004-06-27 17:37:21 +00002406
sewardj1cf558c2005-04-25 01:36:56 +00002407/* This may be needed before m_mylibc is OK to run. */
2408static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2409{
2410 while (True) {
2411 if (*s1 == 0 && *s2 == 0) return 0;
2412 if (*s1 == 0) return -1;
2413 if (*s2 == 0) return 1;
2414
2415 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2416 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2417
2418 s1++; s2++;
2419 }
2420}
2421
2422
sewardjb5f6f512005-03-10 23:59:00 +00002423int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002424{
2425 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002426 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002427 const char *exec = NULL;
2428 char *preload; /* tool-specific LD_PRELOAD .so */
2429 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002430 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002431 struct exeinfo info;
2432 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002433 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002434 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002435 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002436 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002437 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002438
2439 //============================================================
2440 // Nb: startup is complex. Prerequisites are shown at every step.
2441 //
2442 // *** Be very careful when messing with the order ***
2443 //============================================================
2444
sewardj1cf558c2005-04-25 01:36:56 +00002445 //--------------------------------------------------------------
2446 // Start up the logging mechanism
2447 // p: none
2448 //--------------------------------------------------------------
2449 /* Start the debugging-log system ASAP. First find out how many
2450 "-d"s were specified. This is a pre-scan of the command line. */
2451 loglevel = 0;
2452 for (i = 1; i < argc; i++) {
2453 if (argv[i][0] != '-')
2454 break;
2455 if (0 == local_strcmp(argv[i], "--"))
2456 break;
2457 if (0 == local_strcmp(argv[i], "-d"))
2458 loglevel++;
2459 }
2460
2461 /* ... and start the debug logger. Now we can safely emit logging
2462 messages all through startup. */
2463 VG_(debugLog_startup)(loglevel, "Stage 2");
2464
nethercotef4928da2004-06-15 10:54:40 +00002465 //============================================================
2466 // Command line argument handling order:
2467 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002468 // (including the tool-specific usage)
2469 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002470 // * Then, if client is missing, abort with error msg
2471 // * Then, if any cmdline args are bad, abort with error msg
2472 //============================================================
2473
fitzhardingeb50068f2004-02-24 23:42:55 +00002474 // Get the current process datasize rlimit, and set it to zero.
2475 // This prevents any internal uses of brk() from having any effect.
2476 // We remember the old value so we can restore it on exec, so that
2477 // child processes will have a reasonable brk value.
2478 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2479 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2480 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002481
2482 // Get the current process stack rlimit.
2483 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2484
nethercote71980f02004-01-24 18:18:54 +00002485 //--------------------------------------------------------------
2486 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002487 // p: none
nethercote71980f02004-01-24 18:18:54 +00002488 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002489 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002490 {
sewardj1fbc1a52005-04-25 02:05:54 +00002491 void* init_sp = argv - 1;
2492 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002493 }
2494
2495 //--------------------------------------------------------------
2496 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002497 // p: none
nethercote71980f02004-01-24 18:18:54 +00002498 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002499 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002500 if (cp != NULL)
2501 VG_(libdir) = cp;
2502 }
2503
2504 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002505 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2506 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002507 // p: none
nethercote71980f02004-01-24 18:18:54 +00002508 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002509 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002510 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002511 pre_process_cmd_line_options(&need_help, &tool, &exec);
2512
2513 //==============================================================
2514 // Nb: once a tool is specified, the tool.so must be loaded even if
2515 // they specified --help or didn't specify a client program.
2516 //==============================================================
2517
2518 //--------------------------------------------------------------
2519 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002520 // p: set-libdir [for VG_(libdir)]
2521 // p: pre_process_cmd_line_options() [for 'tool']
2522 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002523 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002524 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002525
2526 //==============================================================
2527 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002528 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002529 //==============================================================
2530
2531 //--------------------------------------------------------------
2532 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002533 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002534 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002535 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002536 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002537
2538 //--------------------------------------------------------------
2539 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002540 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2541 // p: layout_remaining_space [so there's space]
2542 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002543 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002544 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002545
2546 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002547 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002548 // p: layout_remaining_space() [everything must be mapped in before now]
2549 // p: load_client() [ditto]
2550 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002551 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2552 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002553
2554 //--------------------------------------------------------------
2555 // Set up client's environment
2556 // p: set-libdir [for VG_(libdir)]
2557 // p: load_tool() [for 'preload']
2558 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002559 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002560 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002561
2562 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002563 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002564 // p: load_client() [for 'info']
2565 // p: fix_environment() [for 'env']
2566 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002567 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002568 {
sewardj1fbc1a52005-04-25 02:05:54 +00002569 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002570
sewardj1fbc1a52005-04-25 02:05:54 +00002571 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2572 &client_auxv);
2573 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002574 }
nethercote71980f02004-01-24 18:18:54 +00002575
sewardj1fbc1a52005-04-25 02:05:54 +00002576 VG_(debugLog)(2, "main",
2577 "Client info: "
2578 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2579 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2580 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002581
2582 //==============================================================
2583 // Finished setting up operating environment. Now initialise
2584 // Valgrind. (This is where the old VG_(main)() started.)
2585 //==============================================================
2586
2587 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002588 // setup file descriptors
2589 // p: n/a
2590 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002591 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002592 setup_file_descriptors();
2593
2594 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002595 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002596 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002597 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002598 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002599 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2600
2601 //==============================================================
2602 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2603 //==============================================================
2604
2605 //--------------------------------------------------------------
2606 // Init tool: pre_clo_init, process cmd line, post_clo_init
2607 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002608 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002609 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2610 // p: parse_procselfmaps [so VG segments are setup so tool can
2611 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002612 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002613 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002614 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002615 VG_(sanity_check_needs)();
2616
nethercotef4928da2004-06-15 10:54:40 +00002617 // If --tool and --help/--help-debug was given, now give the core+tool
2618 // help message
nethercotef4928da2004-06-15 10:54:40 +00002619 if (need_help) {
2620 usage(/*--help-debug?*/2 == need_help);
2621 }
nethercotec314eba2004-07-15 12:59:41 +00002622 process_cmd_line_options(client_auxv, tool);
2623
njn51d827b2005-05-09 01:02:08 +00002624 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002625
2626 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002627 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002628 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002629 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002630 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002631 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002632 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002633 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002634 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002635 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002636
sewardj21c6d0f2005-05-02 10:33:44 +00002637#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002638 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002639 // Protect client trampoline page (which is also sysinfo stuff)
2640 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002641 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002642 {
2643 Segment *seg;
2644 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2645 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002646
sewardjb5f6f512005-03-10 23:59:00 +00002647 /* Make sure this segment isn't treated as stack */
2648 seg = VG_(find_segment)(VG_(client_trampoline_code));
2649 if (seg)
2650 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2651 }
sewardj21c6d0f2005-05-02 10:33:44 +00002652#endif
sewardjb5f6f512005-03-10 23:59:00 +00002653
nethercotec314eba2004-07-15 12:59:41 +00002654 //==============================================================
2655 // Can use VG_(map)() after segments set up
2656 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002657
2658 //--------------------------------------------------------------
2659 // Allow GDB attach
2660 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2661 //--------------------------------------------------------------
2662 /* Hook to delay things long enough so we can get the pid and
2663 attach GDB in another shell. */
2664 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002665 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002666 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2667 /* jrs 20050206: I don't understand why this works on x86. On
2668 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2669 work. */
2670 /* do "jump *$eip" to skip this in gdb (x86) */
2671 //VG_(do_syscall0)(__NR_pause);
2672 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002673 }
2674
sewardjb5d320c2005-03-13 18:57:15 +00002675 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002676 // Search for file descriptors that are inherited from our parent
2677 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2678 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002679 if (VG_(clo_track_fds)) {
2680 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002681 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002682 }
nethercote71980f02004-01-24 18:18:54 +00002683
2684 //--------------------------------------------------------------
2685 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002686 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2687 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002688 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002689 VG_(scheduler_init)();
2690
2691 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002692 // Initialise the pthread model
2693 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002694 // load_client() [for 'client_eip']
2695 // setup_client_stack() [for 'sp_at_startup']
2696 // setup_scheduler() [for the rest of state 1 stuff]
2697 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002698 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002699 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002700
2701 // Tell the tool that we just wrote to the registers.
2702 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2703 sizeof(VexGuestArchState));
2704
sewardj2a99cf62004-11-24 10:44:19 +00002705 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002706 // Initialise the pthread model
2707 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002708 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002709 //if (VG_(clo_model_pthreads))
2710 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002711
2712 //--------------------------------------------------------------
2713 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002714 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002715 //--------------------------------------------------------------
2716 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002717 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002718 VG_(sigstartup_actions)();
2719
2720 //--------------------------------------------------------------
2721 // Perhaps we're profiling Valgrind?
2722 // p: process_cmd_line_options() [for VG_(clo_profile)]
2723 // p: others?
2724 //
2725 // XXX: this seems to be broken? It always says the tool wasn't built
2726 // for profiling; vg_profile.c's functions don't seem to be overriding
2727 // vg_dummy_profile.c's?
2728 //
2729 // XXX: want this as early as possible. Looking for --profile
2730 // in pre_process_cmd_line_options() could get it earlier.
2731 //--------------------------------------------------------------
2732 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002733 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002734
2735 VGP_PUSHCC(VgpStartup);
2736
2737 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002738 // Read suppression file
2739 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2740 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002741 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2742 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002743 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002744 }
nethercote71980f02004-01-24 18:18:54 +00002745
2746 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002747 // Initialise translation table and translation cache
2748 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2749 // aren't identified as part of the client, which would waste
2750 // > 20M of virtual address space.]
2751 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002752 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002753 VG_(init_tt_tc)();
2754
2755 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002756 // Read debug info to find glibc entry points to intercept
2757 // p: parse_procselfmaps? [XXX for debug info?]
2758 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2759 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002760 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002761 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002762 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002763
2764 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002765 // Verbosity message
2766 // p: end_rdtsc_calibration [so startup message is printed first]
2767 //--------------------------------------------------------------
2768 if (VG_(clo_verbosity) == 1)
2769 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2770 if (VG_(clo_verbosity) > 0)
2771 VG_(message)(Vg_UserMsg, "");
2772
2773 //--------------------------------------------------------------
2774 // Setup pointercheck
2775 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2776 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002777 if (VG_(clo_pointercheck))
2778 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002779
nethercote71980f02004-01-24 18:18:54 +00002780 //--------------------------------------------------------------
2781 // Run!
2782 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002783 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002784
sewardjb5f6f512005-03-10 23:59:00 +00002785 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002786
sewardj1fbc1a52005-04-25 02:05:54 +00002787 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002788 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002789
sewardjb5f6f512005-03-10 23:59:00 +00002790 abort();
2791}
2792
2793
2794/* Do everything which needs doing when the last thread exits */
2795void VG_(shutdown_actions)(ThreadId tid)
2796{
2797 vg_assert(tid == VG_(master_tid));
2798 vg_assert(VG_(is_running_thread)(tid));
2799
2800 // Wait for all other threads to exit.
2801 VGA_(reap_threads)(tid);
2802
2803 VG_(clo_model_pthreads) = False;
2804
2805 // Clean the client up before the final report
2806 VGA_(final_tidyup)(tid);
2807
2808 // OK, done
2809 VG_(exit_thread)(tid);
2810
2811 /* should be no threads left */
2812 vg_assert(VG_(count_living_threads)() == 0);
2813
2814 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002815 //--------------------------------------------------------------
2816 // Finalisation: cleanup, messages, etc. Order no so important, only
2817 // affects what order the messages come.
2818 //--------------------------------------------------------------
2819 if (VG_(clo_verbosity) > 0)
2820 VG_(message)(Vg_UserMsg, "");
2821
nethercote71980f02004-01-24 18:18:54 +00002822 /* Print out file descriptor summary and stats. */
2823 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002824 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002825
njn95ec8702004-11-22 16:46:13 +00002826 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002827 VG_(show_all_errors)();
2828
njn51d827b2005-05-09 01:02:08 +00002829 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002830
nethercote885dd912004-08-03 23:14:00 +00002831 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002832
2833 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002834 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002835
nethercote71980f02004-01-24 18:18:54 +00002836 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002837 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002838 if (VG_(clo_profile_flags) > 0)
2839 VG_(show_BB_profile)();
2840
sewardj8b635a42004-11-22 19:01:47 +00002841 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002842 if (0)
2843 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002844}
sewardj8b635a42004-11-22 19:01:47 +00002845
sewardjde4a1d02002-03-22 01:27:54 +00002846/*--------------------------------------------------------------------*/
2847/*--- end vg_main.c ---*/
2848/*--------------------------------------------------------------------*/