blob: 9a2e2ed8aab9d5ad691c6efbea0f9c6b6bf125ab [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"
njnd01fef72005-03-25 23:35:48 +000035#include "pub_core_execontext.h"
njnd2b17112005-04-19 04:10:25 +000036#include "pub_core_errormgr.h"
sewardj1cf558c2005-04-25 01:36:56 +000037#include "pub_core_debuglog.h"
nethercote71980f02004-01-24 18:18:54 +000038
39#include <dirent.h>
40#include <dlfcn.h>
41#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000042#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000043#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <string.h>
45#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000046#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000047#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/wait.h>
49#include <unistd.h>
50
sewardjb5f6f512005-03-10 23:59:00 +000051#include "memcheck/memcheck.h"
52
thughes74b8de22004-04-22 18:12:31 +000053#ifndef AT_DCACHEBSIZE
54#define AT_DCACHEBSIZE 19
55#endif /* AT_DCACHEBSIZE */
56
57#ifndef AT_ICACHEBSIZE
58#define AT_ICACHEBSIZE 20
59#endif /* AT_ICACHEBSIZE */
60
61#ifndef AT_UCACHEBSIZE
62#define AT_UCACHEBSIZE 21
63#endif /* AT_UCACHEBSIZE */
64
nethercote71980f02004-01-24 18:18:54 +000065#ifndef AT_SYSINFO
66#define AT_SYSINFO 32
67#endif /* AT_SYSINFO */
68
69#ifndef AT_SYSINFO_EHDR
70#define AT_SYSINFO_EHDR 33
71#endif /* AT_SYSINFO_EHDR */
72
73#ifndef AT_SECURE
74#define AT_SECURE 23 /* secure mode boolean */
75#endif /* AT_SECURE */
76
nethercote71980f02004-01-24 18:18:54 +000077/* redzone gap between client address space and shadow */
78#define REDZONE_SIZE (1 * 1024*1024)
79
80/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000081#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000082
nethercotee2097312004-06-27 12:29:56 +000083/* Proportion of client space for its heap (rest is for mmaps + stack) */
84#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000085
njn14319cc2005-03-13 06:26:22 +000086/* Number of file descriptors that Valgrind tries to reserve for
87 it's own use - just a small constant. */
88#define N_RESERVED_FDS (10)
89
90/* Default debugger command. */
91#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
92
nethercote71980f02004-01-24 18:18:54 +000093/*====================================================================*/
94/*=== Global entities not referenced from generated code ===*/
95/*====================================================================*/
96
sewardjde4a1d02002-03-22 01:27:54 +000097/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000098 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000099 ------------------------------------------------------------------ */
100
nethercote71980f02004-01-24 18:18:54 +0000101/* Client address space, lowest to highest (see top of ume.c) */
102Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(client_end);
104Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000105Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(clstk_base);
107Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000108
109Addr VG_(brk_base); /* start of brk */
110Addr VG_(brk_limit); /* current brk */
111
nethercote996901a2004-08-03 13:29:09 +0000112Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000113Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000114
115Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000116
nethercote820bd8c2004-09-07 23:04:49 +0000117// Note that VG_(valgrind_last) names the last byte of the section, whereas
118// the VG_(*_end) vars name the byte one past the end of the section.
119Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000120
nethercote73b526f2004-10-31 18:48:21 +0000121struct vki_rlimit VG_(client_rlimit_data);
122struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000123
fitzhardinge98abfc72003-12-16 02:05:15 +0000124/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000125static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000126
127/* client executable */
128Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000129
130/* Path to library directory */
131const Char *VG_(libdir) = VG_LIBDIR;
132
133/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000134static Int vg_argc;
135static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000136
sewardjb5f6f512005-03-10 23:59:00 +0000137/* The master thread the one which will be responsible for mopping
138 everything up at exit. Normally it is tid 1, since that's the
139 first thread created, but it may be something else after a
140 fork(). */
141ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000142
thughesad1c9562004-06-26 11:27:52 +0000143/* Application-visible file descriptor limits */
144Int VG_(fd_soft_limit) = -1;
145Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000146
nethercote4ad74312004-10-26 09:59:49 +0000147/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000148 envp[] as extracted from the client's stack at startup-time. */
149Int VG_(client_argc);
150Char** VG_(client_argv);
151Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000152
sewardj51ac0872004-12-21 01:20:49 +0000153/* Indicates what arch and subarch we are running on. */
154VexArch VG_(vex_arch) = VexArch_INVALID;
155VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
156
157
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
nethercote71980f02004-01-24 18:18:54 +0000162/* Counts downwards in VG_(run_innerloop). */
163UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000164
165/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000166ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000167
nethercote71980f02004-01-24 18:18:54 +0000168/* Tell the logging mechanism whether we are logging to a file
169 descriptor or a socket descriptor. */
170Bool VG_(logging_to_filedes) = True;
171
sewardj73cf3bc2002-11-03 03:20:15 +0000172
nethercote71980f02004-01-24 18:18:54 +0000173/*====================================================================*/
174/*=== Counters, for profiling purposes only ===*/
175/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000176
sewardjde4a1d02002-03-22 01:27:54 +0000177/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000178static UInt sanity_fast_count = 0;
179static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000182{
nethercote3a42fb82004-08-03 18:08:50 +0000183 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000184 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000185 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000186 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000189 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000190
nethercote71980f02004-01-24 18:18:54 +0000191 VG_(message)(Vg_DebugMsg,
192 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000193 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000194
njn9271cbc2005-03-13 05:38:25 +0000195 VG_(print_ExeContext_stats)();
196
nethercote3a42fb82004-08-03 18:08:50 +0000197 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000198 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000199 VG_(message)(Vg_DebugMsg, "");
200 VG_(message)(Vg_DebugMsg,
201 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000202 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000203 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000204 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000205 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000206 }
nethercote71980f02004-01-24 18:18:54 +0000207}
208
209
210/*====================================================================*/
211/*=== Miscellaneous global functions ===*/
212/*====================================================================*/
213
nethercotecf97ffb2004-09-09 13:40:31 +0000214static Int ptrace_setregs(Int pid, ThreadId tid)
215{
sewardj2a99cf62004-11-24 10:44:19 +0000216 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000217}
218
nethercote04d0fbc2004-01-26 16:48:06 +0000219/* Start debugger and get it to attach to this process. Called if the
220 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000221 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000222 meaningfully get the debugger to continue the program, though; to
223 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000224void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000225{
226 Int pid;
227
228 if ((pid = fork()) == 0) {
229 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000230 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000231
232 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000233 Int status;
234 Int res;
235
nethercote71980f02004-01-24 18:18:54 +0000236 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
237 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000238 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000239 kill(pid, SIGSTOP) == 0 &&
240 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000241 Char pidbuf[15];
242 Char file[30];
243 Char buf[100];
244 Char *bufptr;
245 Char *cmdptr;
246
247 VG_(sprintf)(pidbuf, "%d", pid);
248 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
249
250 bufptr = buf;
251 cmdptr = VG_(clo_db_command);
252
253 while (*cmdptr) {
254 switch (*cmdptr) {
255 case '%':
256 switch (*++cmdptr) {
257 case 'f':
258 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
259 bufptr += VG_(strlen)(file);
260 cmdptr++;
261 break;
262 case 'p':
263 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
264 bufptr += VG_(strlen)(pidbuf);
265 cmdptr++;
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 break;
272 default:
273 *bufptr++ = *cmdptr++;
274 break;
275 }
276 }
277
278 *bufptr++ = '\0';
279
280 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000281 res = VG_(system)(buf);
282 if (res == 0) {
283 VG_(message)(Vg_UserMsg, "");
284 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000285 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000286 } else {
287 VG_(message)(Vg_UserMsg, "Apparently failed!");
288 VG_(message)(Vg_UserMsg, "");
289 }
290 }
291
nethercote73b526f2004-10-31 18:48:21 +0000292 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000293 VG_(waitpid)(pid, &status, 0);
294 }
295}
296
297
298/* Print some helpful-ish text about unimplemented things, and give
299 up. */
300void VG_(unimplemented) ( Char* msg )
301{
302 VG_(message)(Vg_UserMsg, "");
303 VG_(message)(Vg_UserMsg,
304 "Valgrind detected that your program requires");
305 VG_(message)(Vg_UserMsg,
306 "the following unimplemented functionality:");
307 VG_(message)(Vg_UserMsg, " %s", msg);
308 VG_(message)(Vg_UserMsg,
309 "This may be because the functionality is hard to implement,");
310 VG_(message)(Vg_UserMsg,
311 "or because no reasonable program would behave this way,");
312 VG_(message)(Vg_UserMsg,
313 "or because nobody has yet needed it. In any case, let us know at");
314 VG_(message)(Vg_UserMsg,
315 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
316 VG_(message)(Vg_UserMsg,
317 "");
318 VG_(message)(Vg_UserMsg,
319 "Valgrind has to exit now. Sorry. Bye!");
320 VG_(message)(Vg_UserMsg,
321 "");
322 VG_(pp_sched_status)();
323 VG_(exit)(1);
324}
325
sewardj2a99cf62004-11-24 10:44:19 +0000326/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000327Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000328{
njncf45fd42004-11-24 16:30:22 +0000329 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000330}
331
njn67516132005-03-22 04:02:43 +0000332Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000333{
334 return INSTR_PTR( VG_(threads)[tid].arch );
335}
336
njnea4b28c2004-11-30 16:04:58 +0000337
nethercote71980f02004-01-24 18:18:54 +0000338/*====================================================================*/
339/*=== Check we were launched by stage 1 ===*/
340/*====================================================================*/
341
342/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000343static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000344{
nethercoteebf1d862004-11-01 18:22:05 +0000345 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000346 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000347
348 for (; auxv->a_type != AT_NULL; auxv++)
349 switch(auxv->a_type) {
350 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000351 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 1;
353 break;
354
355 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000356 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000357 found |= 2;
358 break;
nethercote7f390022004-10-25 17:18:24 +0000359
360 case AT_PHDR:
361 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
362 break;
nethercote71980f02004-01-24 18:18:54 +0000363 }
364
nethercote361a14e2004-07-26 11:11:56 +0000365 if ( found != (1|2) ) {
366 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000367 exit(127);
368 }
nethercote31779c72004-07-30 21:50:15 +0000369 vg_assert(padfile >= 0);
370 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000371}
372
373
374/*====================================================================*/
375/*=== Address space determination ===*/
376/*====================================================================*/
377
nethercote7f390022004-10-25 17:18:24 +0000378extern char _start[];
379
nethercote31779c72004-07-30 21:50:15 +0000380static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000381{
nethercotea3c3cf22004-11-01 18:38:00 +0000382 Int ires;
383 void* vres;
384 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000385
nethercote7f390022004-10-25 17:18:24 +0000386 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
387 // this is a workable approximation
388 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000389 VG_(valgrind_base) = PGROUNDDN(&_start);
390 }
391
nethercote820bd8c2004-09-07 23:04:49 +0000392 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote31779c72004-07-30 21:50:15 +0000394 // This gives the client the largest possible address space while
395 // taking into account the tool's shadow needs.
396 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000397 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000398 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000399 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000400 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000401 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000402 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000403
nethercote31779c72004-07-30 21:50:15 +0000404 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000405 VG_(shadow_end) = VG_(valgrind_base);
406 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000407
nethercotee2097312004-06-27 12:29:56 +0000408#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
409
nethercote71980f02004-01-24 18:18:54 +0000410 if (0)
nethercotee2097312004-06-27 12:29:56 +0000411 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000412 "client_base %p (%dMB)\n"
413 "client_mapbase %p (%dMB)\n"
414 "client_end %p (%dMB)\n"
415 "shadow_base %p (%dMB)\n"
416 "shadow_end %p\n"
417 "valgrind_base %p (%dMB)\n"
418 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000419 VG_(client_base), SEGSIZE(client_base, client_mapbase),
420 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
421 VG_(client_end), SEGSIZE(client_end, shadow_base),
422 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000423 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000424 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
425 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000426 );
427
428#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000431 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000432 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000433 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000434
435 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000436 ires = munmap((void*)VG_(client_base), client_size);
437 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000438
439 // Map shadow memory.
440 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000441 if (shadow_size != 0) {
442 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000443 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000444 if ((void*)-1 == vres) {
445 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000446 "valgrind: Could not allocate address space (%p bytes)\n"
447 "valgrind: for shadow memory\n"
448 "valgrind: Possible causes:\n"
449 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
450 "valgrind: needs at least 1.5GB swap space.\n"
451 "valgrind: - Or, your virtual memory size may be limited (check\n"
452 "valgrind: with 'ulimit -v').\n"
453 "valgrind: - Or, your system may use a kernel that provides only a\n"
454 "valgrind: too-small (eg. 2GB) user address space.\n"
455 , (void*)shadow_size
456 );
nethercoted4722622004-08-30 19:36:42 +0000457 exit(1);
458 }
nethercotee567e702004-07-10 17:49:17 +0000459 }
nethercote71980f02004-01-24 18:18:54 +0000460}
461
462/*====================================================================*/
463/*=== Command line setup ===*/
464/*====================================================================*/
465
466/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
467static char* get_file_clo(char* dir)
468{
469# define FLEN 512
470 Int fd, n;
471 struct stat s1;
472 char* f_clo = NULL;
473 char filename[FLEN];
474
475 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
476 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
477 if ( fd > 0 ) {
478 if ( 0 == fstat(fd, &s1) ) {
479 f_clo = malloc(s1.st_size+1);
480 vg_assert(f_clo);
481 n = read(fd, f_clo, s1.st_size);
482 if (n == -1) n = 0;
483 f_clo[n] = '\0';
484 }
485 close(fd);
486 }
487 return f_clo;
488# undef FLEN
489}
490
491static Int count_args(char* s)
492{
493 Int n = 0;
494 if (s) {
495 char* cp = s;
496 while (True) {
497 // We have alternating sequences: blanks, non-blanks, blanks...
498 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000499 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000500 if ( !*cp ) break;
501 n++;
njn0c0f32a2005-03-26 04:14:01 +0000502 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000503 }
504 }
505 return n;
506}
507
508/* add args out of environment, skipping multiple spaces and -- args */
509static char** copy_args( char* s, char** to )
510{
511 if (s) {
512 char* cp = s;
513 while (True) {
514 // We have alternating sequences: blanks, non-blanks, blanks...
515 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000516 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000517 if ( !*cp ) break;
518 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000519 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000520 if ( *cp ) *cp++ = '\0'; // terminate if necessary
521 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
522 }
523 }
524 return to;
525}
526
527// Augment command line with arguments from environment and .valgrindrc
528// files.
529static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
530{
nethercotef6a1d502004-08-09 12:21:57 +0000531 int vg_argc0 = *vg_argc_inout;
532 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000533
534 char* env_clo = getenv(VALGRINDOPTS);
535 char* f1_clo = get_file_clo( getenv("HOME") );
536 char* f2_clo = get_file_clo(".");
537
538 /* copy any extra args from file or environment, if present */
539 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
540 /* ' ' separated extra options */
541 char **from;
542 char **to;
thughescaca0022004-09-13 10:20:34 +0000543 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
544
545 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
546
nethercote71980f02004-01-24 18:18:54 +0000547 env_arg_count = count_args(env_clo);
548 f1_arg_count = count_args(f1_clo);
549 f2_arg_count = count_args(f2_clo);
550
551 if (0)
552 printf("extra-argc=%d %d %d\n",
553 env_arg_count, f1_arg_count, f2_arg_count);
554
555 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000556 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000557 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000558 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000559 vg_assert(vg_argv0);
560 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000561
562 /* copy argv[0] */
563 *to++ = *from++;
564
565 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
566 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
567 * to override less local ones. */
568 to = copy_args(f1_clo, to);
569 to = copy_args(env_clo, to);
570 to = copy_args(f2_clo, to);
571
572 /* copy original arguments, stopping at command or -- */
573 while (*from) {
574 if (**from != '-')
575 break;
576 if (VG_STREQ(*from, "--")) {
577 from++; /* skip -- */
578 break;
579 }
580 *to++ = *from++;
581 }
582
583 /* add -- */
584 *to++ = "--";
585
nethercotef6a1d502004-08-09 12:21:57 +0000586 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000587
588 /* copy rest of original command line, then NULL */
589 while (*from) *to++ = *from++;
590 *to = NULL;
591 }
592
nethercotef6a1d502004-08-09 12:21:57 +0000593 *vg_argc_inout = vg_argc0;
594 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000595}
596
nethercotef6a1d502004-08-09 12:21:57 +0000597#define VG_CLO_SEP '\01'
598
nethercote71980f02004-01-24 18:18:54 +0000599static void get_command_line( int argc, char** argv,
600 Int* vg_argc_out, Char*** vg_argv_out,
601 char*** cl_argv_out )
602{
nethercotef6a1d502004-08-09 12:21:57 +0000603 int vg_argc0;
604 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000605 char** cl_argv;
606 char* env_clo = getenv(VALGRINDCLO);
607
608 if (env_clo != NULL && *env_clo != '\0') {
609 char *cp;
610 char **cpp;
611
nethercotef6a1d502004-08-09 12:21:57 +0000612 /* OK, VALGRINDCLO is set, which means we must be a child of another
613 Valgrind process using --trace-children, so we're getting all our
614 arguments from VALGRINDCLO, and the entire command line belongs to
615 the client (including argv[0]) */
616 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000617 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000618 if (*cp == VG_CLO_SEP)
619 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000620
nethercotef6a1d502004-08-09 12:21:57 +0000621 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
622 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000623
nethercotef6a1d502004-08-09 12:21:57 +0000624 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000625
626 *cpp++ = "valgrind"; /* nominal argv[0] */
627 *cpp++ = env_clo;
628
nethercotef6a1d502004-08-09 12:21:57 +0000629 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000630 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000631 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000632 *cp++ = '\0'; /* chop it up in place */
633 *cpp++ = cp;
634 }
635 }
636 *cpp = NULL;
637 cl_argv = argv;
638
639 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000640 Bool noaugment = False;
641
nethercote71980f02004-01-24 18:18:54 +0000642 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000643 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000644
nethercotef6a1d502004-08-09 12:21:57 +0000645 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000646 Char* arg = argv[vg_argc0];
647 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000648 break;
sewardjb5f6f512005-03-10 23:59:00 +0000649 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000650 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000651 break;
652 }
njn45270a22005-03-27 01:00:11 +0000653 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000654 }
nethercotef6a1d502004-08-09 12:21:57 +0000655 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000656
657 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000658 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000659 those extra args will already be present in VALGRINDCLO.
660 (We also don't do it when --command-line-only=yes.) */
661 if (!noaugment)
662 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000663 }
664
665 if (0) {
666 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000667 for (i = 0; i < vg_argc0; i++)
668 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000669 }
670
nethercotef6a1d502004-08-09 12:21:57 +0000671 *vg_argc_out = vg_argc0;
672 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000673 *cl_argv_out = cl_argv;
674}
675
676
677/*====================================================================*/
678/*=== Environment and stack setup ===*/
679/*====================================================================*/
680
681/* Scan a colon-separated list, and call a function on each element.
682 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000683 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000684 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000685
686 This routine will return True if (*func) returns True and False if
687 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000688*/
thughes4ad52d02004-06-27 17:37:21 +0000689static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000690{
691 char *cp, *entry;
692 int end;
693
694 if (colsep == NULL ||
695 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000696 return False;
nethercote71980f02004-01-24 18:18:54 +0000697
698 entry = cp = colsep;
699
700 do {
701 end = (*cp == '\0');
702
703 if (*cp == ':' || *cp == '\0') {
704 char save = *cp;
705
706 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000707 if ((*func)(entry)) {
708 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000709 return True;
thughes21942d92004-07-12 09:35:37 +0000710 }
nethercote71980f02004-01-24 18:18:54 +0000711 *cp = save;
712 entry = cp+1;
713 }
714 cp++;
715 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000716
717 return False;
718}
719
nethercote71980f02004-01-24 18:18:54 +0000720/* Prepare the client's environment. This is basically a copy of our
721 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000722 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000723
sewardjb5f6f512005-03-10 23:59:00 +0000724 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000725
726 Yummy. String hacking in C.
727
728 If this needs to handle any more variables it should be hacked
729 into something table driven.
730 */
731static char **fix_environment(char **origenv, const char *preload)
732{
733 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000734 static const char ld_preload[] = "LD_PRELOAD=";
735 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000736 static const int ld_preload_len = sizeof(ld_preload)-1;
737 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
738 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000739 char *inject_path;
740 int inject_path_len;
741 int vgliblen = strlen(VG_(libdir));
742 char **cpp;
743 char **ret;
744 int envc;
745 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
746
747 /* Find the vg_inject.so; also make room for the tool preload
748 library */
749 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
750 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000751 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000752
753 if (preload)
754 snprintf(inject_path, inject_path_len, "%s/%s:%s",
755 VG_(libdir), inject_so, preload);
756 else
757 snprintf(inject_path, inject_path_len, "%s/%s",
758 VG_(libdir), inject_so);
759
760 /* Count the original size of the env */
761 envc = 0; /* trailing NULL */
762 for (cpp = origenv; cpp && *cpp; cpp++)
763 envc++;
764
765 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000766 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000767 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000768
769 /* copy it over */
770 for (cpp = ret; *origenv; )
771 *cpp++ = *origenv++;
772 *cpp = NULL;
773
774 vg_assert(envc == (cpp - ret));
775
776 /* Walk over the new environment, mashing as we go */
777 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000778 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000779 int len = strlen(*cpp) + inject_path_len;
780 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000781 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000782
783 snprintf(cp, len, "%s%s:%s",
784 ld_preload, inject_path, (*cpp)+ld_preload_len);
785
786 *cpp = cp;
787
788 ld_preload_done = 1;
789 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
790 *cpp = "";
791 }
792 }
793
794 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000795 if (!ld_preload_done) {
796 int len = ld_preload_len + inject_path_len;
797 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000798 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000799
800 snprintf(cp, len, "%s%s",
801 ld_preload, inject_path);
802
803 ret[envc++] = cp;
804 }
805
sewardjb5f6f512005-03-10 23:59:00 +0000806 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000807 ret[envc] = NULL;
808
809 return ret;
810}
811
812extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000813
814/* Add a string onto the string table, and return its address */
815static char *copy_str(char **tab, const char *str)
816{
817 char *cp = *tab;
818 char *orig = cp;
819
820 while(*str)
821 *cp++ = *str++;
822 *cp++ = '\0';
823
824 if (0)
nethercote545fe672004-11-01 16:52:43 +0000825 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000826
827 *tab = cp;
828
829 return orig;
830}
831
832/*
833 This sets up the client's initial stack, containing the args,
834 environment and aux vector.
835
836 The format of the stack is:
837
838 higher address +-----------------+
839 | Trampoline code |
840 +-----------------+
841 | |
842 : string table :
843 | |
844 +-----------------+
845 | AT_NULL |
846 - -
847 | auxv |
848 +-----------------+
849 | NULL |
850 - -
851 | envp |
852 +-----------------+
853 | NULL |
854 - -
855 | argv |
856 +-----------------+
857 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000858 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000859 | undefined |
860 : :
861 */
nethercotec25c4492004-10-18 11:52:17 +0000862static Addr setup_client_stack(void* init_sp,
863 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000864 const struct exeinfo *info,
865 UInt** client_auxv)
866{
nethercotee567e702004-07-10 17:49:17 +0000867 void* res;
nethercote71980f02004-01-24 18:18:54 +0000868 char **cpp;
869 char *strtab; /* string table */
870 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000871 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000872 struct ume_auxv *auxv;
873 const struct ume_auxv *orig_auxv;
874 const struct ume_auxv *cauxv;
875 unsigned stringsize; /* total size of strings in bytes */
876 unsigned auxsize; /* total size of auxv in bytes */
877 int argc; /* total argc */
878 int envc; /* total number of env vars */
879 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000880 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000881
882 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000883 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000884
885 /* ==================== compute sizes ==================== */
886
887 /* first of all, work out how big the client stack will be */
888 stringsize = 0;
889
890 /* paste on the extra args if the loader needs them (ie, the #!
891 interpreter and its argument) */
892 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000893 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000894 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000895 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000896 }
nethercoted6a56872004-07-26 15:32:47 +0000897 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000898 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000899 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000900 }
901
902 /* now scan the args we're given... */
903 for (cpp = orig_argv; *cpp; cpp++) {
904 argc++;
905 stringsize += strlen(*cpp) + 1;
906 }
907
908 /* ...and the environment */
909 envc = 0;
910 for (cpp = orig_envp; cpp && *cpp; cpp++) {
911 envc++;
912 stringsize += strlen(*cpp) + 1;
913 }
914
915 /* now, how big is the auxv? */
916 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
917 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
918 if (cauxv->a_type == AT_PLATFORM)
919 stringsize += strlen(cauxv->u.a_ptr) + 1;
920 auxsize += sizeof(*cauxv);
921 }
922
923 /* OK, now we know how big the client stack is */
924 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000925 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000926 sizeof(char **)*argc + /* argv */
927 sizeof(char **) + /* terminal NULL */
928 sizeof(char **)*envc + /* envp */
929 sizeof(char **) + /* terminal NULL */
930 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000931 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000932 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000933
sewardj79048ce2005-02-18 08:28:32 +0000934 if (0) VG_(printf)("stacksize = %d\n", stacksize);
935
nethercotef84f6952004-07-15 14:58:33 +0000936 // decide where stack goes!
937 VG_(clstk_end) = VG_(client_end);
938
nethercote73b526f2004-10-31 18:48:21 +0000939 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000940
nethercote71980f02004-01-24 18:18:54 +0000941 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000942 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000943 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
944
nethercote71980f02004-01-24 18:18:54 +0000945 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000946 stringbase = strtab = (char *)(VG_(client_trampoline_code)
947 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000948
949 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000950
sewardj79048ce2005-02-18 08:28:32 +0000951 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000952 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000953 "clstk_base %p\n"
954 "clstk_end %p\n",
955 stringsize, auxsize, stacksize,
956 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000957
nethercote71980f02004-01-24 18:18:54 +0000958 /* ==================== allocate space ==================== */
959
960 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000961 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000962 PROT_READ | PROT_WRITE | PROT_EXEC,
963 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
964 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000965
966 /* ==================== copy client stack ==================== */
967
nethercotea3c3cf22004-11-01 18:38:00 +0000968 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000969
970 /* --- argc --- */
971 *ptr++ = argc; /* client argc */
972
973 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000974 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000975 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000976 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000977 }
nethercoted6a56872004-07-26 15:32:47 +0000978 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000979 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000980 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000981 }
982 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000983 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000984 }
985 *ptr++ = 0;
986
987 /* --- envp --- */
988 VG_(client_envp) = (Char **)ptr;
989 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000990 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000991 *ptr++ = 0;
992
993 /* --- auxv --- */
994 auxv = (struct ume_auxv *)ptr;
995 *client_auxv = (UInt *)auxv;
996
997 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
998 /* copy the entry... */
999 *auxv = *orig_auxv;
1000
1001 /* ...and fix up the copy */
1002 switch(auxv->a_type) {
1003 case AT_PHDR:
1004 if (info->phdr == 0)
1005 auxv->a_type = AT_IGNORE;
1006 else
1007 auxv->u.a_val = info->phdr;
1008 break;
1009
1010 case AT_PHNUM:
1011 if (info->phdr == 0)
1012 auxv->a_type = AT_IGNORE;
1013 else
1014 auxv->u.a_val = info->phnum;
1015 break;
1016
1017 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001018 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001019 break;
1020
1021 case AT_PLATFORM: /* points to a platform description string */
1022 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1023 break;
1024
1025 case AT_ENTRY:
1026 auxv->u.a_val = info->entry;
1027 break;
1028
1029 case AT_IGNORE:
1030 case AT_EXECFD:
1031 case AT_PHENT:
1032 case AT_PAGESZ:
1033 case AT_FLAGS:
1034 case AT_NOTELF:
1035 case AT_UID:
1036 case AT_EUID:
1037 case AT_GID:
1038 case AT_EGID:
1039 case AT_CLKTCK:
1040 case AT_HWCAP:
1041 case AT_FPUCW:
1042 case AT_DCACHEBSIZE:
1043 case AT_ICACHEBSIZE:
1044 case AT_UCACHEBSIZE:
1045 /* All these are pointerless, so we don't need to do anything
1046 about them. */
1047 break;
1048
1049 case AT_SECURE:
1050 /* If this is 1, then it means that this program is running
1051 suid, and therefore the dynamic linker should be careful
1052 about LD_PRELOAD, etc. However, since stage1 (the thing
1053 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001054 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001055 set AT_SECURE to 0. */
1056 auxv->u.a_val = 0;
1057 break;
1058
1059 case AT_SYSINFO:
1060 /* Leave this unmolested for now, but we'll update it later
1061 when we set up the client trampoline code page */
1062 break;
1063
1064 case AT_SYSINFO_EHDR:
1065 /* Trash this, because we don't reproduce it */
1066 auxv->a_type = AT_IGNORE;
1067 break;
1068
1069 default:
1070 /* stomp out anything we don't know about */
1071 if (0)
nethercote545fe672004-11-01 16:52:43 +00001072 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001073 auxv->a_type = AT_IGNORE;
1074 break;
1075
1076 }
1077 }
1078 *auxv = *orig_auxv;
1079 vg_assert(auxv->a_type == AT_NULL);
1080
njnc6168192004-11-29 13:54:10 +00001081// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1082// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001083#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001084 /* --- trampoline page --- */
1085 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1086 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001087#endif
nethercotef84f6952004-07-15 14:58:33 +00001088
nethercote71980f02004-01-24 18:18:54 +00001089 vg_assert((strtab-stringbase) == stringsize);
1090
nethercote5ee67ca2004-06-22 14:00:09 +00001091 /* We know the initial ESP is pointing at argc/argv */
1092 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001093 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001094
sewardj79048ce2005-02-18 08:28:32 +00001095 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001096 return cl_esp;
1097}
1098
1099/*====================================================================*/
1100/*=== Find executable ===*/
1101/*====================================================================*/
1102
thughes4ad52d02004-06-27 17:37:21 +00001103static const char* executable_name;
1104
1105static Bool match_executable(const char *entry) {
1106 char buf[strlen(entry) + strlen(executable_name) + 2];
1107
1108 /* empty PATH element means . */
1109 if (*entry == '\0')
1110 entry = ".";
1111
1112 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1113
1114 if (access(buf, R_OK|X_OK) == 0) {
1115 executable_name = strdup(buf);
1116 vg_assert(NULL != executable_name);
1117 return True;
1118 }
1119 return False;
1120}
1121
nethercote71980f02004-01-24 18:18:54 +00001122static const char* find_executable(const char* exec)
1123{
1124 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001125 executable_name = exec;
1126 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001127 /* no '/' - we need to search the path */
1128 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001129 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001130 }
thughes4ad52d02004-06-27 17:37:21 +00001131 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001132}
1133
1134
1135/*====================================================================*/
1136/*=== Loading tools ===*/
1137/*====================================================================*/
1138
1139static void list_tools(void)
1140{
1141 DIR *dir = opendir(VG_(libdir));
1142 struct dirent *de;
1143 int first = 1;
1144
1145 if (dir == NULL) {
1146 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001147 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001148 return;
1149 }
1150
nethercotef4928da2004-06-15 10:54:40 +00001151 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001152 int len = strlen(de->d_name);
1153
njn063c5402004-11-22 16:58:05 +00001154 /* look for vgtool_TOOL.so names */
1155 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1156 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001157 VG_STREQ(de->d_name + len - 3, ".so")) {
1158 if (first) {
1159 fprintf(stderr, "Available tools:\n");
1160 first = 0;
1161 }
1162 de->d_name[len-3] = '\0';
1163 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001164 }
1165 }
1166
1167 closedir(dir);
1168
1169 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001170 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1171 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001172}
1173
1174
1175/* Find and load a tool, and check it looks ok. Also looks to see if there's
1176 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001177static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001178 ToolInfo** toolinfo_out, char **preloadpath_out )
1179{
1180 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001181 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001182 char buf[len];
1183 void* handle;
1184 ToolInfo* toolinfo;
1185 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001186
1187 // XXX: allowing full paths for --tool option -- does it make sense?
1188 // Doesn't allow for vgpreload_<tool>.so.
1189
1190 if (strchr(toolname, '/') != 0) {
1191 /* toolname contains '/', and so must be a pathname */
1192 handle = dlopen(toolname, RTLD_NOW);
1193 } else {
1194 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001195 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001196 handle = dlopen(buf, RTLD_NOW);
1197
1198 if (handle != NULL) {
1199 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1200 if (access(buf, R_OK) == 0) {
1201 preloadpath = strdup(buf);
1202 vg_assert(NULL != preloadpath);
1203 }
1204 }
1205 }
1206
1207 ok = (NULL != handle);
1208 if (!ok) {
1209 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1210 goto bad_load;
1211 }
1212
njn26f02512004-11-22 18:33:15 +00001213 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001214 ok = (NULL != toolinfo);
1215 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001216 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001217 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1218 goto bad_load;
1219 }
1220
1221 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1222 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001223 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001224 if (!ok) {
1225 fprintf(stderr, "Error:\n"
1226 " Tool and core interface versions do not match.\n"
1227 " Interface version used by core is: %d.%d (size %d)\n"
1228 " Interface version used by tool is: %d.%d (size %d)\n"
1229 " The major version numbers must match.\n",
1230 VG_CORE_INTERFACE_MAJOR_VERSION,
1231 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001232 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001233 toolinfo->interface_major_version,
1234 toolinfo->interface_minor_version,
1235 toolinfo->sizeof_ToolInfo);
1236 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1237 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001238 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001239 else
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 goto bad_load;
1242 }
1243
njn8a97c6d2005-03-31 04:37:24 +00001244 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001245 *toolinfo_out = toolinfo;
1246 *preloadpath_out = preloadpath;
1247 return;
1248
1249
1250 bad_load:
1251 if (handle != NULL)
1252 dlclose(handle);
1253
nethercotef4928da2004-06-15 10:54:40 +00001254 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001255 list_tools();
1256 exit(127);
1257}
1258
nethercotef4928da2004-06-15 10:54:40 +00001259
1260/*====================================================================*/
1261/*=== Command line errors ===*/
1262/*====================================================================*/
1263
1264static void abort_msg ( void )
1265{
nethercotef8548672004-06-21 12:42:35 +00001266 VG_(clo_log_to) = VgLogTo_Fd;
1267 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001268}
1269
1270void VG_(bad_option) ( Char* opt )
1271{
1272 abort_msg();
1273 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1274 VG_(printf)("valgrind: Use --help for more information.\n");
1275 VG_(exit)(1);
1276}
1277
nethercotef4928da2004-06-15 10:54:40 +00001278static void missing_prog ( void )
1279{
1280 abort_msg();
1281 VG_(printf)("valgrind: no program specified\n");
1282 VG_(printf)("valgrind: Use --help for more information.\n");
1283 VG_(exit)(1);
1284}
1285
1286static void config_error ( Char* msg )
1287{
1288 abort_msg();
1289 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1290 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1291 VG_(exit)(1);
1292}
1293
1294
nethercote71980f02004-01-24 18:18:54 +00001295/*====================================================================*/
1296/*=== Loading the client ===*/
1297/*====================================================================*/
1298
nethercotef4928da2004-06-15 10:54:40 +00001299static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001300 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1301{
1302 // If they didn't specify an executable with --exec, and didn't specify
1303 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001304 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001305 if (cl_argv[0] == NULL ||
1306 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1307 {
nethercotef4928da2004-06-15 10:54:40 +00001308 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001309 }
1310 }
1311
1312 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001313 info->exe_base = VG_(client_base);
1314 info->exe_end = VG_(client_end);
1315 info->argv = cl_argv;
1316
nethercotef4928da2004-06-15 10:54:40 +00001317 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001318 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001319 // Totally zero 'info' before continuing.
1320 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001321 } else {
1322 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001323 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001324 ret = do_exec(exec, info);
1325 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001326 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1327 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001328 exit(127);
1329 }
1330 }
1331
1332 /* Copy necessary bits of 'info' that were filled in */
1333 *client_eip = info->init_eip;
1334 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1335}
1336
nethercote969ecf12004-10-13 17:29:01 +00001337/*====================================================================*/
1338/*=== Address space unpadding ===*/
1339/*====================================================================*/
1340
1341typedef struct {
1342 char* killpad_start;
1343 char* killpad_end;
1344 struct stat* killpad_padstat;
1345} killpad_extra;
1346
1347static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1348 int maj, int min, int ino, void* ex)
1349{
1350 killpad_extra* extra = ex;
1351 void *b, *e;
1352 int res;
1353
1354 vg_assert(NULL != extra->killpad_padstat);
1355
1356 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1357 extra->killpad_padstat->st_ino != ino)
1358 return 1;
1359
1360 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1361 return 1;
1362
1363 if (segstart <= extra->killpad_start)
1364 b = extra->killpad_start;
1365 else
1366 b = segstart;
1367
1368 if (segend >= extra->killpad_end)
1369 e = extra->killpad_end;
1370 else
1371 e = segend;
1372
1373 res = munmap(b, (char *)e-(char *)b);
1374 vg_assert(0 == res);
1375
1376 return 1;
1377}
1378
1379// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001380static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001381{
1382 static struct stat padstat;
1383 killpad_extra extra;
1384 int res;
1385
sewardjb5f6f512005-03-10 23:59:00 +00001386 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001387
1388 res = fstat(padfile, &padstat);
1389 vg_assert(0 == res);
1390 extra.killpad_padstat = &padstat;
1391 extra.killpad_start = start;
1392 extra.killpad_end = end;
1393 foreach_map(killpad, &extra);
1394}
1395
sewardj2c5ffbe2005-03-12 13:32:06 +00001396static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001397{
1398 int res = close(padfile);
1399 vg_assert(0 == res);
1400}
1401
nethercote71980f02004-01-24 18:18:54 +00001402
1403/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001404/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001405/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001406
njn25e49d8e72002-09-23 09:36:25 +00001407/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001408VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001409Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001410Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001411Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001412Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001413Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001414Int VG_(clo_verbosity) = 1;
1415Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001416Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001417
nethercotef1e5e152004-09-01 23:58:16 +00001418/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001419 fd is initially stdout, for --help, but gets moved to stderr by default
1420 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001421VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001422Int VG_(clo_log_fd) = 1;
1423Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001424
thughes6233a382004-08-21 11:10:44 +00001425Bool VG_(clo_time_stamp) = False;
1426
sewardj6024b212003-07-13 10:54:33 +00001427Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001428Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001429Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001430Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001431UChar VG_(clo_trace_flags) = 0; // 00000000b
1432UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001433Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001434Bool VG_(clo_trace_syscalls) = False;
1435Bool VG_(clo_trace_signals) = False;
1436Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001437Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001438Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001439Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001440Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001441Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001442Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001443Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001444Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001445Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001446Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001447Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001448Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001449Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001450Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001451Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001452
jsgf855d93d2003-10-13 22:26:55 +00001453static Bool VG_(clo_wait_for_gdb) = False;
1454
sewardjde4a1d02002-03-22 01:27:54 +00001455
sewardj2c5ffbe2005-03-12 13:32:06 +00001456static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001457{
njn25e49d8e72002-09-23 09:36:25 +00001458 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001459"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001460"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001461" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001462" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001463" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001464" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001465" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001466" -q --quiet run silently; only print error msgs\n"
1467" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001468" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001469" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001470" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001471"\n"
1472" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001473" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001474" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001475" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001476" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001477" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001478"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001479" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001480" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1481" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001482" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001483" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001484" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001485" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001486" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1487" --show-below-main=no|yes continue stack traces below main() [no]\n"
1488" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001489" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001490" --db-attach=no|yes start debugger when errors detected? [no]\n"
1491" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1492" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001493" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1494" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001495"\n";
njn7cf0bd32002-06-08 13:36:03 +00001496
njn25e49d8e72002-09-23 09:36:25 +00001497 Char* usage2 =
1498"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001499" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001500" --sanity-level=<number> level of sanity checking to do [1]\n"
1501" --single-step=no|yes translate each instr separately? [no]\n"
1502" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001503" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001504" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001505" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1506" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001507" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001508" --trace-syscalls=no|yes show all system calls? [no]\n"
1509" --trace-signals=no|yes show signal handling details? [no]\n"
1510" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001511" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001512" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001513#if 0
1514" --model-pthreads=yes|no model the pthreads library [no]\n"
1515#endif
1516" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001517"\n"
1518" --vex-iropt-verbosity 0 .. 9 [0]\n"
1519" --vex-iropt-level 0 .. 2 [2]\n"
1520" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001521" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1522" --vex-guest-max-insns 1 .. 100 [50]\n"
1523" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1524"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001525" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001526" 1000 0000 show conversion into IR\n"
1527" 0100 0000 show after initial opt\n"
1528" 0010 0000 show after instrumentation\n"
1529" 0001 0000 show after second opt\n"
1530" 0000 1000 show after tree building\n"
1531" 0000 0100 show selecting insns\n"
1532" 0000 0010 show after reg-alloc\n"
1533" 0000 0001 show final assembly\n"
1534"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001535" debugging options for Valgrind tools that report errors\n"
1536" --dump-error=<number> show translation for basic block associated\n"
1537" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001538"\n";
njn3e884182003-04-15 13:03:23 +00001539
1540 Char* usage3 =
1541"\n"
nethercote71980f02004-01-24 18:18:54 +00001542" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n"
njn53612422005-03-12 16:22:54 +00001544" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001545" and licensed under the GNU General Public License, version 2.\n"
1546" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001547"\n"
nethercote137bc552003-11-14 17:47:54 +00001548" Tools are copyright and licensed by their authors. See each\n"
1549" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001550"\n";
njn7cf0bd32002-06-08 13:36:03 +00001551
fitzhardinge98abfc72003-12-16 02:05:15 +00001552 VG_(printf)(usage1);
1553 if (VG_(details).name) {
1554 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001555 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001556 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001557 else
1558 VG_(printf)(" (none)\n");
1559 }
nethercote6c999f22004-01-31 22:55:15 +00001560 if (debug_help) {
1561 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001562
nethercote6c999f22004-01-31 22:55:15 +00001563 if (VG_(details).name) {
1564 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1565
1566 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001567 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001568 else
1569 VG_(printf)(" (none)\n");
1570 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001571 }
nethercote421281e2003-11-20 16:20:55 +00001572 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001573 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001574}
sewardjde4a1d02002-03-22 01:27:54 +00001575
nethercote71980f02004-01-24 18:18:54 +00001576static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001577 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001578{
nethercote71980f02004-01-24 18:18:54 +00001579 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001580
sewardj8b635a42004-11-22 19:01:47 +00001581 LibVEX_default_VexControl(& VG_(clo_vex_control));
1582
nethercote71980f02004-01-24 18:18:54 +00001583 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001584 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001585
nethercotef6a1d502004-08-09 12:21:57 +00001586 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001587 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001588 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001589
nethercotef6a1d502004-08-09 12:21:57 +00001590 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1591 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001592 *need_help = 1;
1593
nethercotef6a1d502004-08-09 12:21:57 +00001594 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001595 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001596
nethercotef6c99d72004-11-09 14:35:43 +00001597 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001598 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001599
nethercotef6a1d502004-08-09 12:21:57 +00001600 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1601 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001602 }
1603 }
nethercote71980f02004-01-24 18:18:54 +00001604}
1605
nethercote5ee67ca2004-06-22 14:00:09 +00001606static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001607{
nethercotef8548672004-06-21 12:42:35 +00001608 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001609 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001610
nethercotee1730692003-11-20 10:38:07 +00001611 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001612 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001613
sewardj19d81412002-06-03 01:10:40 +00001614 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001615 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001616 config_error("Please use absolute paths in "
1617 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001618
njnc6168192004-11-29 13:54:10 +00001619// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001620#ifdef __x86__
1621 {
sewardjb5f6f512005-03-10 23:59:00 +00001622 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001623 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1624 switch(auxp[0]) {
1625 case AT_SYSINFO:
1626 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1627 break;
1628 }
1629 }
1630 }
1631#endif
sewardjde4a1d02002-03-22 01:27:54 +00001632
nethercotef6a1d502004-08-09 12:21:57 +00001633 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001636 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001637
thughes3bfd5a02004-07-18 08:05:44 +00001638 /* Look for a colon in the switch name */
1639 while (*colon && *colon != ':' && *colon != '=')
1640 colon++;
nethercote71980f02004-01-24 18:18:54 +00001641
1642 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001643 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001644 if (VG_CLO_STREQN(2, arg, "--") &&
1645 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1646 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1647 {
1648 // prefix matches, convert "--toolname:foo" to "--foo"
1649 if (0)
1650 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001651 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001652 arg[0] = '-';
1653 arg[1] = '-';
1654
1655 } else {
1656 // prefix doesn't match, skip to next arg
1657 continue;
1658 }
1659 }
1660
fitzhardinge98abfc72003-12-16 02:05:15 +00001661 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001662 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1663 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1664 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001665
njn45270a22005-03-27 01:00:11 +00001666 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001667
nethercote71980f02004-01-24 18:18:54 +00001668 else if (VG_CLO_STREQ(arg, "-v") ||
1669 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001670 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001671
nethercote71980f02004-01-24 18:18:54 +00001672 else if (VG_CLO_STREQ(arg, "-q") ||
1673 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001674 VG_(clo_verbosity)--;
1675
sewardj1cf558c2005-04-25 01:36:56 +00001676 else if (VG_CLO_STREQ(arg, "-d")) {
1677 /* do nothing */
1678 }
1679
njn45270a22005-03-27 01:00:11 +00001680 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1681 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1682 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1683 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1684 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1685 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1686 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001687 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001688 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1689 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1690 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1691 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1692 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1693 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1694 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1695 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1696 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
1697 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1698 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1699 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1700 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1701 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001702
njn45270a22005-03-27 01:00:11 +00001703 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1704 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001705
njn45270a22005-03-27 01:00:11 +00001706 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1707 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1708 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1709 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1710 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001711
njn45270a22005-03-27 01:00:11 +00001712 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001713 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001714 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001715 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001716 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001717 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001718 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001719 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001720 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001721 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001722 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001723 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1724
nethercotef8548672004-06-21 12:42:35 +00001725 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1726 VG_(clo_log_to) = VgLogTo_Fd;
1727 VG_(clo_log_name) = NULL;
1728 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001729 }
1730
nethercotef8548672004-06-21 12:42:35 +00001731 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1732 VG_(clo_log_to) = VgLogTo_File;
1733 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001734 }
njnd6bc3c32005-03-27 00:44:31 +00001735
sewardj603d4102005-01-11 14:01:02 +00001736 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1737 VG_(clo_log_to) = VgLogTo_FileExactly;
1738 VG_(clo_log_name) = &arg[19];
1739 }
sewardjde4a1d02002-03-22 01:27:54 +00001740
nethercotef8548672004-06-21 12:42:35 +00001741 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1742 VG_(clo_log_to) = VgLogTo_Socket;
1743 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001744 }
1745
nethercote71980f02004-01-24 18:18:54 +00001746 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001747 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001748 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001749 VG_(message)(Vg_UserMsg,
1750 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001751 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001752 }
nethercote71980f02004-01-24 18:18:54 +00001753 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001754 VG_(clo_n_suppressions)++;
1755 }
sewardjde4a1d02002-03-22 01:27:54 +00001756
sewardjfa8ec112005-01-19 11:55:34 +00001757 /* "stuvwxyz" --> stuvwxyz (binary) */
1758 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1759 Int j;
1760 char* opt = & arg[14];
1761
1762 if (8 != VG_(strlen)(opt)) {
1763 VG_(message)(Vg_UserMsg,
1764 "--trace-flags argument must have 8 digits");
1765 VG_(bad_option)(arg);
1766 }
1767 for (j = 0; j < 8; j++) {
1768 if ('0' == opt[j]) { /* do nothing */ }
1769 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1770 else {
1771 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1772 "contain 0s and 1s");
1773 VG_(bad_option)(arg);
1774 }
1775 }
1776 }
1777
1778 /* "stuvwxyz" --> stuvwxyz (binary) */
1779 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001780 Int j;
nethercote71980f02004-01-24 18:18:54 +00001781 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001782
sewardj2a99cf62004-11-24 10:44:19 +00001783 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001784 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001785 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001786 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001787 }
sewardj8b635a42004-11-22 19:01:47 +00001788 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001789 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001790 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001791 else {
sewardjfa8ec112005-01-19 11:55:34 +00001792 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001793 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001794 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001795 }
1796 }
1797 }
sewardjde4a1d02002-03-22 01:27:54 +00001798
njn45270a22005-03-27 01:00:11 +00001799 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001800
sewardjd153fae2005-01-10 17:24:47 +00001801 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1802 VG_(clo_gen_suppressions) = 0;
1803 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1804 VG_(clo_gen_suppressions) = 1;
1805 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1806 VG_(clo_gen_suppressions) = 2;
1807
nethercote71980f02004-01-24 18:18:54 +00001808 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001809 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001810 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001811 }
njn8c0b3bb2005-03-12 21:20:39 +00001812 skip_arg:
1813 if (arg != vg_argv[i])
1814 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001815 }
1816
sewardj998d40d2004-12-06 14:24:52 +00001817 /* Make VEX control parameters sane */
1818
1819 if (VG_(clo_vex_control).guest_chase_thresh
1820 >= VG_(clo_vex_control).guest_max_insns)
1821 VG_(clo_vex_control).guest_chase_thresh
1822 = VG_(clo_vex_control).guest_max_insns - 1;
1823
1824 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1825 VG_(clo_vex_control).guest_chase_thresh = 0;
1826
1827 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001828
njnf9ebf672003-05-12 21:41:30 +00001829 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001830 VG_(clo_verbosity) = 0;
1831
nethercote04d0fbc2004-01-26 16:48:06 +00001832 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001833 VG_(message)(Vg_UserMsg, "");
1834 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001835 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(message)(Vg_UserMsg,
1837 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001838 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001839 }
1840
nethercotef8548672004-06-21 12:42:35 +00001841 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001842 should be connected to whatever sink has been selected, and we
1843 indiscriminately chuck stuff into it without worrying what the
1844 nature of it is. Oh the wonder of Unix streams. */
1845
nethercotee1730692003-11-20 10:38:07 +00001846 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001847 the terminal any problems to do with processing command line
1848 opts. */
nethercotef8548672004-06-21 12:42:35 +00001849 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001850 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001851
1852 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001853
sewardj4cf05692002-10-27 20:28:29 +00001854 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001855 vg_assert(VG_(clo_log_name) == NULL);
1856 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001857 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001858
sewardj4cf05692002-10-27 20:28:29 +00001859 case VgLogTo_File: {
1860 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001861 Int seq = 0;
1862 Int pid = VG_(getpid)();
1863
nethercotef8548672004-06-21 12:42:35 +00001864 vg_assert(VG_(clo_log_name) != NULL);
1865 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001866
nethercote71980f02004-01-24 18:18:54 +00001867 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001868 if (seq == 0)
1869 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001870 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001871 else
1872 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001873 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001874 seq++;
1875
nethercotef8548672004-06-21 12:42:35 +00001876 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001877 = VG_(open)(logfilename,
1878 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1879 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001880 if (eventually_log_fd >= 0) {
1881 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001882 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001883 } else {
nethercotef8548672004-06-21 12:42:35 +00001884 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001885 VG_(message)(Vg_UserMsg,
1886 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001887 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001888 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001889 "--log-file=<file> (didn't work out for some reason.)");
1890 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001891 }
1892 }
1893 }
sewardj603d4102005-01-11 14:01:02 +00001894 break; /* switch (VG_(clo_log_to)) */
1895 }
1896
1897 case VgLogTo_FileExactly: {
1898 Char logfilename[1000];
1899
1900 vg_assert(VG_(clo_log_name) != NULL);
1901 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1902 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1903
1904 eventually_log_fd
1905 = VG_(open)(logfilename,
1906 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1907 VKI_S_IRUSR|VKI_S_IWUSR);
1908 if (eventually_log_fd >= 0) {
1909 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1910 }
1911 else if (eventually_log_fd != -VKI_EEXIST) {
1912 VG_(message)(Vg_UserMsg,
1913 "Can't create/open log file `%s'; giving up!",
1914 VG_(clo_log_name));
1915 VG_(bad_option)(
1916 "--log-file-exactly=<file> (didn't work out for some reason.)");
1917 /*NOTREACHED*/
1918 }
1919 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001920 }
1921
1922 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001923 vg_assert(VG_(clo_log_name) != NULL);
1924 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1925 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1926 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001927 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001928 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001929 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001930 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001931 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001932 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001933 }
nethercotef8548672004-06-21 12:42:35 +00001934 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001935 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001936 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001937 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001938 VG_(message)(Vg_UserMsg,
1939 "Log messages will sent to stderr instead." );
1940 VG_(message)(Vg_UserMsg,
1941 "" );
1942 /* We don't change anything here. */
1943 } else {
nethercotef8548672004-06-21 12:42:35 +00001944 vg_assert(eventually_log_fd > 0);
1945 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001946 VG_(logging_to_filedes) = False;
1947 }
sewardj73cf3bc2002-11-03 03:20:15 +00001948 break;
1949 }
1950
sewardj4cf05692002-10-27 20:28:29 +00001951 }
1952
nethercotef8548672004-06-21 12:42:35 +00001953 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001954 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001955 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001956 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1957 else {
nethercotef8548672004-06-21 12:42:35 +00001958 VG_(clo_log_fd) = eventually_log_fd;
1959 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001960 }
1961
sewardj4cf05692002-10-27 20:28:29 +00001962 /* Ok, the logging sink is running now. Print a suitable preamble.
1963 If logging to file or a socket, write details of parent PID and
1964 command line args, to help people trying to interpret the
1965 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001966
sewardj83adf412002-05-01 01:25:45 +00001967 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001968 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001969 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001970 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001971 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001972 NULL == VG_(details).version
1973 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001974 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001975 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001976
njnd04b7c62002-10-03 14:05:52 +00001977 /* Core details */
1978 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001979 "Using LibVEX rev %s, a library for dynamic binary translation.",
1980 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001981 VG_(message)(Vg_UserMsg,
1982 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1983 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001984 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001985 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001986 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001987 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001988 }
1989
nethercotec1e395d2003-11-10 13:26:49 +00001990 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001991 VG_(message)(Vg_UserMsg, "");
1992 VG_(message)(Vg_UserMsg,
1993 "My PID = %d, parent PID = %d. Prog and args are:",
1994 VG_(getpid)(), VG_(getppid)() );
1995 for (i = 0; i < VG_(client_argc); i++)
1996 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1997 }
1998
sewardjde4a1d02002-03-22 01:27:54 +00001999 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002000 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002001 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002002 VG_(message)(Vg_DebugMsg, "");
2003 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2004 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002005 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002006 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002007
njn1fd5eb22005-03-13 05:43:23 +00002008 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002009 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002010 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002011 }
nethercotea70f7352004-04-18 12:08:46 +00002012
njn1fd5eb22005-03-13 05:43:23 +00002013 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002014 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2015 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002016 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002017 } else {
2018 #define BUF_LEN 256
2019 Char version_buf[BUF_LEN];
2020 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2021 vg_assert(n <= 256);
2022 if (n > 0) {
2023 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002024 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002025 } else {
njn1fd5eb22005-03-13 05:43:23 +00002026 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002027 }
2028 VG_(close)(fd);
2029 #undef BUF_LEN
2030 }
sewardjde4a1d02002-03-22 01:27:54 +00002031 }
2032
fitzhardinge98abfc72003-12-16 02:05:15 +00002033 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002034 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002035 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002036 needs one, load the default */
2037 static const Char default_supp[] = "default.supp";
2038 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2039 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2040 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2041 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2042 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002043 }
sewardj4cf05692002-10-27 20:28:29 +00002044
sewardjd153fae2005-01-10 17:24:47 +00002045 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002046 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002047 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002048 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002049 VG_(message)(Vg_UserMsg,
2050 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002051 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002052 }
sewardjde4a1d02002-03-22 01:27:54 +00002053}
2054
nethercotef6a1d502004-08-09 12:21:57 +00002055// Build the string for VALGRINDCLO.
2056Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2057{
2058 /* If we're tracing the children, then we need to start it
2059 with our starter+arguments, which are copied into VALGRINDCLO,
2060 except the --exec= option is changed if present.
2061 */
2062 Int i;
2063 Char *exec;
2064 Char *cp;
2065 Char *optvar;
2066 Int optlen, execlen;
2067
2068 // All these allocated blocks are not free - because we're either
2069 // going to exec, or panic when we fail.
2070
2071 // Create --exec= option: "--exec=<exename>"
2072 exec = VG_(arena_malloc)(VG_AR_CORE,
2073 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2074 vg_assert(NULL != exec);
2075 VG_(sprintf)(exec, "--exec=%s", exename);
2076
2077 // Allocate space for optvar (may overestimate by counting --exec twice,
2078 // no matter)
2079 optlen = 1;
2080 for (i = 0; i < vg_argc; i++)
2081 optlen += VG_(strlen)(vg_argv[i]) + 1;
2082 optlen += VG_(strlen)(exec)+1;
2083 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2084
2085 // Copy all valgrind args except the old --exec (if present)
2086 // VG_CLO_SEP is the separator.
2087 cp = optvar;
2088 for (i = 1; i < vg_argc; i++) {
2089 Char *arg = vg_argv[i];
2090
2091 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2092 // don't copy existing --exec= arg
2093 } else if (VG_(strcmp)(arg, "--") == 0) {
2094 // stop at "--"
2095 break;
2096 } else {
2097 // copy non "--exec" arg
2098 Int len = VG_(strlen)(arg);
2099 VG_(memcpy)(cp, arg, len);
2100 cp += len;
2101 *cp++ = VG_CLO_SEP;
2102 }
2103 }
2104 // Add the new --exec= option
2105 execlen = VG_(strlen)(exec);
2106 VG_(memcpy)(cp, exec, execlen);
2107 cp += execlen;
2108 *cp++ = VG_CLO_SEP;
2109
2110 *cp = '\0';
2111
2112 return optvar;
2113}
2114
2115// Build "/proc/self/fd/<execfd>".
2116Char* VG_(build_child_exename)( void )
2117{
2118 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2119 vg_assert(NULL != exename);
2120 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2121 return exename;
2122}
2123
sewardjde4a1d02002-03-22 01:27:54 +00002124
nethercote71980f02004-01-24 18:18:54 +00002125/*====================================================================*/
2126/*=== File descriptor setup ===*/
2127/*====================================================================*/
2128
2129static void setup_file_descriptors(void)
2130{
2131 struct vki_rlimit rl;
2132
2133 /* Get the current file descriptor limits. */
2134 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2135 rl.rlim_cur = 1024;
2136 rl.rlim_max = 1024;
2137 }
2138
2139 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002140 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2141 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002142 } else {
2143 rl.rlim_cur = rl.rlim_max;
2144 }
2145
2146 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002147 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2148 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002149
2150 /* Update the soft limit. */
2151 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2152
nethercotef6a1d502004-08-09 12:21:57 +00002153 if (vgexecfd != -1)
2154 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002155 if (VG_(clexecfd) != -1)
2156 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2157}
2158
nethercote71980f02004-01-24 18:18:54 +00002159/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002160/*=== Initialise program data/text, etc. ===*/
2161/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002162
sewardjb5f6f512005-03-10 23:59:00 +00002163static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2164 UInt dev, UInt ino, ULong foffset,
2165 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002166{
nethercote71980f02004-01-24 18:18:54 +00002167 /* Only record valgrind mappings for now, without loading any
2168 symbols. This is so we know where the free space is before we
2169 start allocating more memory (note: heap is OK, it's just mmap
2170 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002171 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002172 VG_(debugLog)(2, "main",
2173 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
2174 start, start+size, prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002175 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002176 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2177 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002178 /* update VG_(valgrind_last) if it looks wrong */
2179 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002180 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002181 }
sewardjde4a1d02002-03-22 01:27:54 +00002182}
2183
nethercote71980f02004-01-24 18:18:54 +00002184// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002185Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002186
sewardjb5f6f512005-03-10 23:59:00 +00002187/*
2188 This second pass adds in client mappings, and loads symbol tables
2189 for all interesting mappings. The trouble is that things can
2190 change as we go, because we're calling the Tool to track memory as
2191 we find it.
2192
2193 So for Valgrind mappings, we don't replace any mappings which
2194 aren't still identical (which will include the .so mappings, so we
2195 will load their symtabs)>
2196 */
2197static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2198 UInt dev, UInt ino, ULong foffset,
2199 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002200{
nethercote71980f02004-01-24 18:18:54 +00002201 UInt flags;
2202 Bool is_stack_segment;
2203 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002204
nethercote71980f02004-01-24 18:18:54 +00002205 is_stack_segment
2206 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002207
sewardj8c615892005-04-25 02:38:28 +00002208 VG_(debugLog)(2, "main",
2209 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
2210 start, start+size, prot, is_stack_segment, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002211
nethercote71980f02004-01-24 18:18:54 +00002212 if (is_stack_segment)
2213 flags = SF_STACK | SF_GROWDOWN;
2214 else
2215 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002216
nethercote71980f02004-01-24 18:18:54 +00002217 if (filename != NULL)
2218 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002219
sewardjb5f6f512005-03-10 23:59:00 +00002220#if 0
2221 // This needs to be fixed properly. jrs 20050307
2222 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2223 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002224
sewardjb5f6f512005-03-10 23:59:00 +00002225 /* We have to be a bit careful about inserting new mappings into
2226 the Valgrind part of the address space. We're actively
2227 changing things as we parse these mappings, particularly in
2228 shadow memory, and so we don't want to overwrite those
2229 changes. Therefore, we only insert/update a mapping if it is
2230 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
sewardjb5f6f512005-03-10 23:59:00 +00002232 NOTE: we're only talking about the Segment list mapping
2233 metadata; this doesn't actually mmap anything more. */
2234 if (filename || (s && s->addr == start && s->len == size)) {
2235 flags |= SF_VALGRIND;
2236 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2237 } else {
2238 /* assert range is already mapped */
2239 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2240 }
2241 } else
2242#endif
2243 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2244
2245 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2246 VG_TRACK( new_mem_startup, start, size,
2247 !!(prot & VKI_PROT_READ),
2248 !!(prot & VKI_PROT_WRITE),
2249 !!(prot & VKI_PROT_EXEC));
2250 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002251
nethercote71980f02004-01-24 18:18:54 +00002252 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002253 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002254 vg_assert(0 != r_esp);
2255 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002256 if (0) {
2257 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002258 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002259 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2260 r_esp, start+size);
2261 }
nethercote71980f02004-01-24 18:18:54 +00002262 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002263 // what's this for?
2264 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002265 }
sewardjde4a1d02002-03-22 01:27:54 +00002266}
2267
2268
nethercote71980f02004-01-24 18:18:54 +00002269/*====================================================================*/
2270/*=== Sanity check machinery (permanently engaged) ===*/
2271/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002272
2273/* A fast sanity check -- suitable for calling circa once per
2274 millisecond. */
2275
nethercote885dd912004-08-03 23:14:00 +00002276void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002277{
sewardjb5f6f512005-03-10 23:59:00 +00002278 ThreadId tid;
2279
njn37cea302002-09-30 11:24:00 +00002280 VGP_PUSHCC(VgpCoreCheapSanity);
2281
nethercote27fec902004-06-16 21:26:32 +00002282 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002283
2284 /* --- First do all the tests that we can do quickly. ---*/
2285
nethercote297effd2004-08-02 15:07:57 +00002286 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002287
njn25e49d8e72002-09-23 09:36:25 +00002288 /* Check stuff pertaining to the memory check system. */
2289
2290 /* Check that nobody has spuriously claimed that the first or
2291 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002292 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002293 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002294 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002295 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002296 }
njn25e49d8e72002-09-23 09:36:25 +00002297
2298 /* --- Now some more expensive checks. ---*/
2299
2300 /* Once every 25 times, check some more expensive stuff. */
2301 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002302 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002303 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002304
njn37cea302002-09-30 11:24:00 +00002305 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002306 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002307
2308# if 0
2309 { void zzzmemscan(void); zzzmemscan(); }
2310# endif
2311
nethercote297effd2004-08-02 15:07:57 +00002312 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002313 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002314
2315 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002316 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002317 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002318 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002319 }
sewardjb5f6f512005-03-10 23:59:00 +00002320
2321 /* Check that Segments and /proc/self/maps match up */
2322 //vg_assert(VG_(sanity_check_memory)());
2323
2324 /* Look for stack overruns. Visit all threads. */
2325 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002326 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002327
2328 if (VG_(threads)[tid].status == VgTs_Empty ||
2329 VG_(threads)[tid].status == VgTs_Zombie)
2330 continue;
2331
2332 remains = VGA_(stack_unused)(tid);
2333 if (remains < VKI_PAGE_SIZE)
2334 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2335 tid, remains);
2336 }
2337
njn25e49d8e72002-09-23 09:36:25 +00002338 /*
nethercote297effd2004-08-02 15:07:57 +00002339 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002340 */
njn37cea302002-09-30 11:24:00 +00002341 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002342 }
2343
nethercote27fec902004-06-16 21:26:32 +00002344 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002345 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002346 /* Check sanity of the low-level memory manager. Note that bugs
2347 in the client's code can cause this to fail, so we don't do
2348 this check unless specially asked for. And because it's
2349 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002350 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002351 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002352 }
njn37cea302002-09-30 11:24:00 +00002353 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002354}
nethercote71980f02004-01-24 18:18:54 +00002355
2356
2357/*====================================================================*/
2358/*=== main() ===*/
2359/*====================================================================*/
2360
nethercotec314eba2004-07-15 12:59:41 +00002361/*
2362 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002363 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002364 loads the client executable (and the dynamic linker, if necessary)
2365 into the client part, and calls into Valgrind proper.
2366
2367 The code is careful not to allow spurious mappings to appear in the
2368 wrong parts of the address space. In particular, to make sure
2369 dlopen puts things in the right place, it will pad out the forbidden
2370 chunks of address space so that dlopen is forced to put things where
2371 we want them.
2372
2373 The memory map it creates is:
2374
njn80950732005-03-26 00:18:45 +00002375 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002376 | client address space |
2377 : :
2378 : :
2379 | client stack |
2380 client_end +-------------------------+
2381 | redzone |
2382 shadow_base +-------------------------+
2383 | |
nethercote996901a2004-08-03 13:29:09 +00002384 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002385 | (may be 0 sized) |
2386 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002387 valgrind_base +-------------------------+
2388 | kickstart executable |
2389 | valgrind heap vvvvvvvvv| (barely used)
2390 - -
2391 | valgrind .so files |
2392 | and mappings |
2393 - -
2394 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002395 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002396 : kernel :
2397
2398 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2399 VG_(mmap)(), we need to build the segment skip-list, so we know where
2400 we can put things. However, building that structure requires
2401 allocating memory. So we need to a bootstrapping process. It's done
2402 by making VG_(arena_malloc)() have a special static superblock that's
2403 used for the first 1MB's worth of allocations. This is enough to
2404 build the segment skip-list.
2405*/
2406
thughes4ad52d02004-06-27 17:37:21 +00002407
sewardj1cf558c2005-04-25 01:36:56 +00002408/* This may be needed before m_mylibc is OK to run. */
2409static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2410{
2411 while (True) {
2412 if (*s1 == 0 && *s2 == 0) return 0;
2413 if (*s1 == 0) return -1;
2414 if (*s2 == 0) return 1;
2415
2416 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2417 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2418
2419 s1++; s2++;
2420 }
2421}
2422
2423
sewardjb5f6f512005-03-10 23:59:00 +00002424int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002425{
2426 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002427 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002428 const char *exec = NULL;
2429 char *preload; /* tool-specific LD_PRELOAD .so */
2430 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002431 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002432 struct exeinfo info;
2433 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002434 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002435 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002436 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002437 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002438 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002439
2440 //============================================================
2441 // Nb: startup is complex. Prerequisites are shown at every step.
2442 //
2443 // *** Be very careful when messing with the order ***
2444 //============================================================
2445
sewardj1cf558c2005-04-25 01:36:56 +00002446 //--------------------------------------------------------------
2447 // Start up the logging mechanism
2448 // p: none
2449 //--------------------------------------------------------------
2450 /* Start the debugging-log system ASAP. First find out how many
2451 "-d"s were specified. This is a pre-scan of the command line. */
2452 loglevel = 0;
2453 for (i = 1; i < argc; i++) {
2454 if (argv[i][0] != '-')
2455 break;
2456 if (0 == local_strcmp(argv[i], "--"))
2457 break;
2458 if (0 == local_strcmp(argv[i], "-d"))
2459 loglevel++;
2460 }
2461
2462 /* ... and start the debug logger. Now we can safely emit logging
2463 messages all through startup. */
2464 VG_(debugLog_startup)(loglevel, "Stage 2");
2465
nethercotef4928da2004-06-15 10:54:40 +00002466 //============================================================
2467 // Command line argument handling order:
2468 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002469 // (including the tool-specific usage)
2470 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002471 // * Then, if client is missing, abort with error msg
2472 // * Then, if any cmdline args are bad, abort with error msg
2473 //============================================================
2474
fitzhardingeb50068f2004-02-24 23:42:55 +00002475 // Get the current process datasize rlimit, and set it to zero.
2476 // This prevents any internal uses of brk() from having any effect.
2477 // We remember the old value so we can restore it on exec, so that
2478 // child processes will have a reasonable brk value.
2479 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2480 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2481 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002482
2483 // Get the current process stack rlimit.
2484 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2485
nethercote71980f02004-01-24 18:18:54 +00002486 //--------------------------------------------------------------
2487 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002488 // p: none
nethercote71980f02004-01-24 18:18:54 +00002489 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002490 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002491 {
sewardj1fbc1a52005-04-25 02:05:54 +00002492 void* init_sp = argv - 1;
2493 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002494 }
2495
2496 //--------------------------------------------------------------
2497 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002498 // p: none
nethercote71980f02004-01-24 18:18:54 +00002499 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002500 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002501 if (cp != NULL)
2502 VG_(libdir) = cp;
2503 }
2504
2505 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002506 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2507 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002508 // p: none
nethercote71980f02004-01-24 18:18:54 +00002509 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002510 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002511 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002512 pre_process_cmd_line_options(&need_help, &tool, &exec);
2513
2514 //==============================================================
2515 // Nb: once a tool is specified, the tool.so must be loaded even if
2516 // they specified --help or didn't specify a client program.
2517 //==============================================================
2518
2519 //--------------------------------------------------------------
2520 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002521 // p: set-libdir [for VG_(libdir)]
2522 // p: pre_process_cmd_line_options() [for 'tool']
2523 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002524 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002525 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002526
2527 //==============================================================
2528 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002529 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002530 //==============================================================
2531
2532 //--------------------------------------------------------------
2533 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002534 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002535 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002536 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002537 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002538
2539 //--------------------------------------------------------------
2540 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002541 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2542 // p: layout_remaining_space [so there's space]
2543 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002544 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002545 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002546
2547 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002548 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002549 // p: layout_remaining_space() [everything must be mapped in before now]
2550 // p: load_client() [ditto]
2551 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002552 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2553 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002554
2555 //--------------------------------------------------------------
2556 // Set up client's environment
2557 // p: set-libdir [for VG_(libdir)]
2558 // p: load_tool() [for 'preload']
2559 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002560 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002561 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002562
2563 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002564 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002565 // p: load_client() [for 'info']
2566 // p: fix_environment() [for 'env']
2567 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002568 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002569 {
sewardj1fbc1a52005-04-25 02:05:54 +00002570 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002571
sewardj1fbc1a52005-04-25 02:05:54 +00002572 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2573 &client_auxv);
2574 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002575 }
nethercote71980f02004-01-24 18:18:54 +00002576
sewardj1fbc1a52005-04-25 02:05:54 +00002577 VG_(debugLog)(2, "main",
2578 "Client info: "
2579 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2580 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2581 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002582
2583 //==============================================================
2584 // Finished setting up operating environment. Now initialise
2585 // Valgrind. (This is where the old VG_(main)() started.)
2586 //==============================================================
2587
2588 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002589 // setup file descriptors
2590 // p: n/a
2591 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002592 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002593 setup_file_descriptors();
2594
2595 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002596 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002597 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002598 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002599 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002600 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2601
2602 //==============================================================
2603 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2604 //==============================================================
2605
2606 //--------------------------------------------------------------
2607 // Init tool: pre_clo_init, process cmd line, post_clo_init
2608 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002609 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002610 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2611 // p: parse_procselfmaps [so VG segments are setup so tool can
2612 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002613 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002614 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002615 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002616 VG_(sanity_check_needs)();
2617
nethercotef4928da2004-06-15 10:54:40 +00002618 // If --tool and --help/--help-debug was given, now give the core+tool
2619 // help message
nethercotef4928da2004-06-15 10:54:40 +00002620 if (need_help) {
2621 usage(/*--help-debug?*/2 == need_help);
2622 }
nethercotec314eba2004-07-15 12:59:41 +00002623 process_cmd_line_options(client_auxv, tool);
2624
njn26f02512004-11-22 18:33:15 +00002625 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002626
2627 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002628 // Determine CPU architecture and subarchitecture
2629 // p: none
2630 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002631 VG_(debugLog)(1, "main", "Check CPU arch/subarch\n");
sewardj51ac0872004-12-21 01:20:49 +00002632 { Bool ok = VGA_(getArchAndSubArch)(
2633 & VG_(vex_arch), & VG_(vex_subarch) );
2634 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002635 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002636 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002637 VG_(printf)(" Supported CPUs are:\n");
2638 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2639 "AMD Athlon or above)\n");
2640 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002641 VG_(exit)(1);
2642 }
2643 if (VG_(clo_verbosity) > 2) {
2644 VG_(message)(Vg_DebugMsg,
2645 "Host CPU: arch = %s, subarch = %s",
2646 LibVEX_ppVexArch( VG_(vex_arch) ),
2647 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2648 }
2649 }
2650
2651 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002652 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002653 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002654 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002655 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002656 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002657 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002658 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002659 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002660 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002661
sewardja4da2f32005-03-02 14:06:08 +00002662#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002663 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002664 // Protect client trampoline page (which is also sysinfo stuff)
2665 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002666 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002667 {
2668 Segment *seg;
2669 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2670 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002671#endif
sewardjb5f6f512005-03-10 23:59:00 +00002672 /* Make sure this segment isn't treated as stack */
2673 seg = VG_(find_segment)(VG_(client_trampoline_code));
2674 if (seg)
2675 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2676 }
2677
nethercotec314eba2004-07-15 12:59:41 +00002678 //==============================================================
2679 // Can use VG_(map)() after segments set up
2680 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002681
2682 //--------------------------------------------------------------
2683 // Allow GDB attach
2684 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2685 //--------------------------------------------------------------
2686 /* Hook to delay things long enough so we can get the pid and
2687 attach GDB in another shell. */
2688 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002689 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002690 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2691 /* jrs 20050206: I don't understand why this works on x86. On
2692 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2693 work. */
2694 /* do "jump *$eip" to skip this in gdb (x86) */
2695 //VG_(do_syscall0)(__NR_pause);
2696 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002697 }
2698
sewardjb5d320c2005-03-13 18:57:15 +00002699 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002700 // Search for file descriptors that are inherited from our parent
2701 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2702 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002703 if (VG_(clo_track_fds)) {
2704 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002705 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002706 }
nethercote71980f02004-01-24 18:18:54 +00002707
2708 //--------------------------------------------------------------
2709 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002710 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2711 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002712 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002713 VG_(scheduler_init)();
2714
2715 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002716 // Initialise the pthread model
2717 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002718 // load_client() [for 'client_eip']
2719 // setup_client_stack() [for 'sp_at_startup']
2720 // setup_scheduler() [for the rest of state 1 stuff]
2721 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002722 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002723 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002724
2725 // Tell the tool that we just wrote to the registers.
2726 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2727 sizeof(VexGuestArchState));
2728
sewardj2a99cf62004-11-24 10:44:19 +00002729 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002730 // Initialise the pthread model
2731 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002732 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002733 //if (VG_(clo_model_pthreads))
2734 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002735
2736 //--------------------------------------------------------------
2737 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002738 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002739 //--------------------------------------------------------------
2740 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002741 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002742 VG_(sigstartup_actions)();
2743
2744 //--------------------------------------------------------------
2745 // Perhaps we're profiling Valgrind?
2746 // p: process_cmd_line_options() [for VG_(clo_profile)]
2747 // p: others?
2748 //
2749 // XXX: this seems to be broken? It always says the tool wasn't built
2750 // for profiling; vg_profile.c's functions don't seem to be overriding
2751 // vg_dummy_profile.c's?
2752 //
2753 // XXX: want this as early as possible. Looking for --profile
2754 // in pre_process_cmd_line_options() could get it earlier.
2755 //--------------------------------------------------------------
2756 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002757 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002758
2759 VGP_PUSHCC(VgpStartup);
2760
2761 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002762 // Read suppression file
2763 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2764 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002765 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2766 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002767 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002768 }
nethercote71980f02004-01-24 18:18:54 +00002769
2770 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002771 // Initialise translation table and translation cache
2772 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2773 // aren't identified as part of the client, which would waste
2774 // > 20M of virtual address space.]
2775 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002776 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002777 VG_(init_tt_tc)();
2778
2779 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002780 // Read debug info to find glibc entry points to intercept
2781 // p: parse_procselfmaps? [XXX for debug info?]
2782 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2783 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002784 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002785 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002786 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002787
2788 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002789 // Verbosity message
2790 // p: end_rdtsc_calibration [so startup message is printed first]
2791 //--------------------------------------------------------------
2792 if (VG_(clo_verbosity) == 1)
2793 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2794 if (VG_(clo_verbosity) > 0)
2795 VG_(message)(Vg_UserMsg, "");
2796
2797 //--------------------------------------------------------------
2798 // Setup pointercheck
2799 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2800 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002801 if (VG_(clo_pointercheck))
2802 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002803
nethercote71980f02004-01-24 18:18:54 +00002804 //--------------------------------------------------------------
2805 // Run!
2806 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002807 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002808
sewardjb5f6f512005-03-10 23:59:00 +00002809 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002810
sewardj1fbc1a52005-04-25 02:05:54 +00002811 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002812 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002813
sewardjb5f6f512005-03-10 23:59:00 +00002814 abort();
2815}
2816
2817
2818/* Do everything which needs doing when the last thread exits */
2819void VG_(shutdown_actions)(ThreadId tid)
2820{
2821 vg_assert(tid == VG_(master_tid));
2822 vg_assert(VG_(is_running_thread)(tid));
2823
2824 // Wait for all other threads to exit.
2825 VGA_(reap_threads)(tid);
2826
2827 VG_(clo_model_pthreads) = False;
2828
2829 // Clean the client up before the final report
2830 VGA_(final_tidyup)(tid);
2831
2832 // OK, done
2833 VG_(exit_thread)(tid);
2834
2835 /* should be no threads left */
2836 vg_assert(VG_(count_living_threads)() == 0);
2837
2838 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002839 //--------------------------------------------------------------
2840 // Finalisation: cleanup, messages, etc. Order no so important, only
2841 // affects what order the messages come.
2842 //--------------------------------------------------------------
2843 if (VG_(clo_verbosity) > 0)
2844 VG_(message)(Vg_UserMsg, "");
2845
nethercote71980f02004-01-24 18:18:54 +00002846 /* Print out file descriptor summary and stats. */
2847 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002848 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002849
njn95ec8702004-11-22 16:46:13 +00002850 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002851 VG_(show_all_errors)();
2852
sewardjb5f6f512005-03-10 23:59:00 +00002853 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002854
nethercote885dd912004-08-03 23:14:00 +00002855 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002856
2857 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002858 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002859
nethercote71980f02004-01-24 18:18:54 +00002860 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002861 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002862 if (VG_(clo_profile_flags) > 0)
2863 VG_(show_BB_profile)();
2864
sewardj8b635a42004-11-22 19:01:47 +00002865 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002866 if (0)
2867 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002868
nethercote71980f02004-01-24 18:18:54 +00002869}
2870
sewardjde4a1d02002-03-22 01:27:54 +00002871/*--------------------------------------------------------------------*/
2872/*--- end vg_main.c ---*/
2873/*--------------------------------------------------------------------*/