blob: eaa5f69bf5b5de15bfbf212c7219cbdecfa51cd4 [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"
sewardj55f9d1a2005-04-25 11:11:44 +000038#include "pub_core_aspacemgr.h"
nethercote71980f02004-01-24 18:18:54 +000039
40#include <dirent.h>
41#include <dlfcn.h>
42#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000045#include <string.h>
46#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000047#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000049#include <sys/wait.h>
50#include <unistd.h>
51
sewardjb5f6f512005-03-10 23:59:00 +000052#include "memcheck/memcheck.h"
53
thughes74b8de22004-04-22 18:12:31 +000054#ifndef AT_DCACHEBSIZE
55#define AT_DCACHEBSIZE 19
56#endif /* AT_DCACHEBSIZE */
57
58#ifndef AT_ICACHEBSIZE
59#define AT_ICACHEBSIZE 20
60#endif /* AT_ICACHEBSIZE */
61
62#ifndef AT_UCACHEBSIZE
63#define AT_UCACHEBSIZE 21
64#endif /* AT_UCACHEBSIZE */
65
nethercote71980f02004-01-24 18:18:54 +000066#ifndef AT_SYSINFO
67#define AT_SYSINFO 32
68#endif /* AT_SYSINFO */
69
70#ifndef AT_SYSINFO_EHDR
71#define AT_SYSINFO_EHDR 33
72#endif /* AT_SYSINFO_EHDR */
73
74#ifndef AT_SECURE
75#define AT_SECURE 23 /* secure mode boolean */
76#endif /* AT_SECURE */
77
nethercote71980f02004-01-24 18:18:54 +000078/* redzone gap between client address space and shadow */
79#define REDZONE_SIZE (1 * 1024*1024)
80
81/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000082#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000083
nethercotee2097312004-06-27 12:29:56 +000084/* Proportion of client space for its heap (rest is for mmaps + stack) */
85#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000086
njn14319cc2005-03-13 06:26:22 +000087/* Number of file descriptors that Valgrind tries to reserve for
88 it's own use - just a small constant. */
89#define N_RESERVED_FDS (10)
90
91/* Default debugger command. */
92#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
93
nethercote71980f02004-01-24 18:18:54 +000094/*====================================================================*/
95/*=== Global entities not referenced from generated code ===*/
96/*====================================================================*/
97
sewardjde4a1d02002-03-22 01:27:54 +000098/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000099 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000100 ------------------------------------------------------------------ */
101
nethercote71980f02004-01-24 18:18:54 +0000102/* Client address space, lowest to highest (see top of ume.c) */
103Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000104Addr VG_(client_end);
105Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000106Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000107Addr VG_(clstk_base);
108Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000109
110Addr VG_(brk_base); /* start of brk */
111Addr VG_(brk_limit); /* current brk */
112
nethercote996901a2004-08-03 13:29:09 +0000113Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000114Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000115
116Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000117
nethercote820bd8c2004-09-07 23:04:49 +0000118// Note that VG_(valgrind_last) names the last byte of the section, whereas
119// the VG_(*_end) vars name the byte one past the end of the section.
120Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000121
nethercote73b526f2004-10-31 18:48:21 +0000122struct vki_rlimit VG_(client_rlimit_data);
123struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000124
fitzhardinge98abfc72003-12-16 02:05:15 +0000125/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000126static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000127
128/* client executable */
129Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000130
131/* Path to library directory */
132const Char *VG_(libdir) = VG_LIBDIR;
133
134/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000135static Int vg_argc;
136static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000137
sewardjb5f6f512005-03-10 23:59:00 +0000138/* The master thread the one which will be responsible for mopping
139 everything up at exit. Normally it is tid 1, since that's the
140 first thread created, but it may be something else after a
141 fork(). */
142ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000143
thughesad1c9562004-06-26 11:27:52 +0000144/* Application-visible file descriptor limits */
145Int VG_(fd_soft_limit) = -1;
146Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000147
nethercote4ad74312004-10-26 09:59:49 +0000148/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000149 envp[] as extracted from the client's stack at startup-time. */
150Int VG_(client_argc);
151Char** VG_(client_argv);
152Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000153
sewardj51ac0872004-12-21 01:20:49 +0000154/* Indicates what arch and subarch we are running on. */
155VexArch VG_(vex_arch) = VexArch_INVALID;
156VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
157
158
sewardjde4a1d02002-03-22 01:27:54 +0000159/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000160 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000161 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* Counts downwards in VG_(run_innerloop). */
164UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000165
166/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000167ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/* Tell the logging mechanism whether we are logging to a file
170 descriptor or a socket descriptor. */
171Bool VG_(logging_to_filedes) = True;
172
sewardj73cf3bc2002-11-03 03:20:15 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/*====================================================================*/
175/*=== Counters, for profiling purposes only ===*/
176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000177
sewardjde4a1d02002-03-22 01:27:54 +0000178/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000179static UInt sanity_fast_count = 0;
180static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000181
nethercote3a42fb82004-08-03 18:08:50 +0000182static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000183{
nethercote3a42fb82004-08-03 18:08:50 +0000184 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000185 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000187 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000188
nethercote3a42fb82004-08-03 18:08:50 +0000189 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000190 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000191
nethercote71980f02004-01-24 18:18:54 +0000192 VG_(message)(Vg_DebugMsg,
193 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000194 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000195
njn9271cbc2005-03-13 05:38:25 +0000196 VG_(print_ExeContext_stats)();
197
nethercote3a42fb82004-08-03 18:08:50 +0000198 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000199 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000200 VG_(message)(Vg_DebugMsg, "");
201 VG_(message)(Vg_DebugMsg,
202 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000203 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000204 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000205 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000206 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000207 }
nethercote71980f02004-01-24 18:18:54 +0000208}
209
210
211/*====================================================================*/
212/*=== Miscellaneous global functions ===*/
213/*====================================================================*/
214
nethercotecf97ffb2004-09-09 13:40:31 +0000215static Int ptrace_setregs(Int pid, ThreadId tid)
216{
sewardj2a99cf62004-11-24 10:44:19 +0000217 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000218}
219
nethercote04d0fbc2004-01-26 16:48:06 +0000220/* Start debugger and get it to attach to this process. Called if the
221 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000222 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000223 meaningfully get the debugger to continue the program, though; to
224 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000225void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000226{
227 Int pid;
228
229 if ((pid = fork()) == 0) {
230 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000231 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000232
233 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000234 Int status;
235 Int res;
236
nethercote71980f02004-01-24 18:18:54 +0000237 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
238 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000239 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000240 kill(pid, SIGSTOP) == 0 &&
241 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000242 Char pidbuf[15];
243 Char file[30];
244 Char buf[100];
245 Char *bufptr;
246 Char *cmdptr;
247
248 VG_(sprintf)(pidbuf, "%d", pid);
249 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
250
251 bufptr = buf;
252 cmdptr = VG_(clo_db_command);
253
254 while (*cmdptr) {
255 switch (*cmdptr) {
256 case '%':
257 switch (*++cmdptr) {
258 case 'f':
259 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
260 bufptr += VG_(strlen)(file);
261 cmdptr++;
262 break;
263 case 'p':
264 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
265 bufptr += VG_(strlen)(pidbuf);
266 cmdptr++;
267 break;
268 default:
269 *bufptr++ = *cmdptr++;
270 break;
271 }
272 break;
273 default:
274 *bufptr++ = *cmdptr++;
275 break;
276 }
277 }
278
279 *bufptr++ = '\0';
280
281 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000282 res = VG_(system)(buf);
283 if (res == 0) {
284 VG_(message)(Vg_UserMsg, "");
285 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000286 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000287 } else {
288 VG_(message)(Vg_UserMsg, "Apparently failed!");
289 VG_(message)(Vg_UserMsg, "");
290 }
291 }
292
nethercote73b526f2004-10-31 18:48:21 +0000293 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000294 VG_(waitpid)(pid, &status, 0);
295 }
296}
297
298
299/* Print some helpful-ish text about unimplemented things, and give
300 up. */
301void VG_(unimplemented) ( Char* msg )
302{
303 VG_(message)(Vg_UserMsg, "");
304 VG_(message)(Vg_UserMsg,
305 "Valgrind detected that your program requires");
306 VG_(message)(Vg_UserMsg,
307 "the following unimplemented functionality:");
308 VG_(message)(Vg_UserMsg, " %s", msg);
309 VG_(message)(Vg_UserMsg,
310 "This may be because the functionality is hard to implement,");
311 VG_(message)(Vg_UserMsg,
312 "or because no reasonable program would behave this way,");
313 VG_(message)(Vg_UserMsg,
314 "or because nobody has yet needed it. In any case, let us know at");
315 VG_(message)(Vg_UserMsg,
316 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
317 VG_(message)(Vg_UserMsg,
318 "");
319 VG_(message)(Vg_UserMsg,
320 "Valgrind has to exit now. Sorry. Bye!");
321 VG_(message)(Vg_UserMsg,
322 "");
323 VG_(pp_sched_status)();
324 VG_(exit)(1);
325}
326
sewardj2a99cf62004-11-24 10:44:19 +0000327/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000328Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000329{
njncf45fd42004-11-24 16:30:22 +0000330 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000331}
332
njn67516132005-03-22 04:02:43 +0000333Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000334{
335 return INSTR_PTR( VG_(threads)[tid].arch );
336}
337
njnea4b28c2004-11-30 16:04:58 +0000338
nethercote71980f02004-01-24 18:18:54 +0000339/*====================================================================*/
340/*=== Check we were launched by stage 1 ===*/
341/*====================================================================*/
342
343/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000344static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000345{
nethercoteebf1d862004-11-01 18:22:05 +0000346 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000347 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000348
349 for (; auxv->a_type != AT_NULL; auxv++)
350 switch(auxv->a_type) {
351 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000352 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000353 found |= 1;
354 break;
355
356 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000357 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000358 found |= 2;
359 break;
nethercote7f390022004-10-25 17:18:24 +0000360
361 case AT_PHDR:
362 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
363 break;
nethercote71980f02004-01-24 18:18:54 +0000364 }
365
nethercote361a14e2004-07-26 11:11:56 +0000366 if ( found != (1|2) ) {
367 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000368 exit(127);
369 }
nethercote31779c72004-07-30 21:50:15 +0000370 vg_assert(padfile >= 0);
371 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000372}
373
374
375/*====================================================================*/
376/*=== Address space determination ===*/
377/*====================================================================*/
378
nethercote7f390022004-10-25 17:18:24 +0000379extern char _start[];
380
nethercote31779c72004-07-30 21:50:15 +0000381static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000382{
nethercotea3c3cf22004-11-01 18:38:00 +0000383 Int ires;
384 void* vres;
385 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000386
nethercote7f390022004-10-25 17:18:24 +0000387 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
388 // this is a workable approximation
389 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000390 VG_(valgrind_base) = PGROUNDDN(&_start);
391 }
392
nethercote820bd8c2004-09-07 23:04:49 +0000393 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000394
nethercote31779c72004-07-30 21:50:15 +0000395 // This gives the client the largest possible address space while
396 // taking into account the tool's shadow needs.
397 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000398 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000399 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000400 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000401 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000402 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000403 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000406 VG_(shadow_end) = VG_(valgrind_base);
407 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000408
nethercotee2097312004-06-27 12:29:56 +0000409#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
410
nethercote71980f02004-01-24 18:18:54 +0000411 if (0)
nethercotee2097312004-06-27 12:29:56 +0000412 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000413 "client_base %p (%dMB)\n"
414 "client_mapbase %p (%dMB)\n"
415 "client_end %p (%dMB)\n"
416 "shadow_base %p (%dMB)\n"
417 "shadow_end %p\n"
418 "valgrind_base %p (%dMB)\n"
419 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000420 VG_(client_base), SEGSIZE(client_base, client_mapbase),
421 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
422 VG_(client_end), SEGSIZE(client_end, shadow_base),
423 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000424 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000425 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
426 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000427 );
428
429#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000430
431 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000432 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000433 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000434 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000435
436 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000437 ires = munmap((void*)VG_(client_base), client_size);
438 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000439
440 // Map shadow memory.
441 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000442 if (shadow_size != 0) {
443 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000444 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000445 if ((void*)-1 == vres) {
446 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000447 "valgrind: Could not allocate address space (%p bytes)\n"
448 "valgrind: for shadow memory\n"
449 "valgrind: Possible causes:\n"
450 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
451 "valgrind: needs at least 1.5GB swap space.\n"
452 "valgrind: - Or, your virtual memory size may be limited (check\n"
453 "valgrind: with 'ulimit -v').\n"
454 "valgrind: - Or, your system may use a kernel that provides only a\n"
455 "valgrind: too-small (eg. 2GB) user address space.\n"
456 , (void*)shadow_size
457 );
nethercoted4722622004-08-30 19:36:42 +0000458 exit(1);
459 }
nethercotee567e702004-07-10 17:49:17 +0000460 }
nethercote71980f02004-01-24 18:18:54 +0000461}
462
463/*====================================================================*/
464/*=== Command line setup ===*/
465/*====================================================================*/
466
467/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
468static char* get_file_clo(char* dir)
469{
470# define FLEN 512
471 Int fd, n;
472 struct stat s1;
473 char* f_clo = NULL;
474 char filename[FLEN];
475
476 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
477 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
478 if ( fd > 0 ) {
479 if ( 0 == fstat(fd, &s1) ) {
480 f_clo = malloc(s1.st_size+1);
481 vg_assert(f_clo);
482 n = read(fd, f_clo, s1.st_size);
483 if (n == -1) n = 0;
484 f_clo[n] = '\0';
485 }
486 close(fd);
487 }
488 return f_clo;
489# undef FLEN
490}
491
492static Int count_args(char* s)
493{
494 Int n = 0;
495 if (s) {
496 char* cp = s;
497 while (True) {
498 // We have alternating sequences: blanks, non-blanks, blanks...
499 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000500 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000501 if ( !*cp ) break;
502 n++;
njn0c0f32a2005-03-26 04:14:01 +0000503 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000504 }
505 }
506 return n;
507}
508
509/* add args out of environment, skipping multiple spaces and -- args */
510static char** copy_args( char* s, char** to )
511{
512 if (s) {
513 char* cp = s;
514 while (True) {
515 // We have alternating sequences: blanks, non-blanks, blanks...
516 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000517 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000518 if ( !*cp ) break;
519 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000520 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000521 if ( *cp ) *cp++ = '\0'; // terminate if necessary
522 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
523 }
524 }
525 return to;
526}
527
528// Augment command line with arguments from environment and .valgrindrc
529// files.
530static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
531{
nethercotef6a1d502004-08-09 12:21:57 +0000532 int vg_argc0 = *vg_argc_inout;
533 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000534
535 char* env_clo = getenv(VALGRINDOPTS);
536 char* f1_clo = get_file_clo( getenv("HOME") );
537 char* f2_clo = get_file_clo(".");
538
539 /* copy any extra args from file or environment, if present */
540 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
541 /* ' ' separated extra options */
542 char **from;
543 char **to;
thughescaca0022004-09-13 10:20:34 +0000544 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
545
546 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
547
nethercote71980f02004-01-24 18:18:54 +0000548 env_arg_count = count_args(env_clo);
549 f1_arg_count = count_args(f1_clo);
550 f2_arg_count = count_args(f2_clo);
551
552 if (0)
553 printf("extra-argc=%d %d %d\n",
554 env_arg_count, f1_arg_count, f2_arg_count);
555
556 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000557 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000558 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000559 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000560 vg_assert(vg_argv0);
561 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000562
563 /* copy argv[0] */
564 *to++ = *from++;
565
566 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
567 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
568 * to override less local ones. */
569 to = copy_args(f1_clo, to);
570 to = copy_args(env_clo, to);
571 to = copy_args(f2_clo, to);
572
573 /* copy original arguments, stopping at command or -- */
574 while (*from) {
575 if (**from != '-')
576 break;
577 if (VG_STREQ(*from, "--")) {
578 from++; /* skip -- */
579 break;
580 }
581 *to++ = *from++;
582 }
583
584 /* add -- */
585 *to++ = "--";
586
nethercotef6a1d502004-08-09 12:21:57 +0000587 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000588
589 /* copy rest of original command line, then NULL */
590 while (*from) *to++ = *from++;
591 *to = NULL;
592 }
593
nethercotef6a1d502004-08-09 12:21:57 +0000594 *vg_argc_inout = vg_argc0;
595 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000596}
597
nethercotef6a1d502004-08-09 12:21:57 +0000598#define VG_CLO_SEP '\01'
599
nethercote71980f02004-01-24 18:18:54 +0000600static void get_command_line( int argc, char** argv,
601 Int* vg_argc_out, Char*** vg_argv_out,
602 char*** cl_argv_out )
603{
nethercotef6a1d502004-08-09 12:21:57 +0000604 int vg_argc0;
605 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000606 char** cl_argv;
607 char* env_clo = getenv(VALGRINDCLO);
608
609 if (env_clo != NULL && *env_clo != '\0') {
610 char *cp;
611 char **cpp;
612
nethercotef6a1d502004-08-09 12:21:57 +0000613 /* OK, VALGRINDCLO is set, which means we must be a child of another
614 Valgrind process using --trace-children, so we're getting all our
615 arguments from VALGRINDCLO, and the entire command line belongs to
616 the client (including argv[0]) */
617 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000618 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000619 if (*cp == VG_CLO_SEP)
620 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000621
nethercotef6a1d502004-08-09 12:21:57 +0000622 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
623 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000624
nethercotef6a1d502004-08-09 12:21:57 +0000625 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000626
627 *cpp++ = "valgrind"; /* nominal argv[0] */
628 *cpp++ = env_clo;
629
nethercotef6a1d502004-08-09 12:21:57 +0000630 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000631 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000632 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000633 *cp++ = '\0'; /* chop it up in place */
634 *cpp++ = cp;
635 }
636 }
637 *cpp = NULL;
638 cl_argv = argv;
639
640 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000641 Bool noaugment = False;
642
nethercote71980f02004-01-24 18:18:54 +0000643 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000644 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000645
nethercotef6a1d502004-08-09 12:21:57 +0000646 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000647 Char* arg = argv[vg_argc0];
648 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000649 break;
sewardjb5f6f512005-03-10 23:59:00 +0000650 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000651 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000652 break;
653 }
njn45270a22005-03-27 01:00:11 +0000654 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000655 }
nethercotef6a1d502004-08-09 12:21:57 +0000656 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000657
658 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000659 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000660 those extra args will already be present in VALGRINDCLO.
661 (We also don't do it when --command-line-only=yes.) */
662 if (!noaugment)
663 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000664 }
665
666 if (0) {
667 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000668 for (i = 0; i < vg_argc0; i++)
669 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000670 }
671
nethercotef6a1d502004-08-09 12:21:57 +0000672 *vg_argc_out = vg_argc0;
673 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000674 *cl_argv_out = cl_argv;
675}
676
677
678/*====================================================================*/
679/*=== Environment and stack setup ===*/
680/*====================================================================*/
681
682/* Scan a colon-separated list, and call a function on each element.
683 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000684 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000685 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000686
687 This routine will return True if (*func) returns True and False if
688 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000689*/
thughes4ad52d02004-06-27 17:37:21 +0000690static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000691{
692 char *cp, *entry;
693 int end;
694
695 if (colsep == NULL ||
696 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000697 return False;
nethercote71980f02004-01-24 18:18:54 +0000698
699 entry = cp = colsep;
700
701 do {
702 end = (*cp == '\0');
703
704 if (*cp == ':' || *cp == '\0') {
705 char save = *cp;
706
707 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000708 if ((*func)(entry)) {
709 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000710 return True;
thughes21942d92004-07-12 09:35:37 +0000711 }
nethercote71980f02004-01-24 18:18:54 +0000712 *cp = save;
713 entry = cp+1;
714 }
715 cp++;
716 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000717
718 return False;
719}
720
nethercote71980f02004-01-24 18:18:54 +0000721/* Prepare the client's environment. This is basically a copy of our
722 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000723 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000724
sewardjb5f6f512005-03-10 23:59:00 +0000725 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000726
727 Yummy. String hacking in C.
728
729 If this needs to handle any more variables it should be hacked
730 into something table driven.
731 */
732static char **fix_environment(char **origenv, const char *preload)
733{
734 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000735 static const char ld_preload[] = "LD_PRELOAD=";
736 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000737 static const int ld_preload_len = sizeof(ld_preload)-1;
738 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
739 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000740 char *inject_path;
741 int inject_path_len;
742 int vgliblen = strlen(VG_(libdir));
743 char **cpp;
744 char **ret;
745 int envc;
746 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
747
748 /* Find the vg_inject.so; also make room for the tool preload
749 library */
750 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
751 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000752 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000753
754 if (preload)
755 snprintf(inject_path, inject_path_len, "%s/%s:%s",
756 VG_(libdir), inject_so, preload);
757 else
758 snprintf(inject_path, inject_path_len, "%s/%s",
759 VG_(libdir), inject_so);
760
761 /* Count the original size of the env */
762 envc = 0; /* trailing NULL */
763 for (cpp = origenv; cpp && *cpp; cpp++)
764 envc++;
765
766 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000767 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000768 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000769
770 /* copy it over */
771 for (cpp = ret; *origenv; )
772 *cpp++ = *origenv++;
773 *cpp = NULL;
774
775 vg_assert(envc == (cpp - ret));
776
777 /* Walk over the new environment, mashing as we go */
778 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000779 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000780 int len = strlen(*cpp) + inject_path_len;
781 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000782 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000783
784 snprintf(cp, len, "%s%s:%s",
785 ld_preload, inject_path, (*cpp)+ld_preload_len);
786
787 *cpp = cp;
788
789 ld_preload_done = 1;
790 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
791 *cpp = "";
792 }
793 }
794
795 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000796 if (!ld_preload_done) {
797 int len = ld_preload_len + inject_path_len;
798 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000799 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000800
801 snprintf(cp, len, "%s%s",
802 ld_preload, inject_path);
803
804 ret[envc++] = cp;
805 }
806
sewardjb5f6f512005-03-10 23:59:00 +0000807 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000808 ret[envc] = NULL;
809
810 return ret;
811}
812
813extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000814
815/* Add a string onto the string table, and return its address */
816static char *copy_str(char **tab, const char *str)
817{
818 char *cp = *tab;
819 char *orig = cp;
820
821 while(*str)
822 *cp++ = *str++;
823 *cp++ = '\0';
824
825 if (0)
nethercote545fe672004-11-01 16:52:43 +0000826 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000827
828 *tab = cp;
829
830 return orig;
831}
832
833/*
834 This sets up the client's initial stack, containing the args,
835 environment and aux vector.
836
837 The format of the stack is:
838
839 higher address +-----------------+
840 | Trampoline code |
841 +-----------------+
842 | |
843 : string table :
844 | |
845 +-----------------+
846 | AT_NULL |
847 - -
848 | auxv |
849 +-----------------+
850 | NULL |
851 - -
852 | envp |
853 +-----------------+
854 | NULL |
855 - -
856 | argv |
857 +-----------------+
858 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000859 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000860 | undefined |
861 : :
862 */
nethercotec25c4492004-10-18 11:52:17 +0000863static Addr setup_client_stack(void* init_sp,
864 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000865 const struct exeinfo *info,
866 UInt** client_auxv)
867{
nethercotee567e702004-07-10 17:49:17 +0000868 void* res;
nethercote71980f02004-01-24 18:18:54 +0000869 char **cpp;
870 char *strtab; /* string table */
871 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000872 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000873 struct ume_auxv *auxv;
874 const struct ume_auxv *orig_auxv;
875 const struct ume_auxv *cauxv;
876 unsigned stringsize; /* total size of strings in bytes */
877 unsigned auxsize; /* total size of auxv in bytes */
878 int argc; /* total argc */
879 int envc; /* total number of env vars */
880 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000881 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000882
883 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000884 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000885
886 /* ==================== compute sizes ==================== */
887
888 /* first of all, work out how big the client stack will be */
889 stringsize = 0;
890
891 /* paste on the extra args if the loader needs them (ie, the #!
892 interpreter and its argument) */
893 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000894 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000895 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000896 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000897 }
nethercoted6a56872004-07-26 15:32:47 +0000898 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000899 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000900 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000901 }
902
903 /* now scan the args we're given... */
904 for (cpp = orig_argv; *cpp; cpp++) {
905 argc++;
906 stringsize += strlen(*cpp) + 1;
907 }
908
909 /* ...and the environment */
910 envc = 0;
911 for (cpp = orig_envp; cpp && *cpp; cpp++) {
912 envc++;
913 stringsize += strlen(*cpp) + 1;
914 }
915
916 /* now, how big is the auxv? */
917 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
918 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
919 if (cauxv->a_type == AT_PLATFORM)
920 stringsize += strlen(cauxv->u.a_ptr) + 1;
921 auxsize += sizeof(*cauxv);
922 }
923
924 /* OK, now we know how big the client stack is */
925 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000926 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000927 sizeof(char **)*argc + /* argv */
928 sizeof(char **) + /* terminal NULL */
929 sizeof(char **)*envc + /* envp */
930 sizeof(char **) + /* terminal NULL */
931 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000932 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000933 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000934
sewardj79048ce2005-02-18 08:28:32 +0000935 if (0) VG_(printf)("stacksize = %d\n", stacksize);
936
nethercotef84f6952004-07-15 14:58:33 +0000937 // decide where stack goes!
938 VG_(clstk_end) = VG_(client_end);
939
nethercote73b526f2004-10-31 18:48:21 +0000940 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000941
nethercote71980f02004-01-24 18:18:54 +0000942 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000943 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000944 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
945
nethercote71980f02004-01-24 18:18:54 +0000946 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000947 stringbase = strtab = (char *)(VG_(client_trampoline_code)
948 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000949
950 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000951
sewardj79048ce2005-02-18 08:28:32 +0000952 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000953 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000954 "clstk_base %p\n"
955 "clstk_end %p\n",
956 stringsize, auxsize, stacksize,
957 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000958
nethercote71980f02004-01-24 18:18:54 +0000959 /* ==================== allocate space ==================== */
960
961 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000962 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000963 PROT_READ | PROT_WRITE | PROT_EXEC,
964 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
965 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000966
967 /* ==================== copy client stack ==================== */
968
nethercotea3c3cf22004-11-01 18:38:00 +0000969 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000970
971 /* --- argc --- */
972 *ptr++ = argc; /* client argc */
973
974 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000975 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000976 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000977 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000978 }
nethercoted6a56872004-07-26 15:32:47 +0000979 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000980 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000981 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000982 }
983 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000984 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000985 }
986 *ptr++ = 0;
987
988 /* --- envp --- */
989 VG_(client_envp) = (Char **)ptr;
990 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000991 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000992 *ptr++ = 0;
993
994 /* --- auxv --- */
995 auxv = (struct ume_auxv *)ptr;
996 *client_auxv = (UInt *)auxv;
997
998 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
999 /* copy the entry... */
1000 *auxv = *orig_auxv;
1001
1002 /* ...and fix up the copy */
1003 switch(auxv->a_type) {
1004 case AT_PHDR:
1005 if (info->phdr == 0)
1006 auxv->a_type = AT_IGNORE;
1007 else
1008 auxv->u.a_val = info->phdr;
1009 break;
1010
1011 case AT_PHNUM:
1012 if (info->phdr == 0)
1013 auxv->a_type = AT_IGNORE;
1014 else
1015 auxv->u.a_val = info->phnum;
1016 break;
1017
1018 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001019 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001020 break;
1021
1022 case AT_PLATFORM: /* points to a platform description string */
1023 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1024 break;
1025
1026 case AT_ENTRY:
1027 auxv->u.a_val = info->entry;
1028 break;
1029
1030 case AT_IGNORE:
1031 case AT_EXECFD:
1032 case AT_PHENT:
1033 case AT_PAGESZ:
1034 case AT_FLAGS:
1035 case AT_NOTELF:
1036 case AT_UID:
1037 case AT_EUID:
1038 case AT_GID:
1039 case AT_EGID:
1040 case AT_CLKTCK:
1041 case AT_HWCAP:
1042 case AT_FPUCW:
1043 case AT_DCACHEBSIZE:
1044 case AT_ICACHEBSIZE:
1045 case AT_UCACHEBSIZE:
1046 /* All these are pointerless, so we don't need to do anything
1047 about them. */
1048 break;
1049
1050 case AT_SECURE:
1051 /* If this is 1, then it means that this program is running
1052 suid, and therefore the dynamic linker should be careful
1053 about LD_PRELOAD, etc. However, since stage1 (the thing
1054 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001055 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001056 set AT_SECURE to 0. */
1057 auxv->u.a_val = 0;
1058 break;
1059
1060 case AT_SYSINFO:
1061 /* Leave this unmolested for now, but we'll update it later
1062 when we set up the client trampoline code page */
1063 break;
1064
1065 case AT_SYSINFO_EHDR:
1066 /* Trash this, because we don't reproduce it */
1067 auxv->a_type = AT_IGNORE;
1068 break;
1069
1070 default:
1071 /* stomp out anything we don't know about */
1072 if (0)
nethercote545fe672004-11-01 16:52:43 +00001073 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001074 auxv->a_type = AT_IGNORE;
1075 break;
1076
1077 }
1078 }
1079 *auxv = *orig_auxv;
1080 vg_assert(auxv->a_type == AT_NULL);
1081
njnc6168192004-11-29 13:54:10 +00001082// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1083// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001084#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001085 /* --- trampoline page --- */
1086 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1087 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001088#endif
nethercotef84f6952004-07-15 14:58:33 +00001089
nethercote71980f02004-01-24 18:18:54 +00001090 vg_assert((strtab-stringbase) == stringsize);
1091
nethercote5ee67ca2004-06-22 14:00:09 +00001092 /* We know the initial ESP is pointing at argc/argv */
1093 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001094 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001095
sewardj79048ce2005-02-18 08:28:32 +00001096 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001097 return cl_esp;
1098}
1099
1100/*====================================================================*/
1101/*=== Find executable ===*/
1102/*====================================================================*/
1103
thughes4ad52d02004-06-27 17:37:21 +00001104static const char* executable_name;
1105
1106static Bool match_executable(const char *entry) {
1107 char buf[strlen(entry) + strlen(executable_name) + 2];
1108
1109 /* empty PATH element means . */
1110 if (*entry == '\0')
1111 entry = ".";
1112
1113 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1114
1115 if (access(buf, R_OK|X_OK) == 0) {
1116 executable_name = strdup(buf);
1117 vg_assert(NULL != executable_name);
1118 return True;
1119 }
1120 return False;
1121}
1122
nethercote71980f02004-01-24 18:18:54 +00001123static const char* find_executable(const char* exec)
1124{
1125 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001126 executable_name = exec;
1127 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001128 /* no '/' - we need to search the path */
1129 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001130 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001131 }
thughes4ad52d02004-06-27 17:37:21 +00001132 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001133}
1134
1135
1136/*====================================================================*/
1137/*=== Loading tools ===*/
1138/*====================================================================*/
1139
1140static void list_tools(void)
1141{
1142 DIR *dir = opendir(VG_(libdir));
1143 struct dirent *de;
1144 int first = 1;
1145
1146 if (dir == NULL) {
1147 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001148 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001149 return;
1150 }
1151
nethercotef4928da2004-06-15 10:54:40 +00001152 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001153 int len = strlen(de->d_name);
1154
njn063c5402004-11-22 16:58:05 +00001155 /* look for vgtool_TOOL.so names */
1156 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1157 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001158 VG_STREQ(de->d_name + len - 3, ".so")) {
1159 if (first) {
1160 fprintf(stderr, "Available tools:\n");
1161 first = 0;
1162 }
1163 de->d_name[len-3] = '\0';
1164 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001165 }
1166 }
1167
1168 closedir(dir);
1169
1170 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001171 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1172 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001173}
1174
1175
1176/* Find and load a tool, and check it looks ok. Also looks to see if there's
1177 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001178static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001179 ToolInfo** toolinfo_out, char **preloadpath_out )
1180{
1181 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001182 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001183 char buf[len];
1184 void* handle;
1185 ToolInfo* toolinfo;
1186 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001187
1188 // XXX: allowing full paths for --tool option -- does it make sense?
1189 // Doesn't allow for vgpreload_<tool>.so.
1190
1191 if (strchr(toolname, '/') != 0) {
1192 /* toolname contains '/', and so must be a pathname */
1193 handle = dlopen(toolname, RTLD_NOW);
1194 } else {
1195 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001196 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001197 handle = dlopen(buf, RTLD_NOW);
1198
1199 if (handle != NULL) {
1200 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1201 if (access(buf, R_OK) == 0) {
1202 preloadpath = strdup(buf);
1203 vg_assert(NULL != preloadpath);
1204 }
1205 }
1206 }
1207
1208 ok = (NULL != handle);
1209 if (!ok) {
1210 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1211 goto bad_load;
1212 }
1213
njn26f02512004-11-22 18:33:15 +00001214 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001215 ok = (NULL != toolinfo);
1216 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001217 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001218 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1219 goto bad_load;
1220 }
1221
1222 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1223 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001224 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001225 if (!ok) {
1226 fprintf(stderr, "Error:\n"
1227 " Tool and core interface versions do not match.\n"
1228 " Interface version used by core is: %d.%d (size %d)\n"
1229 " Interface version used by tool is: %d.%d (size %d)\n"
1230 " The major version numbers must match.\n",
1231 VG_CORE_INTERFACE_MAJOR_VERSION,
1232 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001233 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001234 toolinfo->interface_major_version,
1235 toolinfo->interface_minor_version,
1236 toolinfo->sizeof_ToolInfo);
1237 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1238 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001239 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001240 else
nethercote996901a2004-08-03 13:29:09 +00001241 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001242 goto bad_load;
1243 }
1244
njn8a97c6d2005-03-31 04:37:24 +00001245 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001246 *toolinfo_out = toolinfo;
1247 *preloadpath_out = preloadpath;
1248 return;
1249
1250
1251 bad_load:
1252 if (handle != NULL)
1253 dlclose(handle);
1254
nethercotef4928da2004-06-15 10:54:40 +00001255 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001256 list_tools();
1257 exit(127);
1258}
1259
nethercotef4928da2004-06-15 10:54:40 +00001260
1261/*====================================================================*/
1262/*=== Command line errors ===*/
1263/*====================================================================*/
1264
1265static void abort_msg ( void )
1266{
nethercotef8548672004-06-21 12:42:35 +00001267 VG_(clo_log_to) = VgLogTo_Fd;
1268 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001269}
1270
1271void VG_(bad_option) ( Char* opt )
1272{
1273 abort_msg();
1274 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1275 VG_(printf)("valgrind: Use --help for more information.\n");
1276 VG_(exit)(1);
1277}
1278
nethercotef4928da2004-06-15 10:54:40 +00001279static void missing_prog ( void )
1280{
1281 abort_msg();
1282 VG_(printf)("valgrind: no program specified\n");
1283 VG_(printf)("valgrind: Use --help for more information.\n");
1284 VG_(exit)(1);
1285}
1286
1287static void config_error ( Char* msg )
1288{
1289 abort_msg();
1290 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1291 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1292 VG_(exit)(1);
1293}
1294
1295
nethercote71980f02004-01-24 18:18:54 +00001296/*====================================================================*/
1297/*=== Loading the client ===*/
1298/*====================================================================*/
1299
nethercotef4928da2004-06-15 10:54:40 +00001300static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001301 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1302{
1303 // If they didn't specify an executable with --exec, and didn't specify
1304 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001305 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001306 if (cl_argv[0] == NULL ||
1307 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1308 {
nethercotef4928da2004-06-15 10:54:40 +00001309 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001310 }
1311 }
1312
1313 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001314 info->exe_base = VG_(client_base);
1315 info->exe_end = VG_(client_end);
1316 info->argv = cl_argv;
1317
nethercotef4928da2004-06-15 10:54:40 +00001318 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001319 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001320 // Totally zero 'info' before continuing.
1321 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001322 } else {
1323 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001324 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001325 ret = do_exec(exec, info);
1326 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001327 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1328 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001329 exit(127);
1330 }
1331 }
1332
1333 /* Copy necessary bits of 'info' that were filled in */
1334 *client_eip = info->init_eip;
1335 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1336}
1337
nethercote969ecf12004-10-13 17:29:01 +00001338/*====================================================================*/
1339/*=== Address space unpadding ===*/
1340/*====================================================================*/
1341
1342typedef struct {
1343 char* killpad_start;
1344 char* killpad_end;
1345 struct stat* killpad_padstat;
1346} killpad_extra;
1347
1348static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1349 int maj, int min, int ino, void* ex)
1350{
1351 killpad_extra* extra = ex;
1352 void *b, *e;
1353 int res;
1354
1355 vg_assert(NULL != extra->killpad_padstat);
1356
1357 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1358 extra->killpad_padstat->st_ino != ino)
1359 return 1;
1360
1361 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1362 return 1;
1363
1364 if (segstart <= extra->killpad_start)
1365 b = extra->killpad_start;
1366 else
1367 b = segstart;
1368
1369 if (segend >= extra->killpad_end)
1370 e = extra->killpad_end;
1371 else
1372 e = segend;
1373
1374 res = munmap(b, (char *)e-(char *)b);
1375 vg_assert(0 == res);
1376
1377 return 1;
1378}
1379
1380// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001381static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001382{
1383 static struct stat padstat;
1384 killpad_extra extra;
1385 int res;
1386
sewardjb5f6f512005-03-10 23:59:00 +00001387 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001388
1389 res = fstat(padfile, &padstat);
1390 vg_assert(0 == res);
1391 extra.killpad_padstat = &padstat;
1392 extra.killpad_start = start;
1393 extra.killpad_end = end;
1394 foreach_map(killpad, &extra);
1395}
1396
sewardj2c5ffbe2005-03-12 13:32:06 +00001397static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001398{
1399 int res = close(padfile);
1400 vg_assert(0 == res);
1401}
1402
nethercote71980f02004-01-24 18:18:54 +00001403
1404/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001405/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001406/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001407
njn25e49d8e72002-09-23 09:36:25 +00001408/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001409VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001410Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001411Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001412Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001413Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001414Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001415Int VG_(clo_verbosity) = 1;
1416Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001417Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001418
nethercotef1e5e152004-09-01 23:58:16 +00001419/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001420 fd is initially stdout, for --help, but gets moved to stderr by default
1421 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001422VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001423Int VG_(clo_log_fd) = 1;
1424Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001425
thughes6233a382004-08-21 11:10:44 +00001426Bool VG_(clo_time_stamp) = False;
1427
sewardj6024b212003-07-13 10:54:33 +00001428Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001429Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001430Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001431Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001432UChar VG_(clo_trace_flags) = 0; // 00000000b
1433UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001434Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001435Bool VG_(clo_trace_syscalls) = False;
1436Bool VG_(clo_trace_signals) = False;
1437Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001438Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001439Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001440Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001441Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001442Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001443Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001444Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001445Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001446Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001447Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001448Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001449Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001450Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001451Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001452Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001453
jsgf855d93d2003-10-13 22:26:55 +00001454static Bool VG_(clo_wait_for_gdb) = False;
1455
sewardjde4a1d02002-03-22 01:27:54 +00001456
sewardj2c5ffbe2005-03-12 13:32:06 +00001457static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001458{
njn25e49d8e72002-09-23 09:36:25 +00001459 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001460"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001461"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001462" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001463" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001464" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001465" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001466" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001467" -q --quiet run silently; only print error msgs\n"
1468" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001469" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001470" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001471" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001472"\n"
1473" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001474" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001475" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001476" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001477" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001478" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001479"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001480" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001481" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1482" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001483" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001484" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001485" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001486" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001487" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1488" --show-below-main=no|yes continue stack traces below main() [no]\n"
1489" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001490" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001491" --db-attach=no|yes start debugger when errors detected? [no]\n"
1492" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1493" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001494" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1495" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001496"\n";
njn7cf0bd32002-06-08 13:36:03 +00001497
njn25e49d8e72002-09-23 09:36:25 +00001498 Char* usage2 =
1499"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001500" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001501" --sanity-level=<number> level of sanity checking to do [1]\n"
1502" --single-step=no|yes translate each instr separately? [no]\n"
1503" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001504" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001505" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001506" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1507" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001508" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001509" --trace-syscalls=no|yes show all system calls? [no]\n"
1510" --trace-signals=no|yes show signal handling details? [no]\n"
1511" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001512" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001513" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001514#if 0
1515" --model-pthreads=yes|no model the pthreads library [no]\n"
1516#endif
1517" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001518"\n"
1519" --vex-iropt-verbosity 0 .. 9 [0]\n"
1520" --vex-iropt-level 0 .. 2 [2]\n"
1521" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001522" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1523" --vex-guest-max-insns 1 .. 100 [50]\n"
1524" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1525"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001526" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001527" 1000 0000 show conversion into IR\n"
1528" 0100 0000 show after initial opt\n"
1529" 0010 0000 show after instrumentation\n"
1530" 0001 0000 show after second opt\n"
1531" 0000 1000 show after tree building\n"
1532" 0000 0100 show selecting insns\n"
1533" 0000 0010 show after reg-alloc\n"
1534" 0000 0001 show final assembly\n"
1535"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001536" debugging options for Valgrind tools that report errors\n"
1537" --dump-error=<number> show translation for basic block associated\n"
1538" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001539"\n";
njn3e884182003-04-15 13:03:23 +00001540
1541 Char* usage3 =
1542"\n"
nethercote71980f02004-01-24 18:18:54 +00001543" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001544"\n"
njn53612422005-03-12 16:22:54 +00001545" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001546" and licensed under the GNU General Public License, version 2.\n"
1547" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001548"\n"
nethercote137bc552003-11-14 17:47:54 +00001549" Tools are copyright and licensed by their authors. See each\n"
1550" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001551"\n";
njn7cf0bd32002-06-08 13:36:03 +00001552
fitzhardinge98abfc72003-12-16 02:05:15 +00001553 VG_(printf)(usage1);
1554 if (VG_(details).name) {
1555 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001556 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001557 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001558 else
1559 VG_(printf)(" (none)\n");
1560 }
nethercote6c999f22004-01-31 22:55:15 +00001561 if (debug_help) {
1562 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001563
nethercote6c999f22004-01-31 22:55:15 +00001564 if (VG_(details).name) {
1565 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1566
1567 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001568 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001569 else
1570 VG_(printf)(" (none)\n");
1571 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001572 }
nethercote421281e2003-11-20 16:20:55 +00001573 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001574 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001575}
sewardjde4a1d02002-03-22 01:27:54 +00001576
nethercote71980f02004-01-24 18:18:54 +00001577static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001578 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001579{
nethercote71980f02004-01-24 18:18:54 +00001580 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001581
sewardj8b635a42004-11-22 19:01:47 +00001582 LibVEX_default_VexControl(& VG_(clo_vex_control));
1583
nethercote71980f02004-01-24 18:18:54 +00001584 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001585 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001586
nethercotef6a1d502004-08-09 12:21:57 +00001587 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001588 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001589 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001590
nethercotef6a1d502004-08-09 12:21:57 +00001591 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1592 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001593 *need_help = 1;
1594
nethercotef6a1d502004-08-09 12:21:57 +00001595 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001596 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001597
nethercotef6c99d72004-11-09 14:35:43 +00001598 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001599 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001600
nethercotef6a1d502004-08-09 12:21:57 +00001601 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1602 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001603 }
1604 }
nethercote71980f02004-01-24 18:18:54 +00001605}
1606
nethercote5ee67ca2004-06-22 14:00:09 +00001607static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001608{
nethercotef8548672004-06-21 12:42:35 +00001609 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001610 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001611
nethercotee1730692003-11-20 10:38:07 +00001612 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001613 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001614
sewardj19d81412002-06-03 01:10:40 +00001615 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001616 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001617 config_error("Please use absolute paths in "
1618 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001619
njnc6168192004-11-29 13:54:10 +00001620// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001621#ifdef __x86__
1622 {
sewardjb5f6f512005-03-10 23:59:00 +00001623 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001624 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1625 switch(auxp[0]) {
1626 case AT_SYSINFO:
1627 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1628 break;
1629 }
1630 }
1631 }
1632#endif
sewardjde4a1d02002-03-22 01:27:54 +00001633
nethercotef6a1d502004-08-09 12:21:57 +00001634 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001635
nethercotef6a1d502004-08-09 12:21:57 +00001636 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001637 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001638
thughes3bfd5a02004-07-18 08:05:44 +00001639 /* Look for a colon in the switch name */
1640 while (*colon && *colon != ':' && *colon != '=')
1641 colon++;
nethercote71980f02004-01-24 18:18:54 +00001642
1643 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001644 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001645 if (VG_CLO_STREQN(2, arg, "--") &&
1646 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1647 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1648 {
1649 // prefix matches, convert "--toolname:foo" to "--foo"
1650 if (0)
1651 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001652 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001653 arg[0] = '-';
1654 arg[1] = '-';
1655
1656 } else {
1657 // prefix doesn't match, skip to next arg
1658 continue;
1659 }
1660 }
1661
fitzhardinge98abfc72003-12-16 02:05:15 +00001662 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001663 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1664 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1665 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001666
njn45270a22005-03-27 01:00:11 +00001667 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001668
nethercote71980f02004-01-24 18:18:54 +00001669 else if (VG_CLO_STREQ(arg, "-v") ||
1670 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001671 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001672
nethercote71980f02004-01-24 18:18:54 +00001673 else if (VG_CLO_STREQ(arg, "-q") ||
1674 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001675 VG_(clo_verbosity)--;
1676
sewardj1cf558c2005-04-25 01:36:56 +00001677 else if (VG_CLO_STREQ(arg, "-d")) {
1678 /* do nothing */
1679 }
1680
njn45270a22005-03-27 01:00:11 +00001681 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1682 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1683 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1684 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1685 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1686 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1687 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001688 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001689 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1690 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1691 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1692 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1693 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1694 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1695 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1696 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1697 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
1698 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1699 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1700 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1701 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1702 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001703
njn45270a22005-03-27 01:00:11 +00001704 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1705 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001706
njn45270a22005-03-27 01:00:11 +00001707 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1708 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1709 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1710 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1711 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001712
njn45270a22005-03-27 01:00:11 +00001713 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001714 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001715 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001716 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001717 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001718 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001719 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001720 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001721 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001722 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001723 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001724 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1725
nethercotef8548672004-06-21 12:42:35 +00001726 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1727 VG_(clo_log_to) = VgLogTo_Fd;
1728 VG_(clo_log_name) = NULL;
1729 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001730 }
1731
nethercotef8548672004-06-21 12:42:35 +00001732 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1733 VG_(clo_log_to) = VgLogTo_File;
1734 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001735 }
njnd6bc3c32005-03-27 00:44:31 +00001736
sewardj603d4102005-01-11 14:01:02 +00001737 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1738 VG_(clo_log_to) = VgLogTo_FileExactly;
1739 VG_(clo_log_name) = &arg[19];
1740 }
sewardjde4a1d02002-03-22 01:27:54 +00001741
nethercotef8548672004-06-21 12:42:35 +00001742 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1743 VG_(clo_log_to) = VgLogTo_Socket;
1744 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001745 }
1746
nethercote71980f02004-01-24 18:18:54 +00001747 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001748 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001749 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001750 VG_(message)(Vg_UserMsg,
1751 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001752 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001753 }
nethercote71980f02004-01-24 18:18:54 +00001754 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001755 VG_(clo_n_suppressions)++;
1756 }
sewardjde4a1d02002-03-22 01:27:54 +00001757
sewardjfa8ec112005-01-19 11:55:34 +00001758 /* "stuvwxyz" --> stuvwxyz (binary) */
1759 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1760 Int j;
1761 char* opt = & arg[14];
1762
1763 if (8 != VG_(strlen)(opt)) {
1764 VG_(message)(Vg_UserMsg,
1765 "--trace-flags argument must have 8 digits");
1766 VG_(bad_option)(arg);
1767 }
1768 for (j = 0; j < 8; j++) {
1769 if ('0' == opt[j]) { /* do nothing */ }
1770 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1771 else {
1772 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1773 "contain 0s and 1s");
1774 VG_(bad_option)(arg);
1775 }
1776 }
1777 }
1778
1779 /* "stuvwxyz" --> stuvwxyz (binary) */
1780 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001781 Int j;
nethercote71980f02004-01-24 18:18:54 +00001782 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001783
sewardj2a99cf62004-11-24 10:44:19 +00001784 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001785 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001786 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001787 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001788 }
sewardj8b635a42004-11-22 19:01:47 +00001789 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001790 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001791 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001792 else {
sewardjfa8ec112005-01-19 11:55:34 +00001793 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001794 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001795 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001796 }
1797 }
1798 }
sewardjde4a1d02002-03-22 01:27:54 +00001799
njn45270a22005-03-27 01:00:11 +00001800 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001801
sewardjd153fae2005-01-10 17:24:47 +00001802 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1803 VG_(clo_gen_suppressions) = 0;
1804 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1805 VG_(clo_gen_suppressions) = 1;
1806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1807 VG_(clo_gen_suppressions) = 2;
1808
nethercote71980f02004-01-24 18:18:54 +00001809 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001810 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001811 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001812 }
njn8c0b3bb2005-03-12 21:20:39 +00001813 skip_arg:
1814 if (arg != vg_argv[i])
1815 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001816 }
1817
sewardj998d40d2004-12-06 14:24:52 +00001818 /* Make VEX control parameters sane */
1819
1820 if (VG_(clo_vex_control).guest_chase_thresh
1821 >= VG_(clo_vex_control).guest_max_insns)
1822 VG_(clo_vex_control).guest_chase_thresh
1823 = VG_(clo_vex_control).guest_max_insns - 1;
1824
1825 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1826 VG_(clo_vex_control).guest_chase_thresh = 0;
1827
1828 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001829
njnf9ebf672003-05-12 21:41:30 +00001830 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(clo_verbosity) = 0;
1832
nethercote04d0fbc2004-01-26 16:48:06 +00001833 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001834 VG_(message)(Vg_UserMsg, "");
1835 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001836 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001837 VG_(message)(Vg_UserMsg,
1838 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001839 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001840 }
1841
nethercotef8548672004-06-21 12:42:35 +00001842 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001843 should be connected to whatever sink has been selected, and we
1844 indiscriminately chuck stuff into it without worrying what the
1845 nature of it is. Oh the wonder of Unix streams. */
1846
nethercotee1730692003-11-20 10:38:07 +00001847 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001848 the terminal any problems to do with processing command line
1849 opts. */
nethercotef8548672004-06-21 12:42:35 +00001850 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001851 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001852
1853 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001854
sewardj4cf05692002-10-27 20:28:29 +00001855 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001856 vg_assert(VG_(clo_log_name) == NULL);
1857 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001858 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001859
sewardj4cf05692002-10-27 20:28:29 +00001860 case VgLogTo_File: {
1861 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001862 Int seq = 0;
1863 Int pid = VG_(getpid)();
1864
nethercotef8548672004-06-21 12:42:35 +00001865 vg_assert(VG_(clo_log_name) != NULL);
1866 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001867
nethercote71980f02004-01-24 18:18:54 +00001868 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001869 if (seq == 0)
1870 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001871 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001872 else
1873 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001874 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001875 seq++;
1876
nethercotef8548672004-06-21 12:42:35 +00001877 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001878 = VG_(open)(logfilename,
1879 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1880 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001881 if (eventually_log_fd >= 0) {
1882 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001883 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001884 } else {
nethercotef8548672004-06-21 12:42:35 +00001885 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001886 VG_(message)(Vg_UserMsg,
1887 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001888 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001889 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001890 "--log-file=<file> (didn't work out for some reason.)");
1891 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001892 }
1893 }
1894 }
sewardj603d4102005-01-11 14:01:02 +00001895 break; /* switch (VG_(clo_log_to)) */
1896 }
1897
1898 case VgLogTo_FileExactly: {
1899 Char logfilename[1000];
1900
1901 vg_assert(VG_(clo_log_name) != NULL);
1902 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1903 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1904
1905 eventually_log_fd
1906 = VG_(open)(logfilename,
1907 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1908 VKI_S_IRUSR|VKI_S_IWUSR);
1909 if (eventually_log_fd >= 0) {
1910 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1911 }
1912 else if (eventually_log_fd != -VKI_EEXIST) {
1913 VG_(message)(Vg_UserMsg,
1914 "Can't create/open log file `%s'; giving up!",
1915 VG_(clo_log_name));
1916 VG_(bad_option)(
1917 "--log-file-exactly=<file> (didn't work out for some reason.)");
1918 /*NOTREACHED*/
1919 }
1920 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001921 }
1922
1923 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001924 vg_assert(VG_(clo_log_name) != NULL);
1925 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1926 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1927 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001928 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001929 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001930 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001931 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001932 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001933 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001934 }
nethercotef8548672004-06-21 12:42:35 +00001935 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001937 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001938 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001939 VG_(message)(Vg_UserMsg,
1940 "Log messages will sent to stderr instead." );
1941 VG_(message)(Vg_UserMsg,
1942 "" );
1943 /* We don't change anything here. */
1944 } else {
nethercotef8548672004-06-21 12:42:35 +00001945 vg_assert(eventually_log_fd > 0);
1946 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001947 VG_(logging_to_filedes) = False;
1948 }
sewardj73cf3bc2002-11-03 03:20:15 +00001949 break;
1950 }
1951
sewardj4cf05692002-10-27 20:28:29 +00001952 }
1953
nethercotef8548672004-06-21 12:42:35 +00001954 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001955 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001956 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001957 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1958 else {
nethercotef8548672004-06-21 12:42:35 +00001959 VG_(clo_log_fd) = eventually_log_fd;
1960 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001961 }
1962
sewardj4cf05692002-10-27 20:28:29 +00001963 /* Ok, the logging sink is running now. Print a suitable preamble.
1964 If logging to file or a socket, write details of parent PID and
1965 command line args, to help people trying to interpret the
1966 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001967
sewardj83adf412002-05-01 01:25:45 +00001968 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001969 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001970 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001971 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001972 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001973 NULL == VG_(details).version
1974 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001975 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001976 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001977
njnd04b7c62002-10-03 14:05:52 +00001978 /* Core details */
1979 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001980 "Using LibVEX rev %s, a library for dynamic binary translation.",
1981 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001982 VG_(message)(Vg_UserMsg,
1983 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1984 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001985 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001986 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001987 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001988 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001989 }
1990
nethercotec1e395d2003-11-10 13:26:49 +00001991 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001992 VG_(message)(Vg_UserMsg, "");
1993 VG_(message)(Vg_UserMsg,
1994 "My PID = %d, parent PID = %d. Prog and args are:",
1995 VG_(getpid)(), VG_(getppid)() );
1996 for (i = 0; i < VG_(client_argc); i++)
1997 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1998 }
1999
sewardjde4a1d02002-03-22 01:27:54 +00002000 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002001 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002002 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002003 VG_(message)(Vg_DebugMsg, "");
2004 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2005 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002006 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002007 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002008
njn1fd5eb22005-03-13 05:43:23 +00002009 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002010 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002012 }
nethercotea70f7352004-04-18 12:08:46 +00002013
njn1fd5eb22005-03-13 05:43:23 +00002014 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002015 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2016 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002017 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002018 } else {
2019 #define BUF_LEN 256
2020 Char version_buf[BUF_LEN];
2021 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2022 vg_assert(n <= 256);
2023 if (n > 0) {
2024 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002025 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002026 } else {
njn1fd5eb22005-03-13 05:43:23 +00002027 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002028 }
2029 VG_(close)(fd);
2030 #undef BUF_LEN
2031 }
sewardjde4a1d02002-03-22 01:27:54 +00002032 }
2033
fitzhardinge98abfc72003-12-16 02:05:15 +00002034 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002035 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002036 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002037 needs one, load the default */
2038 static const Char default_supp[] = "default.supp";
2039 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2040 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2041 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2042 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2043 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002044 }
sewardj4cf05692002-10-27 20:28:29 +00002045
sewardjd153fae2005-01-10 17:24:47 +00002046 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002047 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002048 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002049 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002050 VG_(message)(Vg_UserMsg,
2051 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002052 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002053 }
sewardjde4a1d02002-03-22 01:27:54 +00002054}
2055
nethercotef6a1d502004-08-09 12:21:57 +00002056// Build the string for VALGRINDCLO.
2057Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2058{
2059 /* If we're tracing the children, then we need to start it
2060 with our starter+arguments, which are copied into VALGRINDCLO,
2061 except the --exec= option is changed if present.
2062 */
2063 Int i;
2064 Char *exec;
2065 Char *cp;
2066 Char *optvar;
2067 Int optlen, execlen;
2068
2069 // All these allocated blocks are not free - because we're either
2070 // going to exec, or panic when we fail.
2071
2072 // Create --exec= option: "--exec=<exename>"
2073 exec = VG_(arena_malloc)(VG_AR_CORE,
2074 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2075 vg_assert(NULL != exec);
2076 VG_(sprintf)(exec, "--exec=%s", exename);
2077
2078 // Allocate space for optvar (may overestimate by counting --exec twice,
2079 // no matter)
2080 optlen = 1;
2081 for (i = 0; i < vg_argc; i++)
2082 optlen += VG_(strlen)(vg_argv[i]) + 1;
2083 optlen += VG_(strlen)(exec)+1;
2084 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2085
2086 // Copy all valgrind args except the old --exec (if present)
2087 // VG_CLO_SEP is the separator.
2088 cp = optvar;
2089 for (i = 1; i < vg_argc; i++) {
2090 Char *arg = vg_argv[i];
2091
2092 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2093 // don't copy existing --exec= arg
2094 } else if (VG_(strcmp)(arg, "--") == 0) {
2095 // stop at "--"
2096 break;
2097 } else {
2098 // copy non "--exec" arg
2099 Int len = VG_(strlen)(arg);
2100 VG_(memcpy)(cp, arg, len);
2101 cp += len;
2102 *cp++ = VG_CLO_SEP;
2103 }
2104 }
2105 // Add the new --exec= option
2106 execlen = VG_(strlen)(exec);
2107 VG_(memcpy)(cp, exec, execlen);
2108 cp += execlen;
2109 *cp++ = VG_CLO_SEP;
2110
2111 *cp = '\0';
2112
2113 return optvar;
2114}
2115
2116// Build "/proc/self/fd/<execfd>".
2117Char* VG_(build_child_exename)( void )
2118{
2119 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2120 vg_assert(NULL != exename);
2121 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2122 return exename;
2123}
2124
sewardjde4a1d02002-03-22 01:27:54 +00002125
nethercote71980f02004-01-24 18:18:54 +00002126/*====================================================================*/
2127/*=== File descriptor setup ===*/
2128/*====================================================================*/
2129
2130static void setup_file_descriptors(void)
2131{
2132 struct vki_rlimit rl;
2133
2134 /* Get the current file descriptor limits. */
2135 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2136 rl.rlim_cur = 1024;
2137 rl.rlim_max = 1024;
2138 }
2139
2140 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002141 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2142 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002143 } else {
2144 rl.rlim_cur = rl.rlim_max;
2145 }
2146
2147 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002148 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2149 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002150
2151 /* Update the soft limit. */
2152 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2153
nethercotef6a1d502004-08-09 12:21:57 +00002154 if (vgexecfd != -1)
2155 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002156 if (VG_(clexecfd) != -1)
2157 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2158}
2159
nethercote71980f02004-01-24 18:18:54 +00002160/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002161/*=== Initialise program data/text, etc. ===*/
2162/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002163
sewardjb5f6f512005-03-10 23:59:00 +00002164static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2165 UInt dev, UInt ino, ULong foffset,
2166 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002167{
nethercote71980f02004-01-24 18:18:54 +00002168 /* Only record valgrind mappings for now, without loading any
2169 symbols. This is so we know where the free space is before we
2170 start allocating more memory (note: heap is OK, it's just mmap
2171 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002172 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002173 VG_(debugLog)(2, "main",
2174 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
2175 start, start+size, prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002176 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002177 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2178 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002179 /* update VG_(valgrind_last) if it looks wrong */
2180 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002181 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002182 }
sewardjde4a1d02002-03-22 01:27:54 +00002183}
2184
nethercote71980f02004-01-24 18:18:54 +00002185// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002186Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002187
sewardjb5f6f512005-03-10 23:59:00 +00002188/*
2189 This second pass adds in client mappings, and loads symbol tables
2190 for all interesting mappings. The trouble is that things can
2191 change as we go, because we're calling the Tool to track memory as
2192 we find it.
2193
2194 So for Valgrind mappings, we don't replace any mappings which
2195 aren't still identical (which will include the .so mappings, so we
2196 will load their symtabs)>
2197 */
2198static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2199 UInt dev, UInt ino, ULong foffset,
2200 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002201{
nethercote71980f02004-01-24 18:18:54 +00002202 UInt flags;
2203 Bool is_stack_segment;
2204 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002205
nethercote71980f02004-01-24 18:18:54 +00002206 is_stack_segment
2207 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002208
sewardj8c615892005-04-25 02:38:28 +00002209 VG_(debugLog)(2, "main",
2210 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
2211 start, start+size, prot, is_stack_segment, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002212
nethercote71980f02004-01-24 18:18:54 +00002213 if (is_stack_segment)
2214 flags = SF_STACK | SF_GROWDOWN;
2215 else
2216 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002217
nethercote71980f02004-01-24 18:18:54 +00002218 if (filename != NULL)
2219 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002220
sewardjb5f6f512005-03-10 23:59:00 +00002221#if 0
2222 // This needs to be fixed properly. jrs 20050307
2223 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2224 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002225
sewardjb5f6f512005-03-10 23:59:00 +00002226 /* We have to be a bit careful about inserting new mappings into
2227 the Valgrind part of the address space. We're actively
2228 changing things as we parse these mappings, particularly in
2229 shadow memory, and so we don't want to overwrite those
2230 changes. Therefore, we only insert/update a mapping if it is
2231 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002232
sewardjb5f6f512005-03-10 23:59:00 +00002233 NOTE: we're only talking about the Segment list mapping
2234 metadata; this doesn't actually mmap anything more. */
2235 if (filename || (s && s->addr == start && s->len == size)) {
2236 flags |= SF_VALGRIND;
2237 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2238 } else {
2239 /* assert range is already mapped */
2240 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2241 }
2242 } else
2243#endif
2244 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2245
2246 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2247 VG_TRACK( new_mem_startup, start, size,
2248 !!(prot & VKI_PROT_READ),
2249 !!(prot & VKI_PROT_WRITE),
2250 !!(prot & VKI_PROT_EXEC));
2251 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002252
nethercote71980f02004-01-24 18:18:54 +00002253 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002254 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002255 vg_assert(0 != r_esp);
2256 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002257 if (0) {
2258 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002259 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002260 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2261 r_esp, start+size);
2262 }
nethercote71980f02004-01-24 18:18:54 +00002263 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002264 // what's this for?
2265 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002266 }
sewardjde4a1d02002-03-22 01:27:54 +00002267}
2268
2269
nethercote71980f02004-01-24 18:18:54 +00002270/*====================================================================*/
2271/*=== Sanity check machinery (permanently engaged) ===*/
2272/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002273
2274/* A fast sanity check -- suitable for calling circa once per
2275 millisecond. */
2276
nethercote885dd912004-08-03 23:14:00 +00002277void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002278{
sewardjb5f6f512005-03-10 23:59:00 +00002279 ThreadId tid;
2280
njn37cea302002-09-30 11:24:00 +00002281 VGP_PUSHCC(VgpCoreCheapSanity);
2282
nethercote27fec902004-06-16 21:26:32 +00002283 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002284
2285 /* --- First do all the tests that we can do quickly. ---*/
2286
nethercote297effd2004-08-02 15:07:57 +00002287 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002288
njn25e49d8e72002-09-23 09:36:25 +00002289 /* Check stuff pertaining to the memory check system. */
2290
2291 /* Check that nobody has spuriously claimed that the first or
2292 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002293 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002294 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002295 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002296 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002297 }
njn25e49d8e72002-09-23 09:36:25 +00002298
2299 /* --- Now some more expensive checks. ---*/
2300
2301 /* Once every 25 times, check some more expensive stuff. */
2302 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002303 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002304 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002305
njn37cea302002-09-30 11:24:00 +00002306 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002307 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002308
2309# if 0
2310 { void zzzmemscan(void); zzzmemscan(); }
2311# endif
2312
nethercote297effd2004-08-02 15:07:57 +00002313 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002314 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002315
2316 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002317 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002318 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002319 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002320 }
sewardjb5f6f512005-03-10 23:59:00 +00002321
2322 /* Check that Segments and /proc/self/maps match up */
2323 //vg_assert(VG_(sanity_check_memory)());
2324
2325 /* Look for stack overruns. Visit all threads. */
2326 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002327 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002328
2329 if (VG_(threads)[tid].status == VgTs_Empty ||
2330 VG_(threads)[tid].status == VgTs_Zombie)
2331 continue;
2332
2333 remains = VGA_(stack_unused)(tid);
2334 if (remains < VKI_PAGE_SIZE)
2335 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2336 tid, remains);
2337 }
2338
njn25e49d8e72002-09-23 09:36:25 +00002339 /*
nethercote297effd2004-08-02 15:07:57 +00002340 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002341 */
njn37cea302002-09-30 11:24:00 +00002342 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002343 }
2344
nethercote27fec902004-06-16 21:26:32 +00002345 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002346 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002347 /* Check sanity of the low-level memory manager. Note that bugs
2348 in the client's code can cause this to fail, so we don't do
2349 this check unless specially asked for. And because it's
2350 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002351 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002352 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002353 }
njn37cea302002-09-30 11:24:00 +00002354 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002355}
nethercote71980f02004-01-24 18:18:54 +00002356
2357
2358/*====================================================================*/
2359/*=== main() ===*/
2360/*====================================================================*/
2361
nethercotec314eba2004-07-15 12:59:41 +00002362/*
2363 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002364 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002365 loads the client executable (and the dynamic linker, if necessary)
2366 into the client part, and calls into Valgrind proper.
2367
2368 The code is careful not to allow spurious mappings to appear in the
2369 wrong parts of the address space. In particular, to make sure
2370 dlopen puts things in the right place, it will pad out the forbidden
2371 chunks of address space so that dlopen is forced to put things where
2372 we want them.
2373
2374 The memory map it creates is:
2375
njn80950732005-03-26 00:18:45 +00002376 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002377 | client address space |
2378 : :
2379 : :
2380 | client stack |
2381 client_end +-------------------------+
2382 | redzone |
2383 shadow_base +-------------------------+
2384 | |
nethercote996901a2004-08-03 13:29:09 +00002385 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002386 | (may be 0 sized) |
2387 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002388 valgrind_base +-------------------------+
2389 | kickstart executable |
2390 | valgrind heap vvvvvvvvv| (barely used)
2391 - -
2392 | valgrind .so files |
2393 | and mappings |
2394 - -
2395 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002396 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002397 : kernel :
2398
2399 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2400 VG_(mmap)(), we need to build the segment skip-list, so we know where
2401 we can put things. However, building that structure requires
2402 allocating memory. So we need to a bootstrapping process. It's done
2403 by making VG_(arena_malloc)() have a special static superblock that's
2404 used for the first 1MB's worth of allocations. This is enough to
2405 build the segment skip-list.
2406*/
2407
thughes4ad52d02004-06-27 17:37:21 +00002408
sewardj1cf558c2005-04-25 01:36:56 +00002409/* This may be needed before m_mylibc is OK to run. */
2410static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2411{
2412 while (True) {
2413 if (*s1 == 0 && *s2 == 0) return 0;
2414 if (*s1 == 0) return -1;
2415 if (*s2 == 0) return 1;
2416
2417 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2418 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2419
2420 s1++; s2++;
2421 }
2422}
2423
2424
sewardjb5f6f512005-03-10 23:59:00 +00002425int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002426{
2427 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002428 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002429 const char *exec = NULL;
2430 char *preload; /* tool-specific LD_PRELOAD .so */
2431 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002432 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002433 struct exeinfo info;
2434 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002435 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002436 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002437 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002438 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002439 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002440
2441 //============================================================
2442 // Nb: startup is complex. Prerequisites are shown at every step.
2443 //
2444 // *** Be very careful when messing with the order ***
2445 //============================================================
2446
sewardj1cf558c2005-04-25 01:36:56 +00002447 //--------------------------------------------------------------
2448 // Start up the logging mechanism
2449 // p: none
2450 //--------------------------------------------------------------
2451 /* Start the debugging-log system ASAP. First find out how many
2452 "-d"s were specified. This is a pre-scan of the command line. */
2453 loglevel = 0;
2454 for (i = 1; i < argc; i++) {
2455 if (argv[i][0] != '-')
2456 break;
2457 if (0 == local_strcmp(argv[i], "--"))
2458 break;
2459 if (0 == local_strcmp(argv[i], "-d"))
2460 loglevel++;
2461 }
2462
2463 /* ... and start the debug logger. Now we can safely emit logging
2464 messages all through startup. */
2465 VG_(debugLog_startup)(loglevel, "Stage 2");
2466
nethercotef4928da2004-06-15 10:54:40 +00002467 //============================================================
2468 // Command line argument handling order:
2469 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002470 // (including the tool-specific usage)
2471 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002472 // * Then, if client is missing, abort with error msg
2473 // * Then, if any cmdline args are bad, abort with error msg
2474 //============================================================
2475
fitzhardingeb50068f2004-02-24 23:42:55 +00002476 // Get the current process datasize rlimit, and set it to zero.
2477 // This prevents any internal uses of brk() from having any effect.
2478 // We remember the old value so we can restore it on exec, so that
2479 // child processes will have a reasonable brk value.
2480 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2481 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2482 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002483
2484 // Get the current process stack rlimit.
2485 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2486
nethercote71980f02004-01-24 18:18:54 +00002487 //--------------------------------------------------------------
2488 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002489 // p: none
nethercote71980f02004-01-24 18:18:54 +00002490 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002491 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002492 {
sewardj1fbc1a52005-04-25 02:05:54 +00002493 void* init_sp = argv - 1;
2494 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002495 }
2496
2497 //--------------------------------------------------------------
2498 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002499 // p: none
nethercote71980f02004-01-24 18:18:54 +00002500 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002501 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002502 if (cp != NULL)
2503 VG_(libdir) = cp;
2504 }
2505
2506 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002507 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2508 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002509 // p: none
nethercote71980f02004-01-24 18:18:54 +00002510 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002511 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002512 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002513 pre_process_cmd_line_options(&need_help, &tool, &exec);
2514
2515 //==============================================================
2516 // Nb: once a tool is specified, the tool.so must be loaded even if
2517 // they specified --help or didn't specify a client program.
2518 //==============================================================
2519
2520 //--------------------------------------------------------------
2521 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002522 // p: set-libdir [for VG_(libdir)]
2523 // p: pre_process_cmd_line_options() [for 'tool']
2524 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002525 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002526 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002527
2528 //==============================================================
2529 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002530 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002531 //==============================================================
2532
2533 //--------------------------------------------------------------
2534 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002535 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002536 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002537 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002538 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002539
2540 //--------------------------------------------------------------
2541 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002542 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2543 // p: layout_remaining_space [so there's space]
2544 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002545 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002546 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002547
2548 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002549 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002550 // p: layout_remaining_space() [everything must be mapped in before now]
2551 // p: load_client() [ditto]
2552 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002553 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2554 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002555
2556 //--------------------------------------------------------------
2557 // Set up client's environment
2558 // p: set-libdir [for VG_(libdir)]
2559 // p: load_tool() [for 'preload']
2560 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002561 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002562 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002563
2564 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002565 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002566 // p: load_client() [for 'info']
2567 // p: fix_environment() [for 'env']
2568 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002569 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002570 {
sewardj1fbc1a52005-04-25 02:05:54 +00002571 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002572
sewardj1fbc1a52005-04-25 02:05:54 +00002573 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2574 &client_auxv);
2575 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002576 }
nethercote71980f02004-01-24 18:18:54 +00002577
sewardj1fbc1a52005-04-25 02:05:54 +00002578 VG_(debugLog)(2, "main",
2579 "Client info: "
2580 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2581 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2582 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002583
2584 //==============================================================
2585 // Finished setting up operating environment. Now initialise
2586 // Valgrind. (This is where the old VG_(main)() started.)
2587 //==============================================================
2588
2589 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002590 // setup file descriptors
2591 // p: n/a
2592 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002593 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002594 setup_file_descriptors();
2595
2596 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002597 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002598 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002599 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002600 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002601 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2602
2603 //==============================================================
2604 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2605 //==============================================================
2606
2607 //--------------------------------------------------------------
2608 // Init tool: pre_clo_init, process cmd line, post_clo_init
2609 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002610 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002611 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2612 // p: parse_procselfmaps [so VG segments are setup so tool can
2613 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002614 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002615 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002616 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002617 VG_(sanity_check_needs)();
2618
nethercotef4928da2004-06-15 10:54:40 +00002619 // If --tool and --help/--help-debug was given, now give the core+tool
2620 // help message
nethercotef4928da2004-06-15 10:54:40 +00002621 if (need_help) {
2622 usage(/*--help-debug?*/2 == need_help);
2623 }
nethercotec314eba2004-07-15 12:59:41 +00002624 process_cmd_line_options(client_auxv, tool);
2625
njn26f02512004-11-22 18:33:15 +00002626 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002627
2628 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002629 // Determine CPU architecture and subarchitecture
2630 // p: none
2631 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002632 VG_(debugLog)(1, "main", "Check CPU arch/subarch\n");
sewardj51ac0872004-12-21 01:20:49 +00002633 { Bool ok = VGA_(getArchAndSubArch)(
2634 & VG_(vex_arch), & VG_(vex_subarch) );
2635 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002636 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002637 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002638 VG_(printf)(" Supported CPUs are:\n");
2639 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2640 "AMD Athlon or above)\n");
2641 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002642 VG_(exit)(1);
2643 }
2644 if (VG_(clo_verbosity) > 2) {
2645 VG_(message)(Vg_DebugMsg,
2646 "Host CPU: arch = %s, subarch = %s",
2647 LibVEX_ppVexArch( VG_(vex_arch) ),
2648 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2649 }
2650 }
2651
2652 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002653 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002654 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002655 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002656 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002657 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002658 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002659 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002660 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002661 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002662
sewardja4da2f32005-03-02 14:06:08 +00002663#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002664 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002665 // Protect client trampoline page (which is also sysinfo stuff)
2666 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002667 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002668 {
2669 Segment *seg;
2670 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2671 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002672#endif
sewardjb5f6f512005-03-10 23:59:00 +00002673 /* Make sure this segment isn't treated as stack */
2674 seg = VG_(find_segment)(VG_(client_trampoline_code));
2675 if (seg)
2676 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2677 }
2678
nethercotec314eba2004-07-15 12:59:41 +00002679 //==============================================================
2680 // Can use VG_(map)() after segments set up
2681 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002682
2683 //--------------------------------------------------------------
2684 // Allow GDB attach
2685 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2686 //--------------------------------------------------------------
2687 /* Hook to delay things long enough so we can get the pid and
2688 attach GDB in another shell. */
2689 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002690 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002691 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2692 /* jrs 20050206: I don't understand why this works on x86. On
2693 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2694 work. */
2695 /* do "jump *$eip" to skip this in gdb (x86) */
2696 //VG_(do_syscall0)(__NR_pause);
2697 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002698 }
2699
sewardjb5d320c2005-03-13 18:57:15 +00002700 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002701 // Search for file descriptors that are inherited from our parent
2702 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2703 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002704 if (VG_(clo_track_fds)) {
2705 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002706 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002707 }
nethercote71980f02004-01-24 18:18:54 +00002708
2709 //--------------------------------------------------------------
2710 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002711 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2712 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002713 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002714 VG_(scheduler_init)();
2715
2716 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002717 // Initialise the pthread model
2718 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002719 // load_client() [for 'client_eip']
2720 // setup_client_stack() [for 'sp_at_startup']
2721 // setup_scheduler() [for the rest of state 1 stuff]
2722 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002723 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002724 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002725
2726 // Tell the tool that we just wrote to the registers.
2727 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2728 sizeof(VexGuestArchState));
2729
sewardj2a99cf62004-11-24 10:44:19 +00002730 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002731 // Initialise the pthread model
2732 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002733 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002734 //if (VG_(clo_model_pthreads))
2735 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002736
2737 //--------------------------------------------------------------
2738 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002739 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002740 //--------------------------------------------------------------
2741 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002742 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002743 VG_(sigstartup_actions)();
2744
2745 //--------------------------------------------------------------
2746 // Perhaps we're profiling Valgrind?
2747 // p: process_cmd_line_options() [for VG_(clo_profile)]
2748 // p: others?
2749 //
2750 // XXX: this seems to be broken? It always says the tool wasn't built
2751 // for profiling; vg_profile.c's functions don't seem to be overriding
2752 // vg_dummy_profile.c's?
2753 //
2754 // XXX: want this as early as possible. Looking for --profile
2755 // in pre_process_cmd_line_options() could get it earlier.
2756 //--------------------------------------------------------------
2757 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002758 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002759
2760 VGP_PUSHCC(VgpStartup);
2761
2762 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002763 // Read suppression file
2764 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2765 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002766 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2767 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002768 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002769 }
nethercote71980f02004-01-24 18:18:54 +00002770
2771 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002772 // Initialise translation table and translation cache
2773 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2774 // aren't identified as part of the client, which would waste
2775 // > 20M of virtual address space.]
2776 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002777 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002778 VG_(init_tt_tc)();
2779
2780 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002781 // Read debug info to find glibc entry points to intercept
2782 // p: parse_procselfmaps? [XXX for debug info?]
2783 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2784 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002785 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002786 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002787 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002788
2789 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002790 // Verbosity message
2791 // p: end_rdtsc_calibration [so startup message is printed first]
2792 //--------------------------------------------------------------
2793 if (VG_(clo_verbosity) == 1)
2794 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2795 if (VG_(clo_verbosity) > 0)
2796 VG_(message)(Vg_UserMsg, "");
2797
2798 //--------------------------------------------------------------
2799 // Setup pointercheck
2800 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2801 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002802 if (VG_(clo_pointercheck))
2803 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002804
nethercote71980f02004-01-24 18:18:54 +00002805 //--------------------------------------------------------------
2806 // Run!
2807 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002808 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002809
sewardjb5f6f512005-03-10 23:59:00 +00002810 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002811
sewardj1fbc1a52005-04-25 02:05:54 +00002812 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002813 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002814
sewardjb5f6f512005-03-10 23:59:00 +00002815 abort();
2816}
2817
2818
2819/* Do everything which needs doing when the last thread exits */
2820void VG_(shutdown_actions)(ThreadId tid)
2821{
2822 vg_assert(tid == VG_(master_tid));
2823 vg_assert(VG_(is_running_thread)(tid));
2824
2825 // Wait for all other threads to exit.
2826 VGA_(reap_threads)(tid);
2827
2828 VG_(clo_model_pthreads) = False;
2829
2830 // Clean the client up before the final report
2831 VGA_(final_tidyup)(tid);
2832
2833 // OK, done
2834 VG_(exit_thread)(tid);
2835
2836 /* should be no threads left */
2837 vg_assert(VG_(count_living_threads)() == 0);
2838
2839 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002840 //--------------------------------------------------------------
2841 // Finalisation: cleanup, messages, etc. Order no so important, only
2842 // affects what order the messages come.
2843 //--------------------------------------------------------------
2844 if (VG_(clo_verbosity) > 0)
2845 VG_(message)(Vg_UserMsg, "");
2846
nethercote71980f02004-01-24 18:18:54 +00002847 /* Print out file descriptor summary and stats. */
2848 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002849 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002850
njn95ec8702004-11-22 16:46:13 +00002851 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002852 VG_(show_all_errors)();
2853
sewardjb5f6f512005-03-10 23:59:00 +00002854 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002855
nethercote885dd912004-08-03 23:14:00 +00002856 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002857
2858 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002859 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002860
nethercote71980f02004-01-24 18:18:54 +00002861 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002862 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002863 if (VG_(clo_profile_flags) > 0)
2864 VG_(show_BB_profile)();
2865
sewardj8b635a42004-11-22 19:01:47 +00002866 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002867 if (0)
2868 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002869
nethercote71980f02004-01-24 18:18:54 +00002870}
2871
sewardjde4a1d02002-03-22 01:27:54 +00002872/*--------------------------------------------------------------------*/
2873/*--- end vg_main.c ---*/
2874/*--------------------------------------------------------------------*/