blob: 71196fe10c9216db417e2273aa63e1b293f7c838 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
39#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000040#include "pub_core_tooliface.h"
nethercote71980f02004-01-24 18:18:54 +000041
42#include <dirent.h>
43#include <dlfcn.h>
44#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000045#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000046#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000047#include <string.h>
48#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000049#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000051#include <sys/wait.h>
52#include <unistd.h>
53
sewardjb5f6f512005-03-10 23:59:00 +000054#include "memcheck/memcheck.h"
55
thughes74b8de22004-04-22 18:12:31 +000056#ifndef AT_DCACHEBSIZE
57#define AT_DCACHEBSIZE 19
58#endif /* AT_DCACHEBSIZE */
59
60#ifndef AT_ICACHEBSIZE
61#define AT_ICACHEBSIZE 20
62#endif /* AT_ICACHEBSIZE */
63
64#ifndef AT_UCACHEBSIZE
65#define AT_UCACHEBSIZE 21
66#endif /* AT_UCACHEBSIZE */
67
nethercote71980f02004-01-24 18:18:54 +000068#ifndef AT_SYSINFO
69#define AT_SYSINFO 32
70#endif /* AT_SYSINFO */
71
72#ifndef AT_SYSINFO_EHDR
73#define AT_SYSINFO_EHDR 33
74#endif /* AT_SYSINFO_EHDR */
75
76#ifndef AT_SECURE
77#define AT_SECURE 23 /* secure mode boolean */
78#endif /* AT_SECURE */
79
nethercote71980f02004-01-24 18:18:54 +000080/* redzone gap between client address space and shadow */
81#define REDZONE_SIZE (1 * 1024*1024)
82
83/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000084#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000085
nethercotee2097312004-06-27 12:29:56 +000086/* Proportion of client space for its heap (rest is for mmaps + stack) */
87#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000088
njn14319cc2005-03-13 06:26:22 +000089/* Number of file descriptors that Valgrind tries to reserve for
90 it's own use - just a small constant. */
91#define N_RESERVED_FDS (10)
92
93/* Default debugger command. */
94#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
95
nethercote71980f02004-01-24 18:18:54 +000096/*====================================================================*/
97/*=== Global entities not referenced from generated code ===*/
98/*====================================================================*/
99
sewardjde4a1d02002-03-22 01:27:54 +0000100/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000101 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000102 ------------------------------------------------------------------ */
103
nethercote71980f02004-01-24 18:18:54 +0000104/* Client address space, lowest to highest (see top of ume.c) */
105Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(client_end);
107Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000108Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000109Addr VG_(clstk_base);
110Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000111
112Addr VG_(brk_base); /* start of brk */
113Addr VG_(brk_limit); /* current brk */
114
nethercote996901a2004-08-03 13:29:09 +0000115Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000116Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000117
118Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000119
nethercote820bd8c2004-09-07 23:04:49 +0000120// Note that VG_(valgrind_last) names the last byte of the section, whereas
121// the VG_(*_end) vars name the byte one past the end of the section.
122Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
nethercote73b526f2004-10-31 18:48:21 +0000124struct vki_rlimit VG_(client_rlimit_data);
125struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000126
fitzhardinge98abfc72003-12-16 02:05:15 +0000127/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000128static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000129
130/* client executable */
131Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000132
133/* Path to library directory */
134const Char *VG_(libdir) = VG_LIBDIR;
135
136/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000137static Int vg_argc;
138static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000139
sewardjb5f6f512005-03-10 23:59:00 +0000140/* The master thread the one which will be responsible for mopping
141 everything up at exit. Normally it is tid 1, since that's the
142 first thread created, but it may be something else after a
143 fork(). */
144ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000145
thughesad1c9562004-06-26 11:27:52 +0000146/* Application-visible file descriptor limits */
147Int VG_(fd_soft_limit) = -1;
148Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000149
nethercote4ad74312004-10-26 09:59:49 +0000150/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000151 envp[] as extracted from the client's stack at startup-time. */
152Int VG_(client_argc);
153Char** VG_(client_argv);
154Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000155
sewardj51ac0872004-12-21 01:20:49 +0000156/* Indicates what arch and subarch we are running on. */
157VexArch VG_(vex_arch) = VexArch_INVALID;
158VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
159
160
sewardjde4a1d02002-03-22 01:27:54 +0000161/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000162 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000163 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000164
nethercote71980f02004-01-24 18:18:54 +0000165/* Counts downwards in VG_(run_innerloop). */
166UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000167
168/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000169ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000170
nethercote71980f02004-01-24 18:18:54 +0000171/* Tell the logging mechanism whether we are logging to a file
172 descriptor or a socket descriptor. */
173Bool VG_(logging_to_filedes) = True;
174
sewardj73cf3bc2002-11-03 03:20:15 +0000175
nethercote71980f02004-01-24 18:18:54 +0000176/*====================================================================*/
177/*=== Counters, for profiling purposes only ===*/
178/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000179
sewardjde4a1d02002-03-22 01:27:54 +0000180/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000181static UInt sanity_fast_count = 0;
182static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000183
nethercote3a42fb82004-08-03 18:08:50 +0000184static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000185{
nethercote3a42fb82004-08-03 18:08:50 +0000186 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000187 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000188 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000189 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000190
nethercote3a42fb82004-08-03 18:08:50 +0000191 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000192 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000193
nethercote71980f02004-01-24 18:18:54 +0000194 VG_(message)(Vg_DebugMsg,
195 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000196 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000197
njn9271cbc2005-03-13 05:38:25 +0000198 VG_(print_ExeContext_stats)();
199
nethercote3a42fb82004-08-03 18:08:50 +0000200 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000201 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000202 VG_(message)(Vg_DebugMsg, "");
203 VG_(message)(Vg_DebugMsg,
204 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000205 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000206 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000207 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000208 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000209 }
nethercote71980f02004-01-24 18:18:54 +0000210}
211
212
213/*====================================================================*/
214/*=== Miscellaneous global functions ===*/
215/*====================================================================*/
216
nethercotecf97ffb2004-09-09 13:40:31 +0000217static Int ptrace_setregs(Int pid, ThreadId tid)
218{
sewardj2a99cf62004-11-24 10:44:19 +0000219 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000220}
221
nethercote04d0fbc2004-01-26 16:48:06 +0000222/* Start debugger and get it to attach to this process. Called if the
223 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000224 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000225 meaningfully get the debugger to continue the program, though; to
226 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000227void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000228{
229 Int pid;
230
231 if ((pid = fork()) == 0) {
232 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000233 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000234
235 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000236 Int status;
237 Int res;
238
nethercote71980f02004-01-24 18:18:54 +0000239 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
240 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000241 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000242 kill(pid, SIGSTOP) == 0 &&
243 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000244 Char pidbuf[15];
245 Char file[30];
246 Char buf[100];
247 Char *bufptr;
248 Char *cmdptr;
249
250 VG_(sprintf)(pidbuf, "%d", pid);
251 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
252
253 bufptr = buf;
254 cmdptr = VG_(clo_db_command);
255
256 while (*cmdptr) {
257 switch (*cmdptr) {
258 case '%':
259 switch (*++cmdptr) {
260 case 'f':
261 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
262 bufptr += VG_(strlen)(file);
263 cmdptr++;
264 break;
265 case 'p':
266 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
267 bufptr += VG_(strlen)(pidbuf);
268 cmdptr++;
269 break;
270 default:
271 *bufptr++ = *cmdptr++;
272 break;
273 }
274 break;
275 default:
276 *bufptr++ = *cmdptr++;
277 break;
278 }
279 }
280
281 *bufptr++ = '\0';
282
283 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000284 res = VG_(system)(buf);
285 if (res == 0) {
286 VG_(message)(Vg_UserMsg, "");
287 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000288 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000289 } else {
290 VG_(message)(Vg_UserMsg, "Apparently failed!");
291 VG_(message)(Vg_UserMsg, "");
292 }
293 }
294
nethercote73b526f2004-10-31 18:48:21 +0000295 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000296 VG_(waitpid)(pid, &status, 0);
297 }
298}
299
300
301/* Print some helpful-ish text about unimplemented things, and give
302 up. */
303void VG_(unimplemented) ( Char* msg )
304{
305 VG_(message)(Vg_UserMsg, "");
306 VG_(message)(Vg_UserMsg,
307 "Valgrind detected that your program requires");
308 VG_(message)(Vg_UserMsg,
309 "the following unimplemented functionality:");
310 VG_(message)(Vg_UserMsg, " %s", msg);
311 VG_(message)(Vg_UserMsg,
312 "This may be because the functionality is hard to implement,");
313 VG_(message)(Vg_UserMsg,
314 "or because no reasonable program would behave this way,");
315 VG_(message)(Vg_UserMsg,
316 "or because nobody has yet needed it. In any case, let us know at");
317 VG_(message)(Vg_UserMsg,
318 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
319 VG_(message)(Vg_UserMsg,
320 "");
321 VG_(message)(Vg_UserMsg,
322 "Valgrind has to exit now. Sorry. Bye!");
323 VG_(message)(Vg_UserMsg,
324 "");
325 VG_(pp_sched_status)();
326 VG_(exit)(1);
327}
328
sewardj2a99cf62004-11-24 10:44:19 +0000329/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000330Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000331{
njncf45fd42004-11-24 16:30:22 +0000332 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000333}
334
njn67516132005-03-22 04:02:43 +0000335Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000336{
337 return INSTR_PTR( VG_(threads)[tid].arch );
338}
339
njnea4b28c2004-11-30 16:04:58 +0000340
nethercote71980f02004-01-24 18:18:54 +0000341/*====================================================================*/
342/*=== Check we were launched by stage 1 ===*/
343/*====================================================================*/
344
345/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000346static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000347{
nethercoteebf1d862004-11-01 18:22:05 +0000348 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000349 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000350
351 for (; auxv->a_type != AT_NULL; auxv++)
352 switch(auxv->a_type) {
353 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000354 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000355 found |= 1;
356 break;
357
358 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000359 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000360 found |= 2;
361 break;
nethercote7f390022004-10-25 17:18:24 +0000362
363 case AT_PHDR:
364 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
365 break;
nethercote71980f02004-01-24 18:18:54 +0000366 }
367
nethercote361a14e2004-07-26 11:11:56 +0000368 if ( found != (1|2) ) {
369 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000370 exit(127);
371 }
nethercote31779c72004-07-30 21:50:15 +0000372 vg_assert(padfile >= 0);
373 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000374}
375
376
377/*====================================================================*/
378/*=== Address space determination ===*/
379/*====================================================================*/
380
nethercote7f390022004-10-25 17:18:24 +0000381extern char _start[];
382
nethercote31779c72004-07-30 21:50:15 +0000383static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000384{
nethercotea3c3cf22004-11-01 18:38:00 +0000385 Int ires;
386 void* vres;
387 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000388
nethercote7f390022004-10-25 17:18:24 +0000389 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
390 // this is a workable approximation
391 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000392 VG_(valgrind_base) = PGROUNDDN(&_start);
393 }
394
nethercote820bd8c2004-09-07 23:04:49 +0000395 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000396
nethercote31779c72004-07-30 21:50:15 +0000397 // This gives the client the largest possible address space while
398 // taking into account the tool's shadow needs.
399 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000400 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000401 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000402 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000403 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000404 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000405 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000406
nethercote31779c72004-07-30 21:50:15 +0000407 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000408 VG_(shadow_end) = VG_(valgrind_base);
409 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000410
nethercotee2097312004-06-27 12:29:56 +0000411#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
412
nethercote71980f02004-01-24 18:18:54 +0000413 if (0)
nethercotee2097312004-06-27 12:29:56 +0000414 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000415 "client_base %p (%dMB)\n"
416 "client_mapbase %p (%dMB)\n"
417 "client_end %p (%dMB)\n"
418 "shadow_base %p (%dMB)\n"
419 "shadow_end %p\n"
420 "valgrind_base %p (%dMB)\n"
421 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000422 VG_(client_base), SEGSIZE(client_base, client_mapbase),
423 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
424 VG_(client_end), SEGSIZE(client_end, shadow_base),
425 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000426 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000427 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
428 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000429 );
430
431#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000432
433 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000434 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000435 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000436 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000437
438 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000439 ires = munmap((void*)VG_(client_base), client_size);
440 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000441
442 // Map shadow memory.
443 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000444 if (shadow_size != 0) {
445 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000446 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000447 if ((void*)-1 == vres) {
448 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000449 "valgrind: Could not allocate address space (%p bytes)\n"
450 "valgrind: for shadow memory\n"
451 "valgrind: Possible causes:\n"
452 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
453 "valgrind: needs at least 1.5GB swap space.\n"
454 "valgrind: - Or, your virtual memory size may be limited (check\n"
455 "valgrind: with 'ulimit -v').\n"
456 "valgrind: - Or, your system may use a kernel that provides only a\n"
457 "valgrind: too-small (eg. 2GB) user address space.\n"
458 , (void*)shadow_size
459 );
nethercoted4722622004-08-30 19:36:42 +0000460 exit(1);
461 }
nethercotee567e702004-07-10 17:49:17 +0000462 }
nethercote71980f02004-01-24 18:18:54 +0000463}
464
465/*====================================================================*/
466/*=== Command line setup ===*/
467/*====================================================================*/
468
469/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
470static char* get_file_clo(char* dir)
471{
472# define FLEN 512
473 Int fd, n;
474 struct stat s1;
475 char* f_clo = NULL;
476 char filename[FLEN];
477
478 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
479 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
480 if ( fd > 0 ) {
481 if ( 0 == fstat(fd, &s1) ) {
482 f_clo = malloc(s1.st_size+1);
483 vg_assert(f_clo);
484 n = read(fd, f_clo, s1.st_size);
485 if (n == -1) n = 0;
486 f_clo[n] = '\0';
487 }
488 close(fd);
489 }
490 return f_clo;
491# undef FLEN
492}
493
494static Int count_args(char* s)
495{
496 Int n = 0;
497 if (s) {
498 char* cp = s;
499 while (True) {
500 // We have alternating sequences: blanks, non-blanks, blanks...
501 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000502 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000503 if ( !*cp ) break;
504 n++;
njn0c0f32a2005-03-26 04:14:01 +0000505 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000506 }
507 }
508 return n;
509}
510
511/* add args out of environment, skipping multiple spaces and -- args */
512static char** copy_args( char* s, char** to )
513{
514 if (s) {
515 char* cp = s;
516 while (True) {
517 // We have alternating sequences: blanks, non-blanks, blanks...
518 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000519 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000520 if ( !*cp ) break;
521 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000522 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000523 if ( *cp ) *cp++ = '\0'; // terminate if necessary
524 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
525 }
526 }
527 return to;
528}
529
530// Augment command line with arguments from environment and .valgrindrc
531// files.
532static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
533{
nethercotef6a1d502004-08-09 12:21:57 +0000534 int vg_argc0 = *vg_argc_inout;
535 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000536
537 char* env_clo = getenv(VALGRINDOPTS);
538 char* f1_clo = get_file_clo( getenv("HOME") );
539 char* f2_clo = get_file_clo(".");
540
541 /* copy any extra args from file or environment, if present */
542 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
543 /* ' ' separated extra options */
544 char **from;
545 char **to;
thughescaca0022004-09-13 10:20:34 +0000546 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
547
548 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
549
nethercote71980f02004-01-24 18:18:54 +0000550 env_arg_count = count_args(env_clo);
551 f1_arg_count = count_args(f1_clo);
552 f2_arg_count = count_args(f2_clo);
553
554 if (0)
555 printf("extra-argc=%d %d %d\n",
556 env_arg_count, f1_arg_count, f2_arg_count);
557
558 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000559 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000560 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000561 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000562 vg_assert(vg_argv0);
563 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000564
565 /* copy argv[0] */
566 *to++ = *from++;
567
568 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
569 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
570 * to override less local ones. */
571 to = copy_args(f1_clo, to);
572 to = copy_args(env_clo, to);
573 to = copy_args(f2_clo, to);
574
575 /* copy original arguments, stopping at command or -- */
576 while (*from) {
577 if (**from != '-')
578 break;
579 if (VG_STREQ(*from, "--")) {
580 from++; /* skip -- */
581 break;
582 }
583 *to++ = *from++;
584 }
585
586 /* add -- */
587 *to++ = "--";
588
nethercotef6a1d502004-08-09 12:21:57 +0000589 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000590
591 /* copy rest of original command line, then NULL */
592 while (*from) *to++ = *from++;
593 *to = NULL;
594 }
595
nethercotef6a1d502004-08-09 12:21:57 +0000596 *vg_argc_inout = vg_argc0;
597 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000598}
599
nethercotef6a1d502004-08-09 12:21:57 +0000600#define VG_CLO_SEP '\01'
601
nethercote71980f02004-01-24 18:18:54 +0000602static void get_command_line( int argc, char** argv,
603 Int* vg_argc_out, Char*** vg_argv_out,
604 char*** cl_argv_out )
605{
nethercotef6a1d502004-08-09 12:21:57 +0000606 int vg_argc0;
607 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000608 char** cl_argv;
609 char* env_clo = getenv(VALGRINDCLO);
610
611 if (env_clo != NULL && *env_clo != '\0') {
612 char *cp;
613 char **cpp;
614
nethercotef6a1d502004-08-09 12:21:57 +0000615 /* OK, VALGRINDCLO is set, which means we must be a child of another
616 Valgrind process using --trace-children, so we're getting all our
617 arguments from VALGRINDCLO, and the entire command line belongs to
618 the client (including argv[0]) */
619 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000620 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000621 if (*cp == VG_CLO_SEP)
622 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000623
nethercotef6a1d502004-08-09 12:21:57 +0000624 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
625 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000626
nethercotef6a1d502004-08-09 12:21:57 +0000627 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000628
629 *cpp++ = "valgrind"; /* nominal argv[0] */
630 *cpp++ = env_clo;
631
nethercotef6a1d502004-08-09 12:21:57 +0000632 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000633 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000634 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000635 *cp++ = '\0'; /* chop it up in place */
636 *cpp++ = cp;
637 }
638 }
639 *cpp = NULL;
640 cl_argv = argv;
641
642 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000643 Bool noaugment = False;
644
nethercote71980f02004-01-24 18:18:54 +0000645 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000646 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000647
nethercotef6a1d502004-08-09 12:21:57 +0000648 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000649 Char* arg = argv[vg_argc0];
650 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000651 break;
sewardjb5f6f512005-03-10 23:59:00 +0000652 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000653 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000654 break;
655 }
njn45270a22005-03-27 01:00:11 +0000656 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000657 }
nethercotef6a1d502004-08-09 12:21:57 +0000658 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000659
660 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000661 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000662 those extra args will already be present in VALGRINDCLO.
663 (We also don't do it when --command-line-only=yes.) */
664 if (!noaugment)
665 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000666 }
667
668 if (0) {
669 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000670 for (i = 0; i < vg_argc0; i++)
671 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000672 }
673
nethercotef6a1d502004-08-09 12:21:57 +0000674 *vg_argc_out = vg_argc0;
675 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000676 *cl_argv_out = cl_argv;
677}
678
679
680/*====================================================================*/
681/*=== Environment and stack setup ===*/
682/*====================================================================*/
683
684/* Scan a colon-separated list, and call a function on each element.
685 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000686 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000687 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000688
689 This routine will return True if (*func) returns True and False if
690 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000691*/
thughes4ad52d02004-06-27 17:37:21 +0000692static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000693{
694 char *cp, *entry;
695 int end;
696
697 if (colsep == NULL ||
698 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000699 return False;
nethercote71980f02004-01-24 18:18:54 +0000700
701 entry = cp = colsep;
702
703 do {
704 end = (*cp == '\0');
705
706 if (*cp == ':' || *cp == '\0') {
707 char save = *cp;
708
709 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000710 if ((*func)(entry)) {
711 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000712 return True;
thughes21942d92004-07-12 09:35:37 +0000713 }
nethercote71980f02004-01-24 18:18:54 +0000714 *cp = save;
715 entry = cp+1;
716 }
717 cp++;
718 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000719
720 return False;
721}
722
nethercote71980f02004-01-24 18:18:54 +0000723/* Prepare the client's environment. This is basically a copy of our
724 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000725 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000726
sewardjb5f6f512005-03-10 23:59:00 +0000727 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000728
729 Yummy. String hacking in C.
730
731 If this needs to handle any more variables it should be hacked
732 into something table driven.
733 */
734static char **fix_environment(char **origenv, const char *preload)
735{
736 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000737 static const char ld_preload[] = "LD_PRELOAD=";
738 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000739 static const int ld_preload_len = sizeof(ld_preload)-1;
740 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
741 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000742 char *inject_path;
743 int inject_path_len;
744 int vgliblen = strlen(VG_(libdir));
745 char **cpp;
746 char **ret;
747 int envc;
748 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
749
750 /* Find the vg_inject.so; also make room for the tool preload
751 library */
752 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
753 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000754 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000755
756 if (preload)
757 snprintf(inject_path, inject_path_len, "%s/%s:%s",
758 VG_(libdir), inject_so, preload);
759 else
760 snprintf(inject_path, inject_path_len, "%s/%s",
761 VG_(libdir), inject_so);
762
763 /* Count the original size of the env */
764 envc = 0; /* trailing NULL */
765 for (cpp = origenv; cpp && *cpp; cpp++)
766 envc++;
767
768 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000769 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000770 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000771
772 /* copy it over */
773 for (cpp = ret; *origenv; )
774 *cpp++ = *origenv++;
775 *cpp = NULL;
776
777 vg_assert(envc == (cpp - ret));
778
779 /* Walk over the new environment, mashing as we go */
780 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000781 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000782 int len = strlen(*cpp) + inject_path_len;
783 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000784 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000785
786 snprintf(cp, len, "%s%s:%s",
787 ld_preload, inject_path, (*cpp)+ld_preload_len);
788
789 *cpp = cp;
790
791 ld_preload_done = 1;
792 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
793 *cpp = "";
794 }
795 }
796
797 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000798 if (!ld_preload_done) {
799 int len = ld_preload_len + inject_path_len;
800 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000801 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000802
803 snprintf(cp, len, "%s%s",
804 ld_preload, inject_path);
805
806 ret[envc++] = cp;
807 }
808
sewardjb5f6f512005-03-10 23:59:00 +0000809 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000810 ret[envc] = NULL;
811
812 return ret;
813}
814
815extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000816
817/* Add a string onto the string table, and return its address */
818static char *copy_str(char **tab, const char *str)
819{
820 char *cp = *tab;
821 char *orig = cp;
822
823 while(*str)
824 *cp++ = *str++;
825 *cp++ = '\0';
826
827 if (0)
nethercote545fe672004-11-01 16:52:43 +0000828 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000829
830 *tab = cp;
831
832 return orig;
833}
834
835/*
836 This sets up the client's initial stack, containing the args,
837 environment and aux vector.
838
839 The format of the stack is:
840
841 higher address +-----------------+
842 | Trampoline code |
843 +-----------------+
844 | |
845 : string table :
846 | |
847 +-----------------+
848 | AT_NULL |
849 - -
850 | auxv |
851 +-----------------+
852 | NULL |
853 - -
854 | envp |
855 +-----------------+
856 | NULL |
857 - -
858 | argv |
859 +-----------------+
860 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000861 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000862 | undefined |
863 : :
864 */
nethercotec25c4492004-10-18 11:52:17 +0000865static Addr setup_client_stack(void* init_sp,
866 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000867 const struct exeinfo *info,
868 UInt** client_auxv)
869{
nethercotee567e702004-07-10 17:49:17 +0000870 void* res;
nethercote71980f02004-01-24 18:18:54 +0000871 char **cpp;
872 char *strtab; /* string table */
873 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000874 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000875 struct ume_auxv *auxv;
876 const struct ume_auxv *orig_auxv;
877 const struct ume_auxv *cauxv;
878 unsigned stringsize; /* total size of strings in bytes */
879 unsigned auxsize; /* total size of auxv in bytes */
880 int argc; /* total argc */
881 int envc; /* total number of env vars */
882 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000883 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000884
885 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000886 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000887
888 /* ==================== compute sizes ==================== */
889
890 /* first of all, work out how big the client stack will be */
891 stringsize = 0;
892
893 /* paste on the extra args if the loader needs them (ie, the #!
894 interpreter and its argument) */
895 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000896 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000897 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000898 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000899 }
nethercoted6a56872004-07-26 15:32:47 +0000900 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000901 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000902 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000903 }
904
905 /* now scan the args we're given... */
906 for (cpp = orig_argv; *cpp; cpp++) {
907 argc++;
908 stringsize += strlen(*cpp) + 1;
909 }
910
911 /* ...and the environment */
912 envc = 0;
913 for (cpp = orig_envp; cpp && *cpp; cpp++) {
914 envc++;
915 stringsize += strlen(*cpp) + 1;
916 }
917
918 /* now, how big is the auxv? */
919 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
920 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
921 if (cauxv->a_type == AT_PLATFORM)
922 stringsize += strlen(cauxv->u.a_ptr) + 1;
923 auxsize += sizeof(*cauxv);
924 }
925
926 /* OK, now we know how big the client stack is */
927 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000928 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000929 sizeof(char **)*argc + /* argv */
930 sizeof(char **) + /* terminal NULL */
931 sizeof(char **)*envc + /* envp */
932 sizeof(char **) + /* terminal NULL */
933 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000934 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000935 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000936
sewardj79048ce2005-02-18 08:28:32 +0000937 if (0) VG_(printf)("stacksize = %d\n", stacksize);
938
nethercotef84f6952004-07-15 14:58:33 +0000939 // decide where stack goes!
940 VG_(clstk_end) = VG_(client_end);
941
nethercote73b526f2004-10-31 18:48:21 +0000942 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000943
nethercote71980f02004-01-24 18:18:54 +0000944 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000945 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000946 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
947
nethercote71980f02004-01-24 18:18:54 +0000948 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000949 stringbase = strtab = (char *)(VG_(client_trampoline_code)
950 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000951
952 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000953
sewardj79048ce2005-02-18 08:28:32 +0000954 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000955 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000956 "clstk_base %p\n"
957 "clstk_end %p\n",
958 stringsize, auxsize, stacksize,
959 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000960
nethercote71980f02004-01-24 18:18:54 +0000961 /* ==================== allocate space ==================== */
962
963 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000964 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000965 PROT_READ | PROT_WRITE | PROT_EXEC,
966 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
967 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000968
969 /* ==================== copy client stack ==================== */
970
nethercotea3c3cf22004-11-01 18:38:00 +0000971 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000972
973 /* --- argc --- */
974 *ptr++ = argc; /* client argc */
975
976 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000977 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000978 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000979 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000980 }
nethercoted6a56872004-07-26 15:32:47 +0000981 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000982 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000983 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000984 }
985 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000986 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000987 }
988 *ptr++ = 0;
989
990 /* --- envp --- */
991 VG_(client_envp) = (Char **)ptr;
992 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000993 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000994 *ptr++ = 0;
995
996 /* --- auxv --- */
997 auxv = (struct ume_auxv *)ptr;
998 *client_auxv = (UInt *)auxv;
999
1000 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1001 /* copy the entry... */
1002 *auxv = *orig_auxv;
1003
1004 /* ...and fix up the copy */
1005 switch(auxv->a_type) {
1006 case AT_PHDR:
1007 if (info->phdr == 0)
1008 auxv->a_type = AT_IGNORE;
1009 else
1010 auxv->u.a_val = info->phdr;
1011 break;
1012
1013 case AT_PHNUM:
1014 if (info->phdr == 0)
1015 auxv->a_type = AT_IGNORE;
1016 else
1017 auxv->u.a_val = info->phnum;
1018 break;
1019
1020 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001021 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001022 break;
1023
1024 case AT_PLATFORM: /* points to a platform description string */
1025 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1026 break;
1027
1028 case AT_ENTRY:
1029 auxv->u.a_val = info->entry;
1030 break;
1031
1032 case AT_IGNORE:
1033 case AT_EXECFD:
1034 case AT_PHENT:
1035 case AT_PAGESZ:
1036 case AT_FLAGS:
1037 case AT_NOTELF:
1038 case AT_UID:
1039 case AT_EUID:
1040 case AT_GID:
1041 case AT_EGID:
1042 case AT_CLKTCK:
1043 case AT_HWCAP:
1044 case AT_FPUCW:
1045 case AT_DCACHEBSIZE:
1046 case AT_ICACHEBSIZE:
1047 case AT_UCACHEBSIZE:
1048 /* All these are pointerless, so we don't need to do anything
1049 about them. */
1050 break;
1051
1052 case AT_SECURE:
1053 /* If this is 1, then it means that this program is running
1054 suid, and therefore the dynamic linker should be careful
1055 about LD_PRELOAD, etc. However, since stage1 (the thing
1056 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001057 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001058 set AT_SECURE to 0. */
1059 auxv->u.a_val = 0;
1060 break;
1061
1062 case AT_SYSINFO:
1063 /* Leave this unmolested for now, but we'll update it later
1064 when we set up the client trampoline code page */
1065 break;
1066
1067 case AT_SYSINFO_EHDR:
1068 /* Trash this, because we don't reproduce it */
1069 auxv->a_type = AT_IGNORE;
1070 break;
1071
1072 default:
1073 /* stomp out anything we don't know about */
1074 if (0)
nethercote545fe672004-11-01 16:52:43 +00001075 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001076 auxv->a_type = AT_IGNORE;
1077 break;
1078
1079 }
1080 }
1081 *auxv = *orig_auxv;
1082 vg_assert(auxv->a_type == AT_NULL);
1083
njnc6168192004-11-29 13:54:10 +00001084// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1085// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001086#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001087 /* --- trampoline page --- */
1088 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1089 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001090#endif
nethercotef84f6952004-07-15 14:58:33 +00001091
nethercote71980f02004-01-24 18:18:54 +00001092 vg_assert((strtab-stringbase) == stringsize);
1093
nethercote5ee67ca2004-06-22 14:00:09 +00001094 /* We know the initial ESP is pointing at argc/argv */
1095 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001096 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001097
sewardj79048ce2005-02-18 08:28:32 +00001098 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001099 return cl_esp;
1100}
1101
1102/*====================================================================*/
1103/*=== Find executable ===*/
1104/*====================================================================*/
1105
thughes4ad52d02004-06-27 17:37:21 +00001106static const char* executable_name;
1107
1108static Bool match_executable(const char *entry) {
1109 char buf[strlen(entry) + strlen(executable_name) + 2];
1110
1111 /* empty PATH element means . */
1112 if (*entry == '\0')
1113 entry = ".";
1114
1115 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1116
1117 if (access(buf, R_OK|X_OK) == 0) {
1118 executable_name = strdup(buf);
1119 vg_assert(NULL != executable_name);
1120 return True;
1121 }
1122 return False;
1123}
1124
nethercote71980f02004-01-24 18:18:54 +00001125static const char* find_executable(const char* exec)
1126{
1127 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001128 executable_name = exec;
1129 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001130 /* no '/' - we need to search the path */
1131 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001132 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001133 }
thughes4ad52d02004-06-27 17:37:21 +00001134 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001135}
1136
1137
1138/*====================================================================*/
1139/*=== Loading tools ===*/
1140/*====================================================================*/
1141
1142static void list_tools(void)
1143{
1144 DIR *dir = opendir(VG_(libdir));
1145 struct dirent *de;
1146 int first = 1;
1147
1148 if (dir == NULL) {
1149 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001150 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001151 return;
1152 }
1153
nethercotef4928da2004-06-15 10:54:40 +00001154 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001155 int len = strlen(de->d_name);
1156
njn063c5402004-11-22 16:58:05 +00001157 /* look for vgtool_TOOL.so names */
1158 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1159 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001160 VG_STREQ(de->d_name + len - 3, ".so")) {
1161 if (first) {
1162 fprintf(stderr, "Available tools:\n");
1163 first = 0;
1164 }
1165 de->d_name[len-3] = '\0';
1166 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001167 }
1168 }
1169
1170 closedir(dir);
1171
1172 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001173 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1174 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001175}
1176
1177
1178/* Find and load a tool, and check it looks ok. Also looks to see if there's
1179 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001180static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001181 ToolInfo** toolinfo_out, char **preloadpath_out )
1182{
1183 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001184 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001185 char buf[len];
1186 void* handle;
1187 ToolInfo* toolinfo;
1188 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001189
1190 // XXX: allowing full paths for --tool option -- does it make sense?
1191 // Doesn't allow for vgpreload_<tool>.so.
1192
1193 if (strchr(toolname, '/') != 0) {
1194 /* toolname contains '/', and so must be a pathname */
1195 handle = dlopen(toolname, RTLD_NOW);
1196 } else {
1197 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001198 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001199 handle = dlopen(buf, RTLD_NOW);
1200
1201 if (handle != NULL) {
1202 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1203 if (access(buf, R_OK) == 0) {
1204 preloadpath = strdup(buf);
1205 vg_assert(NULL != preloadpath);
1206 }
1207 }
1208 }
1209
1210 ok = (NULL != handle);
1211 if (!ok) {
1212 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1213 goto bad_load;
1214 }
1215
njn51d827b2005-05-09 01:02:08 +00001216 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001217 ok = (NULL != toolinfo);
1218 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001219 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001220 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1221 goto bad_load;
1222 }
1223
1224 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001225 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1226 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001227 if (!ok) {
1228 fprintf(stderr, "Error:\n"
1229 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001230 " Interface version used by core is: %d (size %d)\n"
1231 " Interface version used by tool is: %d (size %d)\n"
1232 " The version numbers must match.\n",
1233 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001234 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001235 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001236 toolinfo->sizeof_ToolInfo);
1237 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001238 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_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;
sewardjce058b02005-05-01 08:55:38 +00001438Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001439Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001440Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001441Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001442Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001443Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001444Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001445Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001446Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001447Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001448Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001449Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001450Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001451Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001452Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001453Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001454
jsgf855d93d2003-10-13 22:26:55 +00001455static Bool VG_(clo_wait_for_gdb) = False;
1456
sewardjde4a1d02002-03-22 01:27:54 +00001457
sewardj2c5ffbe2005-03-12 13:32:06 +00001458static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001459{
njn25e49d8e72002-09-23 09:36:25 +00001460 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001461"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001462"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001463" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001464" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001465" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001466" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001467" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001468" -q --quiet run silently; only print error msgs\n"
1469" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001470" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001471" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001472" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001473"\n"
1474" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001475" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001476" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001477" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001478" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001479" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001480"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001481" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001482" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1483" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001484" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001485" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001486" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001487" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001488" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1489" --show-below-main=no|yes continue stack traces below main() [no]\n"
1490" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001491" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001492" --db-attach=no|yes start debugger when errors detected? [no]\n"
1493" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1494" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001495" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1496" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001497"\n";
njn7cf0bd32002-06-08 13:36:03 +00001498
njn25e49d8e72002-09-23 09:36:25 +00001499 Char* usage2 =
1500"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001501" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001502" --sanity-level=<number> level of sanity checking to do [1]\n"
1503" --single-step=no|yes translate each instr separately? [no]\n"
1504" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001505" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001506" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001507" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1508" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001509" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001510" --trace-syscalls=no|yes show all system calls? [no]\n"
1511" --trace-signals=no|yes show signal handling details? [no]\n"
1512" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001513" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001514" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001515" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001516#if 0
1517" --model-pthreads=yes|no model the pthreads library [no]\n"
1518#endif
1519" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001520"\n"
1521" --vex-iropt-verbosity 0 .. 9 [0]\n"
1522" --vex-iropt-level 0 .. 2 [2]\n"
1523" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001524" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1525" --vex-guest-max-insns 1 .. 100 [50]\n"
1526" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1527"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001528" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001529" 1000 0000 show conversion into IR\n"
1530" 0100 0000 show after initial opt\n"
1531" 0010 0000 show after instrumentation\n"
1532" 0001 0000 show after second opt\n"
1533" 0000 1000 show after tree building\n"
1534" 0000 0100 show selecting insns\n"
1535" 0000 0010 show after reg-alloc\n"
1536" 0000 0001 show final assembly\n"
1537"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001538" debugging options for Valgrind tools that report errors\n"
1539" --dump-error=<number> show translation for basic block associated\n"
1540" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001541"\n";
njn3e884182003-04-15 13:03:23 +00001542
1543 Char* usage3 =
1544"\n"
nethercote71980f02004-01-24 18:18:54 +00001545" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001546"\n"
njn53612422005-03-12 16:22:54 +00001547" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001548" and licensed under the GNU General Public License, version 2.\n"
1549" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001550"\n"
nethercote137bc552003-11-14 17:47:54 +00001551" Tools are copyright and licensed by their authors. See each\n"
1552" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001553"\n";
njn7cf0bd32002-06-08 13:36:03 +00001554
fitzhardinge98abfc72003-12-16 02:05:15 +00001555 VG_(printf)(usage1);
1556 if (VG_(details).name) {
1557 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001558 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001559 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001560 else
1561 VG_(printf)(" (none)\n");
1562 }
nethercote6c999f22004-01-31 22:55:15 +00001563 if (debug_help) {
1564 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001565
nethercote6c999f22004-01-31 22:55:15 +00001566 if (VG_(details).name) {
1567 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1568
1569 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001570 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001571 else
1572 VG_(printf)(" (none)\n");
1573 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001574 }
nethercote421281e2003-11-20 16:20:55 +00001575 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001576 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001577}
sewardjde4a1d02002-03-22 01:27:54 +00001578
nethercote71980f02004-01-24 18:18:54 +00001579static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001580 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001581{
nethercote71980f02004-01-24 18:18:54 +00001582 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001583
sewardj8b635a42004-11-22 19:01:47 +00001584 LibVEX_default_VexControl(& VG_(clo_vex_control));
1585
nethercote71980f02004-01-24 18:18:54 +00001586 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001587 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001588
nethercotef6a1d502004-08-09 12:21:57 +00001589 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001590 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001591 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001592
nethercotef6a1d502004-08-09 12:21:57 +00001593 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1594 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001595 *need_help = 1;
1596
nethercotef6a1d502004-08-09 12:21:57 +00001597 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001598 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001599
nethercotef6c99d72004-11-09 14:35:43 +00001600 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001601 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001602
nethercotef6a1d502004-08-09 12:21:57 +00001603 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1604 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001605 }
1606 }
nethercote71980f02004-01-24 18:18:54 +00001607}
1608
nethercote5ee67ca2004-06-22 14:00:09 +00001609static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001610{
nethercotef8548672004-06-21 12:42:35 +00001611 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001612 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001613
nethercotee1730692003-11-20 10:38:07 +00001614 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001615 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001616
sewardj19d81412002-06-03 01:10:40 +00001617 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001618 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001619 config_error("Please use absolute paths in "
1620 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001621
njnc6168192004-11-29 13:54:10 +00001622// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001623#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001624 {
sewardjb5f6f512005-03-10 23:59:00 +00001625 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001626 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1627 switch(auxp[0]) {
1628 case AT_SYSINFO:
1629 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1630 break;
1631 }
1632 }
1633 }
1634#endif
sewardjde4a1d02002-03-22 01:27:54 +00001635
nethercotef6a1d502004-08-09 12:21:57 +00001636 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001637
nethercotef6a1d502004-08-09 12:21:57 +00001638 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001639 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001640
thughes3bfd5a02004-07-18 08:05:44 +00001641 /* Look for a colon in the switch name */
1642 while (*colon && *colon != ':' && *colon != '=')
1643 colon++;
nethercote71980f02004-01-24 18:18:54 +00001644
1645 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001646 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001647 if (VG_CLO_STREQN(2, arg, "--") &&
1648 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1649 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1650 {
1651 // prefix matches, convert "--toolname:foo" to "--foo"
1652 if (0)
1653 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001654 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001655 arg[0] = '-';
1656 arg[1] = '-';
1657
1658 } else {
1659 // prefix doesn't match, skip to next arg
1660 continue;
1661 }
1662 }
1663
fitzhardinge98abfc72003-12-16 02:05:15 +00001664 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001665 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1666 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1667 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001668
njn45270a22005-03-27 01:00:11 +00001669 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 else if (VG_CLO_STREQ(arg, "-v") ||
1672 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001673 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 else if (VG_CLO_STREQ(arg, "-q") ||
1676 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001677 VG_(clo_verbosity)--;
1678
sewardj1cf558c2005-04-25 01:36:56 +00001679 else if (VG_CLO_STREQ(arg, "-d")) {
1680 /* do nothing */
1681 }
1682
njn45270a22005-03-27 01:00:11 +00001683 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1684 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1685 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1686 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1687 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1688 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1689 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001690 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001691 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1692 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1693 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1694 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1695 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1696 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1697 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1698 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1699 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001700 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001701 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1702 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1703 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1704 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1705 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001706
njn45270a22005-03-27 01:00:11 +00001707 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1708 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001709
njn45270a22005-03-27 01:00:11 +00001710 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1711 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1712 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1713 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1714 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001715
njn45270a22005-03-27 01:00:11 +00001716 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001717 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001718 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001719 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001720 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001721 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001722 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001723 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001724 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001725 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001726 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001727 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1728
nethercotef8548672004-06-21 12:42:35 +00001729 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1730 VG_(clo_log_to) = VgLogTo_Fd;
1731 VG_(clo_log_name) = NULL;
1732 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001733 }
1734
nethercotef8548672004-06-21 12:42:35 +00001735 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1736 VG_(clo_log_to) = VgLogTo_File;
1737 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001738 }
njnd6bc3c32005-03-27 00:44:31 +00001739
sewardj603d4102005-01-11 14:01:02 +00001740 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1741 VG_(clo_log_to) = VgLogTo_FileExactly;
1742 VG_(clo_log_name) = &arg[19];
1743 }
sewardjde4a1d02002-03-22 01:27:54 +00001744
nethercotef8548672004-06-21 12:42:35 +00001745 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1746 VG_(clo_log_to) = VgLogTo_Socket;
1747 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001748 }
1749
nethercote71980f02004-01-24 18:18:54 +00001750 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001751 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001752 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001753 VG_(message)(Vg_UserMsg,
1754 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001755 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001756 }
nethercote71980f02004-01-24 18:18:54 +00001757 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001758 VG_(clo_n_suppressions)++;
1759 }
sewardjde4a1d02002-03-22 01:27:54 +00001760
sewardjfa8ec112005-01-19 11:55:34 +00001761 /* "stuvwxyz" --> stuvwxyz (binary) */
1762 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1763 Int j;
1764 char* opt = & arg[14];
1765
1766 if (8 != VG_(strlen)(opt)) {
1767 VG_(message)(Vg_UserMsg,
1768 "--trace-flags argument must have 8 digits");
1769 VG_(bad_option)(arg);
1770 }
1771 for (j = 0; j < 8; j++) {
1772 if ('0' == opt[j]) { /* do nothing */ }
1773 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1774 else {
1775 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1776 "contain 0s and 1s");
1777 VG_(bad_option)(arg);
1778 }
1779 }
1780 }
1781
1782 /* "stuvwxyz" --> stuvwxyz (binary) */
1783 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001784 Int j;
nethercote71980f02004-01-24 18:18:54 +00001785 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001786
sewardj2a99cf62004-11-24 10:44:19 +00001787 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001788 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001789 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001790 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001791 }
sewardj8b635a42004-11-22 19:01:47 +00001792 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001793 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001794 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001795 else {
sewardjfa8ec112005-01-19 11:55:34 +00001796 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001797 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001798 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001799 }
1800 }
1801 }
sewardjde4a1d02002-03-22 01:27:54 +00001802
njn45270a22005-03-27 01:00:11 +00001803 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001804
sewardjd153fae2005-01-10 17:24:47 +00001805 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1806 VG_(clo_gen_suppressions) = 0;
1807 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1808 VG_(clo_gen_suppressions) = 1;
1809 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1810 VG_(clo_gen_suppressions) = 2;
1811
nethercote71980f02004-01-24 18:18:54 +00001812 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001813 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001814 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001815 }
njn8c0b3bb2005-03-12 21:20:39 +00001816 skip_arg:
1817 if (arg != vg_argv[i])
1818 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001819 }
1820
sewardj998d40d2004-12-06 14:24:52 +00001821 /* Make VEX control parameters sane */
1822
1823 if (VG_(clo_vex_control).guest_chase_thresh
1824 >= VG_(clo_vex_control).guest_max_insns)
1825 VG_(clo_vex_control).guest_chase_thresh
1826 = VG_(clo_vex_control).guest_max_insns - 1;
1827
1828 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1829 VG_(clo_vex_control).guest_chase_thresh = 0;
1830
1831 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001832
njnf9ebf672003-05-12 21:41:30 +00001833 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001834 VG_(clo_verbosity) = 0;
1835
nethercote04d0fbc2004-01-26 16:48:06 +00001836 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001837 VG_(message)(Vg_UserMsg, "");
1838 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001839 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001840 VG_(message)(Vg_UserMsg,
1841 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001842 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001843 }
1844
nethercotef8548672004-06-21 12:42:35 +00001845 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001846 should be connected to whatever sink has been selected, and we
1847 indiscriminately chuck stuff into it without worrying what the
1848 nature of it is. Oh the wonder of Unix streams. */
1849
nethercotee1730692003-11-20 10:38:07 +00001850 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001851 the terminal any problems to do with processing command line
1852 opts. */
nethercotef8548672004-06-21 12:42:35 +00001853 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001854 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001855
1856 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001857
sewardj4cf05692002-10-27 20:28:29 +00001858 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001859 vg_assert(VG_(clo_log_name) == NULL);
1860 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001861 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001862
sewardj4cf05692002-10-27 20:28:29 +00001863 case VgLogTo_File: {
1864 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001865 Int seq = 0;
1866 Int pid = VG_(getpid)();
1867
nethercotef8548672004-06-21 12:42:35 +00001868 vg_assert(VG_(clo_log_name) != NULL);
1869 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001870
nethercote71980f02004-01-24 18:18:54 +00001871 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001872 if (seq == 0)
1873 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001874 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001875 else
1876 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001877 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001878 seq++;
1879
nethercotef8548672004-06-21 12:42:35 +00001880 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001881 = VG_(open)(logfilename,
1882 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1883 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001884 if (eventually_log_fd >= 0) {
1885 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001886 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001887 } else {
nethercotef8548672004-06-21 12:42:35 +00001888 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001889 VG_(message)(Vg_UserMsg,
1890 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001891 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001892 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001893 "--log-file=<file> (didn't work out for some reason.)");
1894 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001895 }
1896 }
1897 }
sewardj603d4102005-01-11 14:01:02 +00001898 break; /* switch (VG_(clo_log_to)) */
1899 }
1900
1901 case VgLogTo_FileExactly: {
1902 Char logfilename[1000];
1903
1904 vg_assert(VG_(clo_log_name) != NULL);
1905 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1906 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1907
1908 eventually_log_fd
1909 = VG_(open)(logfilename,
1910 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1911 VKI_S_IRUSR|VKI_S_IWUSR);
1912 if (eventually_log_fd >= 0) {
1913 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1914 }
1915 else if (eventually_log_fd != -VKI_EEXIST) {
1916 VG_(message)(Vg_UserMsg,
1917 "Can't create/open log file `%s'; giving up!",
1918 VG_(clo_log_name));
1919 VG_(bad_option)(
1920 "--log-file-exactly=<file> (didn't work out for some reason.)");
1921 /*NOTREACHED*/
1922 }
1923 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001924 }
1925
1926 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001927 vg_assert(VG_(clo_log_name) != NULL);
1928 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1929 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1930 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001931 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001932 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001933 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001934 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001935 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001936 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001937 }
nethercotef8548672004-06-21 12:42:35 +00001938 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001939 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001940 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001941 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001942 VG_(message)(Vg_UserMsg,
1943 "Log messages will sent to stderr instead." );
1944 VG_(message)(Vg_UserMsg,
1945 "" );
1946 /* We don't change anything here. */
1947 } else {
nethercotef8548672004-06-21 12:42:35 +00001948 vg_assert(eventually_log_fd > 0);
1949 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001950 VG_(logging_to_filedes) = False;
1951 }
sewardj73cf3bc2002-11-03 03:20:15 +00001952 break;
1953 }
1954
sewardj4cf05692002-10-27 20:28:29 +00001955 }
1956
nethercotef8548672004-06-21 12:42:35 +00001957 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001958 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001959 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001960 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1961 else {
nethercotef8548672004-06-21 12:42:35 +00001962 VG_(clo_log_fd) = eventually_log_fd;
1963 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001964 }
1965
sewardj4cf05692002-10-27 20:28:29 +00001966 /* Ok, the logging sink is running now. Print a suitable preamble.
1967 If logging to file or a socket, write details of parent PID and
1968 command line args, to help people trying to interpret the
1969 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001970
sewardj83adf412002-05-01 01:25:45 +00001971 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001972 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001973 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001974 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001975 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001976 NULL == VG_(details).version
1977 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001978 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001979 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001980
njnd04b7c62002-10-03 14:05:52 +00001981 /* Core details */
1982 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001983 "Using LibVEX rev %s, a library for dynamic binary translation.",
1984 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001985 VG_(message)(Vg_UserMsg,
1986 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1987 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001988 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001989 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001990 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001991 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001992 }
1993
nethercotec1e395d2003-11-10 13:26:49 +00001994 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001995 VG_(message)(Vg_UserMsg, "");
1996 VG_(message)(Vg_UserMsg,
1997 "My PID = %d, parent PID = %d. Prog and args are:",
1998 VG_(getpid)(), VG_(getppid)() );
1999 for (i = 0; i < VG_(client_argc); i++)
2000 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2001 }
2002
sewardjde4a1d02002-03-22 01:27:54 +00002003 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002004 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002005 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002006 VG_(message)(Vg_DebugMsg, "");
2007 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2008 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002009 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002010 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002011
njn1fd5eb22005-03-13 05:43:23 +00002012 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002013 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002014 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002015 }
nethercotea70f7352004-04-18 12:08:46 +00002016
njn1fd5eb22005-03-13 05:43:23 +00002017 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002018 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2019 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002020 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002021 } else {
2022 #define BUF_LEN 256
2023 Char version_buf[BUF_LEN];
2024 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2025 vg_assert(n <= 256);
2026 if (n > 0) {
2027 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002028 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002029 } else {
njn1fd5eb22005-03-13 05:43:23 +00002030 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002031 }
2032 VG_(close)(fd);
2033 #undef BUF_LEN
2034 }
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
2036
fitzhardinge98abfc72003-12-16 02:05:15 +00002037 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002038 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002039 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002040 needs one, load the default */
2041 static const Char default_supp[] = "default.supp";
2042 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2043 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2044 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2045 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2046 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002047 }
sewardj4cf05692002-10-27 20:28:29 +00002048
sewardjd153fae2005-01-10 17:24:47 +00002049 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002050 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002051 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002052 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002053 VG_(message)(Vg_UserMsg,
2054 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002055 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002056 }
sewardjde4a1d02002-03-22 01:27:54 +00002057}
2058
nethercotef6a1d502004-08-09 12:21:57 +00002059// Build the string for VALGRINDCLO.
2060Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2061{
2062 /* If we're tracing the children, then we need to start it
2063 with our starter+arguments, which are copied into VALGRINDCLO,
2064 except the --exec= option is changed if present.
2065 */
2066 Int i;
2067 Char *exec;
2068 Char *cp;
2069 Char *optvar;
2070 Int optlen, execlen;
2071
2072 // All these allocated blocks are not free - because we're either
2073 // going to exec, or panic when we fail.
2074
2075 // Create --exec= option: "--exec=<exename>"
2076 exec = VG_(arena_malloc)(VG_AR_CORE,
2077 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2078 vg_assert(NULL != exec);
2079 VG_(sprintf)(exec, "--exec=%s", exename);
2080
2081 // Allocate space for optvar (may overestimate by counting --exec twice,
2082 // no matter)
2083 optlen = 1;
2084 for (i = 0; i < vg_argc; i++)
2085 optlen += VG_(strlen)(vg_argv[i]) + 1;
2086 optlen += VG_(strlen)(exec)+1;
2087 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2088
2089 // Copy all valgrind args except the old --exec (if present)
2090 // VG_CLO_SEP is the separator.
2091 cp = optvar;
2092 for (i = 1; i < vg_argc; i++) {
2093 Char *arg = vg_argv[i];
2094
2095 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2096 // don't copy existing --exec= arg
2097 } else if (VG_(strcmp)(arg, "--") == 0) {
2098 // stop at "--"
2099 break;
2100 } else {
2101 // copy non "--exec" arg
2102 Int len = VG_(strlen)(arg);
2103 VG_(memcpy)(cp, arg, len);
2104 cp += len;
2105 *cp++ = VG_CLO_SEP;
2106 }
2107 }
2108 // Add the new --exec= option
2109 execlen = VG_(strlen)(exec);
2110 VG_(memcpy)(cp, exec, execlen);
2111 cp += execlen;
2112 *cp++ = VG_CLO_SEP;
2113
2114 *cp = '\0';
2115
2116 return optvar;
2117}
2118
2119// Build "/proc/self/fd/<execfd>".
2120Char* VG_(build_child_exename)( void )
2121{
2122 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2123 vg_assert(NULL != exename);
2124 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2125 return exename;
2126}
2127
sewardjde4a1d02002-03-22 01:27:54 +00002128
nethercote71980f02004-01-24 18:18:54 +00002129/*====================================================================*/
2130/*=== File descriptor setup ===*/
2131/*====================================================================*/
2132
2133static void setup_file_descriptors(void)
2134{
2135 struct vki_rlimit rl;
2136
2137 /* Get the current file descriptor limits. */
2138 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2139 rl.rlim_cur = 1024;
2140 rl.rlim_max = 1024;
2141 }
2142
2143 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002144 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2145 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002146 } else {
2147 rl.rlim_cur = rl.rlim_max;
2148 }
2149
2150 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002151 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2152 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002153
2154 /* Update the soft limit. */
2155 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2156
nethercotef6a1d502004-08-09 12:21:57 +00002157 if (vgexecfd != -1)
2158 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002159 if (VG_(clexecfd) != -1)
2160 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2161}
2162
nethercote71980f02004-01-24 18:18:54 +00002163/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002164/*=== Initialise program data/text, etc. ===*/
2165/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002166
sewardjb5f6f512005-03-10 23:59:00 +00002167static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2168 UInt dev, UInt ino, ULong foffset,
2169 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002170{
nethercote71980f02004-01-24 18:18:54 +00002171 /* Only record valgrind mappings for now, without loading any
2172 symbols. This is so we know where the free space is before we
2173 start allocating more memory (note: heap is OK, it's just mmap
2174 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002175 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002176 VG_(debugLog)(2, "main",
2177 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002178 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002179 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002180 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2181 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002182 /* update VG_(valgrind_last) if it looks wrong */
2183 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002184 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002185 }
sewardjde4a1d02002-03-22 01:27:54 +00002186}
2187
nethercote71980f02004-01-24 18:18:54 +00002188// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002189Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002190
sewardjb5f6f512005-03-10 23:59:00 +00002191/*
2192 This second pass adds in client mappings, and loads symbol tables
2193 for all interesting mappings. The trouble is that things can
2194 change as we go, because we're calling the Tool to track memory as
2195 we find it.
2196
2197 So for Valgrind mappings, we don't replace any mappings which
2198 aren't still identical (which will include the .so mappings, so we
2199 will load their symtabs)>
2200 */
2201static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2202 UInt dev, UInt ino, ULong foffset,
2203 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002204{
nethercote71980f02004-01-24 18:18:54 +00002205 UInt flags;
2206 Bool is_stack_segment;
2207 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002208
nethercote71980f02004-01-24 18:18:54 +00002209 is_stack_segment
2210 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002211
sewardj8c615892005-04-25 02:38:28 +00002212 VG_(debugLog)(2, "main",
2213 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002214 (void*)start, (void*)(start+size), prot, is_stack_segment,
2215 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002216
nethercote71980f02004-01-24 18:18:54 +00002217 if (is_stack_segment)
2218 flags = SF_STACK | SF_GROWDOWN;
2219 else
2220 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002221
nethercote71980f02004-01-24 18:18:54 +00002222 if (filename != NULL)
2223 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002224
sewardjb5f6f512005-03-10 23:59:00 +00002225#if 0
2226 // This needs to be fixed properly. jrs 20050307
2227 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2228 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002229
sewardjb5f6f512005-03-10 23:59:00 +00002230 /* We have to be a bit careful about inserting new mappings into
2231 the Valgrind part of the address space. We're actively
2232 changing things as we parse these mappings, particularly in
2233 shadow memory, and so we don't want to overwrite those
2234 changes. Therefore, we only insert/update a mapping if it is
2235 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002236
sewardjb5f6f512005-03-10 23:59:00 +00002237 NOTE: we're only talking about the Segment list mapping
2238 metadata; this doesn't actually mmap anything more. */
2239 if (filename || (s && s->addr == start && s->len == size)) {
2240 flags |= SF_VALGRIND;
2241 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2242 } else {
2243 /* assert range is already mapped */
2244 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2245 }
2246 } else
2247#endif
2248 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2249
2250 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2251 VG_TRACK( new_mem_startup, start, size,
2252 !!(prot & VKI_PROT_READ),
2253 !!(prot & VKI_PROT_WRITE),
2254 !!(prot & VKI_PROT_EXEC));
2255 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002256
nethercote71980f02004-01-24 18:18:54 +00002257 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002258 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002259 vg_assert(0 != r_esp);
2260 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002261 if (0) {
2262 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002263 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002264 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2265 r_esp, start+size);
2266 }
nethercote71980f02004-01-24 18:18:54 +00002267 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002268 // what's this for?
2269 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002270 }
sewardjde4a1d02002-03-22 01:27:54 +00002271}
2272
2273
nethercote71980f02004-01-24 18:18:54 +00002274/*====================================================================*/
2275/*=== Sanity check machinery (permanently engaged) ===*/
2276/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002277
2278/* A fast sanity check -- suitable for calling circa once per
2279 millisecond. */
2280
nethercote885dd912004-08-03 23:14:00 +00002281void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002282{
sewardjb5f6f512005-03-10 23:59:00 +00002283 ThreadId tid;
2284
njn37cea302002-09-30 11:24:00 +00002285 VGP_PUSHCC(VgpCoreCheapSanity);
2286
nethercote27fec902004-06-16 21:26:32 +00002287 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002288
2289 /* --- First do all the tests that we can do quickly. ---*/
2290
nethercote297effd2004-08-02 15:07:57 +00002291 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002292
njn25e49d8e72002-09-23 09:36:25 +00002293 /* Check stuff pertaining to the memory check system. */
2294
2295 /* Check that nobody has spuriously claimed that the first or
2296 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002297 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002298 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002299 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002300 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002301 }
njn25e49d8e72002-09-23 09:36:25 +00002302
2303 /* --- Now some more expensive checks. ---*/
2304
2305 /* Once every 25 times, check some more expensive stuff. */
2306 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002307 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002308 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002309
njn37cea302002-09-30 11:24:00 +00002310 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002311 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002312
2313# if 0
2314 { void zzzmemscan(void); zzzmemscan(); }
2315# endif
2316
nethercote297effd2004-08-02 15:07:57 +00002317 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002318 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002319
2320 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002321 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002322 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002323 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002324 }
sewardjb5f6f512005-03-10 23:59:00 +00002325
2326 /* Check that Segments and /proc/self/maps match up */
2327 //vg_assert(VG_(sanity_check_memory)());
2328
2329 /* Look for stack overruns. Visit all threads. */
2330 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002331 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002332
2333 if (VG_(threads)[tid].status == VgTs_Empty ||
2334 VG_(threads)[tid].status == VgTs_Zombie)
2335 continue;
2336
2337 remains = VGA_(stack_unused)(tid);
2338 if (remains < VKI_PAGE_SIZE)
2339 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2340 tid, remains);
2341 }
2342
njn25e49d8e72002-09-23 09:36:25 +00002343 /*
nethercote297effd2004-08-02 15:07:57 +00002344 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002345 */
njn37cea302002-09-30 11:24:00 +00002346 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002347 }
2348
nethercote27fec902004-06-16 21:26:32 +00002349 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002350 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002351 /* Check sanity of the low-level memory manager. Note that bugs
2352 in the client's code can cause this to fail, so we don't do
2353 this check unless specially asked for. And because it's
2354 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002355 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002356 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002357 }
njn37cea302002-09-30 11:24:00 +00002358 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002359}
nethercote71980f02004-01-24 18:18:54 +00002360
2361
2362/*====================================================================*/
2363/*=== main() ===*/
2364/*====================================================================*/
2365
nethercotec314eba2004-07-15 12:59:41 +00002366/*
2367 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002368 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002369 loads the client executable (and the dynamic linker, if necessary)
2370 into the client part, and calls into Valgrind proper.
2371
2372 The code is careful not to allow spurious mappings to appear in the
2373 wrong parts of the address space. In particular, to make sure
2374 dlopen puts things in the right place, it will pad out the forbidden
2375 chunks of address space so that dlopen is forced to put things where
2376 we want them.
2377
2378 The memory map it creates is:
2379
njn80950732005-03-26 00:18:45 +00002380 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002381 | client address space |
2382 : :
2383 : :
2384 | client stack |
2385 client_end +-------------------------+
2386 | redzone |
2387 shadow_base +-------------------------+
2388 | |
nethercote996901a2004-08-03 13:29:09 +00002389 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002390 | (may be 0 sized) |
2391 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002392 valgrind_base +-------------------------+
2393 | kickstart executable |
2394 | valgrind heap vvvvvvvvv| (barely used)
2395 - -
2396 | valgrind .so files |
2397 | and mappings |
2398 - -
2399 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002400 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002401 : kernel :
2402
2403 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2404 VG_(mmap)(), we need to build the segment skip-list, so we know where
2405 we can put things. However, building that structure requires
2406 allocating memory. So we need to a bootstrapping process. It's done
2407 by making VG_(arena_malloc)() have a special static superblock that's
2408 used for the first 1MB's worth of allocations. This is enough to
2409 build the segment skip-list.
2410*/
2411
thughes4ad52d02004-06-27 17:37:21 +00002412
sewardj1cf558c2005-04-25 01:36:56 +00002413/* This may be needed before m_mylibc is OK to run. */
2414static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2415{
2416 while (True) {
2417 if (*s1 == 0 && *s2 == 0) return 0;
2418 if (*s1 == 0) return -1;
2419 if (*s2 == 0) return 1;
2420
2421 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2422 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2423
2424 s1++; s2++;
2425 }
2426}
2427
2428
sewardjb5f6f512005-03-10 23:59:00 +00002429int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002430{
2431 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002432 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002433 const char *exec = NULL;
2434 char *preload; /* tool-specific LD_PRELOAD .so */
2435 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002436 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002437 struct exeinfo info;
2438 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002439 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002440 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002441 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002442 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002443 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002444
2445 //============================================================
2446 // Nb: startup is complex. Prerequisites are shown at every step.
2447 //
2448 // *** Be very careful when messing with the order ***
2449 //============================================================
2450
sewardj1cf558c2005-04-25 01:36:56 +00002451 //--------------------------------------------------------------
2452 // Start up the logging mechanism
2453 // p: none
2454 //--------------------------------------------------------------
2455 /* Start the debugging-log system ASAP. First find out how many
2456 "-d"s were specified. This is a pre-scan of the command line. */
2457 loglevel = 0;
2458 for (i = 1; i < argc; i++) {
2459 if (argv[i][0] != '-')
2460 break;
2461 if (0 == local_strcmp(argv[i], "--"))
2462 break;
2463 if (0 == local_strcmp(argv[i], "-d"))
2464 loglevel++;
2465 }
2466
2467 /* ... and start the debug logger. Now we can safely emit logging
2468 messages all through startup. */
2469 VG_(debugLog_startup)(loglevel, "Stage 2");
2470
nethercotef4928da2004-06-15 10:54:40 +00002471 //============================================================
2472 // Command line argument handling order:
2473 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002474 // (including the tool-specific usage)
2475 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002476 // * Then, if client is missing, abort with error msg
2477 // * Then, if any cmdline args are bad, abort with error msg
2478 //============================================================
2479
fitzhardingeb50068f2004-02-24 23:42:55 +00002480 // Get the current process datasize rlimit, and set it to zero.
2481 // This prevents any internal uses of brk() from having any effect.
2482 // We remember the old value so we can restore it on exec, so that
2483 // child processes will have a reasonable brk value.
2484 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2485 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2486 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002487
2488 // Get the current process stack rlimit.
2489 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2490
nethercote71980f02004-01-24 18:18:54 +00002491 //--------------------------------------------------------------
2492 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002493 // p: none
nethercote71980f02004-01-24 18:18:54 +00002494 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002495 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002496 {
sewardj1fbc1a52005-04-25 02:05:54 +00002497 void* init_sp = argv - 1;
2498 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002499 }
2500
2501 //--------------------------------------------------------------
2502 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002503 // p: none
nethercote71980f02004-01-24 18:18:54 +00002504 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002505 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002506 if (cp != NULL)
2507 VG_(libdir) = cp;
2508 }
2509
2510 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002511 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2512 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002513 // p: none
nethercote71980f02004-01-24 18:18:54 +00002514 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002515 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002516 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002517 pre_process_cmd_line_options(&need_help, &tool, &exec);
2518
2519 //==============================================================
2520 // Nb: once a tool is specified, the tool.so must be loaded even if
2521 // they specified --help or didn't specify a client program.
2522 //==============================================================
2523
2524 //--------------------------------------------------------------
2525 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002526 // p: set-libdir [for VG_(libdir)]
2527 // p: pre_process_cmd_line_options() [for 'tool']
2528 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002529 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002530 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002531
2532 //==============================================================
2533 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002534 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002535 //==============================================================
2536
2537 //--------------------------------------------------------------
2538 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002539 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002540 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002541 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002542 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002543
2544 //--------------------------------------------------------------
2545 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002546 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2547 // p: layout_remaining_space [so there's space]
2548 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002549 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002550 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002551
2552 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002553 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002554 // p: layout_remaining_space() [everything must be mapped in before now]
2555 // p: load_client() [ditto]
2556 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002557 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2558 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002559
2560 //--------------------------------------------------------------
2561 // Set up client's environment
2562 // p: set-libdir [for VG_(libdir)]
2563 // p: load_tool() [for 'preload']
2564 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002565 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002566 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002567
2568 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002569 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002570 // p: load_client() [for 'info']
2571 // p: fix_environment() [for 'env']
2572 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002573 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002574 {
sewardj1fbc1a52005-04-25 02:05:54 +00002575 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002576
sewardj1fbc1a52005-04-25 02:05:54 +00002577 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2578 &client_auxv);
2579 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002580 }
nethercote71980f02004-01-24 18:18:54 +00002581
sewardj1fbc1a52005-04-25 02:05:54 +00002582 VG_(debugLog)(2, "main",
2583 "Client info: "
2584 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2585 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2586 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002587
2588 //==============================================================
2589 // Finished setting up operating environment. Now initialise
2590 // Valgrind. (This is where the old VG_(main)() started.)
2591 //==============================================================
2592
2593 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002594 // setup file descriptors
2595 // p: n/a
2596 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002597 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002598 setup_file_descriptors();
2599
2600 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002601 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002602 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002603 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002604 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002605 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2606
2607 //==============================================================
2608 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2609 //==============================================================
2610
2611 //--------------------------------------------------------------
2612 // Init tool: pre_clo_init, process cmd line, post_clo_init
2613 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002614 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002615 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2616 // p: parse_procselfmaps [so VG segments are setup so tool can
2617 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002618 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002619 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002620 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002621 VG_(sanity_check_needs)();
2622
nethercotef4928da2004-06-15 10:54:40 +00002623 // If --tool and --help/--help-debug was given, now give the core+tool
2624 // help message
nethercotef4928da2004-06-15 10:54:40 +00002625 if (need_help) {
2626 usage(/*--help-debug?*/2 == need_help);
2627 }
nethercotec314eba2004-07-15 12:59:41 +00002628 process_cmd_line_options(client_auxv, tool);
2629
njn51d827b2005-05-09 01:02:08 +00002630 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002631
2632 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002633 // Determine CPU architecture and subarchitecture
2634 // p: none
2635 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002636 VG_(debugLog)(1, "main", "Check CPU arch/subarch\n");
sewardj51ac0872004-12-21 01:20:49 +00002637 { Bool ok = VGA_(getArchAndSubArch)(
2638 & VG_(vex_arch), & VG_(vex_subarch) );
2639 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002640 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002641 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002642 VG_(printf)(" Supported CPUs are:\n");
2643 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2644 "AMD Athlon or above)\n");
2645 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002646 VG_(exit)(1);
2647 }
2648 if (VG_(clo_verbosity) > 2) {
2649 VG_(message)(Vg_DebugMsg,
2650 "Host CPU: arch = %s, subarch = %s",
2651 LibVEX_ppVexArch( VG_(vex_arch) ),
2652 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2653 }
2654 }
2655
2656 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002657 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002658 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002659 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002660 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002661 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002662 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002663 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002664 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002665 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002666
sewardj21c6d0f2005-05-02 10:33:44 +00002667#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002668 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002669 // Protect client trampoline page (which is also sysinfo stuff)
2670 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002671 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002672 {
2673 Segment *seg;
2674 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2675 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002676
sewardjb5f6f512005-03-10 23:59:00 +00002677 /* Make sure this segment isn't treated as stack */
2678 seg = VG_(find_segment)(VG_(client_trampoline_code));
2679 if (seg)
2680 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2681 }
sewardj21c6d0f2005-05-02 10:33:44 +00002682#endif
sewardjb5f6f512005-03-10 23:59:00 +00002683
nethercotec314eba2004-07-15 12:59:41 +00002684 //==============================================================
2685 // Can use VG_(map)() after segments set up
2686 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002687
2688 //--------------------------------------------------------------
2689 // Allow GDB attach
2690 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2691 //--------------------------------------------------------------
2692 /* Hook to delay things long enough so we can get the pid and
2693 attach GDB in another shell. */
2694 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002695 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002696 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2697 /* jrs 20050206: I don't understand why this works on x86. On
2698 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2699 work. */
2700 /* do "jump *$eip" to skip this in gdb (x86) */
2701 //VG_(do_syscall0)(__NR_pause);
2702 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002703 }
2704
sewardjb5d320c2005-03-13 18:57:15 +00002705 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002706 // Search for file descriptors that are inherited from our parent
2707 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2708 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002709 if (VG_(clo_track_fds)) {
2710 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002711 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002712 }
nethercote71980f02004-01-24 18:18:54 +00002713
2714 //--------------------------------------------------------------
2715 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002716 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2717 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002718 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002719 VG_(scheduler_init)();
2720
2721 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002722 // Initialise the pthread model
2723 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002724 // load_client() [for 'client_eip']
2725 // setup_client_stack() [for 'sp_at_startup']
2726 // setup_scheduler() [for the rest of state 1 stuff]
2727 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002728 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002729 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002730
2731 // Tell the tool that we just wrote to the registers.
2732 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2733 sizeof(VexGuestArchState));
2734
sewardj2a99cf62004-11-24 10:44:19 +00002735 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002736 // Initialise the pthread model
2737 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002738 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002739 //if (VG_(clo_model_pthreads))
2740 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002741
2742 //--------------------------------------------------------------
2743 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002744 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002745 //--------------------------------------------------------------
2746 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002747 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002748 VG_(sigstartup_actions)();
2749
2750 //--------------------------------------------------------------
2751 // Perhaps we're profiling Valgrind?
2752 // p: process_cmd_line_options() [for VG_(clo_profile)]
2753 // p: others?
2754 //
2755 // XXX: this seems to be broken? It always says the tool wasn't built
2756 // for profiling; vg_profile.c's functions don't seem to be overriding
2757 // vg_dummy_profile.c's?
2758 //
2759 // XXX: want this as early as possible. Looking for --profile
2760 // in pre_process_cmd_line_options() could get it earlier.
2761 //--------------------------------------------------------------
2762 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002763 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002764
2765 VGP_PUSHCC(VgpStartup);
2766
2767 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002768 // Read suppression file
2769 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2770 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002771 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2772 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002773 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002774 }
nethercote71980f02004-01-24 18:18:54 +00002775
2776 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002777 // Initialise translation table and translation cache
2778 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2779 // aren't identified as part of the client, which would waste
2780 // > 20M of virtual address space.]
2781 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002782 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002783 VG_(init_tt_tc)();
2784
2785 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002786 // Read debug info to find glibc entry points to intercept
2787 // p: parse_procselfmaps? [XXX for debug info?]
2788 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2789 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002790 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002791 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002792 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002793
2794 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002795 // Verbosity message
2796 // p: end_rdtsc_calibration [so startup message is printed first]
2797 //--------------------------------------------------------------
2798 if (VG_(clo_verbosity) == 1)
2799 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2800 if (VG_(clo_verbosity) > 0)
2801 VG_(message)(Vg_UserMsg, "");
2802
2803 //--------------------------------------------------------------
2804 // Setup pointercheck
2805 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2806 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002807 if (VG_(clo_pointercheck))
2808 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002809
nethercote71980f02004-01-24 18:18:54 +00002810 //--------------------------------------------------------------
2811 // Run!
2812 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002813 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002814
sewardjb5f6f512005-03-10 23:59:00 +00002815 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002816
sewardj1fbc1a52005-04-25 02:05:54 +00002817 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002818 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002819
sewardjb5f6f512005-03-10 23:59:00 +00002820 abort();
2821}
2822
2823
2824/* Do everything which needs doing when the last thread exits */
2825void VG_(shutdown_actions)(ThreadId tid)
2826{
2827 vg_assert(tid == VG_(master_tid));
2828 vg_assert(VG_(is_running_thread)(tid));
2829
2830 // Wait for all other threads to exit.
2831 VGA_(reap_threads)(tid);
2832
2833 VG_(clo_model_pthreads) = False;
2834
2835 // Clean the client up before the final report
2836 VGA_(final_tidyup)(tid);
2837
2838 // OK, done
2839 VG_(exit_thread)(tid);
2840
2841 /* should be no threads left */
2842 vg_assert(VG_(count_living_threads)() == 0);
2843
2844 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002845 //--------------------------------------------------------------
2846 // Finalisation: cleanup, messages, etc. Order no so important, only
2847 // affects what order the messages come.
2848 //--------------------------------------------------------------
2849 if (VG_(clo_verbosity) > 0)
2850 VG_(message)(Vg_UserMsg, "");
2851
nethercote71980f02004-01-24 18:18:54 +00002852 /* Print out file descriptor summary and stats. */
2853 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002854 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002855
njn95ec8702004-11-22 16:46:13 +00002856 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002857 VG_(show_all_errors)();
2858
njn51d827b2005-05-09 01:02:08 +00002859 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002860
nethercote885dd912004-08-03 23:14:00 +00002861 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002862
2863 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002864 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002865
nethercote71980f02004-01-24 18:18:54 +00002866 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002867 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002868 if (VG_(clo_profile_flags) > 0)
2869 VG_(show_BB_profile)();
2870
sewardj8b635a42004-11-22 19:01:47 +00002871 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002872 if (0)
2873 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002874}
sewardj8b635a42004-11-22 19:01:47 +00002875
sewardjde4a1d02002-03-22 01:27:54 +00002876/*--------------------------------------------------------------------*/
2877/*--- end vg_main.c ---*/
2878/*--------------------------------------------------------------------*/