blob: f181423cb763988e822c1e58b43be1623be1b12f [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"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njnd1af0032005-05-29 17:01:48 +000040#include "pub_core_redir.h"
njn2521d322005-05-08 14:45:13 +000041#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000042#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000043#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000044
45#include <dirent.h>
46#include <dlfcn.h>
47#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000048#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000049#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000050#include <string.h>
51#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000052#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000054#include <sys/wait.h>
55#include <unistd.h>
56
sewardjb5f6f512005-03-10 23:59:00 +000057#include "memcheck/memcheck.h"
58
thughes74b8de22004-04-22 18:12:31 +000059#ifndef AT_DCACHEBSIZE
60#define AT_DCACHEBSIZE 19
61#endif /* AT_DCACHEBSIZE */
62
63#ifndef AT_ICACHEBSIZE
64#define AT_ICACHEBSIZE 20
65#endif /* AT_ICACHEBSIZE */
66
67#ifndef AT_UCACHEBSIZE
68#define AT_UCACHEBSIZE 21
69#endif /* AT_UCACHEBSIZE */
70
nethercote71980f02004-01-24 18:18:54 +000071#ifndef AT_SYSINFO
72#define AT_SYSINFO 32
73#endif /* AT_SYSINFO */
74
75#ifndef AT_SYSINFO_EHDR
76#define AT_SYSINFO_EHDR 33
77#endif /* AT_SYSINFO_EHDR */
78
79#ifndef AT_SECURE
80#define AT_SECURE 23 /* secure mode boolean */
81#endif /* AT_SECURE */
82
nethercote71980f02004-01-24 18:18:54 +000083/* redzone gap between client address space and shadow */
84#define REDZONE_SIZE (1 * 1024*1024)
85
86/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000087#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000088
nethercotee2097312004-06-27 12:29:56 +000089/* Proportion of client space for its heap (rest is for mmaps + stack) */
90#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000091
njn14319cc2005-03-13 06:26:22 +000092/* Number of file descriptors that Valgrind tries to reserve for
93 it's own use - just a small constant. */
94#define N_RESERVED_FDS (10)
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
sewardjde4a1d02002-03-22 01:27:54 +0000157/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000158 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000159 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000160
sewardjde4a1d02002-03-22 01:27:54 +0000161/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000162ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Tell the logging mechanism whether we are logging to a file
165 descriptor or a socket descriptor. */
njnbe9b47b2005-05-15 16:22:58 +0000166Bool VG_(logging_to_socket) = False;
nethercote71980f02004-01-24 18:18:54 +0000167
sewardj73cf3bc2002-11-03 03:20:15 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/*====================================================================*/
170/*=== Counters, for profiling purposes only ===*/
171/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000172
sewardjde4a1d02002-03-22 01:27:54 +0000173/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000174static UInt sanity_fast_count = 0;
175static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000176
nethercote3a42fb82004-08-03 18:08:50 +0000177static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000178{
nethercote3a42fb82004-08-03 18:08:50 +0000179 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000180 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000181 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000182 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000183
nethercote3a42fb82004-08-03 18:08:50 +0000184 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000185 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000186
nethercote71980f02004-01-24 18:18:54 +0000187 VG_(message)(Vg_DebugMsg,
188 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000189 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000190
njn9271cbc2005-03-13 05:38:25 +0000191 VG_(print_ExeContext_stats)();
192
nethercote3a42fb82004-08-03 18:08:50 +0000193 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000194 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000195 VG_(message)(Vg_DebugMsg, "");
196 VG_(message)(Vg_DebugMsg,
197 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000198 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000199 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000200 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000201 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000202 }
nethercote71980f02004-01-24 18:18:54 +0000203}
204
205
206/*====================================================================*/
207/*=== Miscellaneous global functions ===*/
208/*====================================================================*/
209
nethercotecf97ffb2004-09-09 13:40:31 +0000210static Int ptrace_setregs(Int pid, ThreadId tid)
211{
sewardj2a99cf62004-11-24 10:44:19 +0000212 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000213}
214
nethercote04d0fbc2004-01-26 16:48:06 +0000215/* Start debugger and get it to attach to this process. Called if the
216 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000217 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000218 meaningfully get the debugger to continue the program, though; to
219 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000220void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000221{
222 Int pid;
223
224 if ((pid = fork()) == 0) {
225 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000226 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000227
228 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000229 Int status;
230 Int res;
231
nethercote71980f02004-01-24 18:18:54 +0000232 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
233 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000234 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000235 kill(pid, SIGSTOP) == 0 &&
236 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000237 Char pidbuf[15];
238 Char file[30];
239 Char buf[100];
240 Char *bufptr;
241 Char *cmdptr;
242
243 VG_(sprintf)(pidbuf, "%d", pid);
244 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
245
246 bufptr = buf;
247 cmdptr = VG_(clo_db_command);
248
249 while (*cmdptr) {
250 switch (*cmdptr) {
251 case '%':
252 switch (*++cmdptr) {
253 case 'f':
254 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
255 bufptr += VG_(strlen)(file);
256 cmdptr++;
257 break;
258 case 'p':
259 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
260 bufptr += VG_(strlen)(pidbuf);
261 cmdptr++;
262 break;
263 default:
264 *bufptr++ = *cmdptr++;
265 break;
266 }
267 break;
268 default:
269 *bufptr++ = *cmdptr++;
270 break;
271 }
272 }
273
274 *bufptr++ = '\0';
275
276 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000277 res = VG_(system)(buf);
278 if (res == 0) {
279 VG_(message)(Vg_UserMsg, "");
280 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000281 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000282 } else {
283 VG_(message)(Vg_UserMsg, "Apparently failed!");
284 VG_(message)(Vg_UserMsg, "");
285 }
286 }
287
nethercote73b526f2004-10-31 18:48:21 +0000288 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000289 VG_(waitpid)(pid, &status, 0);
290 }
291}
292
293
294/* Print some helpful-ish text about unimplemented things, and give
295 up. */
296void VG_(unimplemented) ( Char* msg )
297{
298 VG_(message)(Vg_UserMsg, "");
299 VG_(message)(Vg_UserMsg,
300 "Valgrind detected that your program requires");
301 VG_(message)(Vg_UserMsg,
302 "the following unimplemented functionality:");
303 VG_(message)(Vg_UserMsg, " %s", msg);
304 VG_(message)(Vg_UserMsg,
305 "This may be because the functionality is hard to implement,");
306 VG_(message)(Vg_UserMsg,
307 "or because no reasonable program would behave this way,");
308 VG_(message)(Vg_UserMsg,
309 "or because nobody has yet needed it. In any case, let us know at");
310 VG_(message)(Vg_UserMsg,
311 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
312 VG_(message)(Vg_UserMsg,
313 "");
314 VG_(message)(Vg_UserMsg,
315 "Valgrind has to exit now. Sorry. Bye!");
316 VG_(message)(Vg_UserMsg,
317 "");
318 VG_(pp_sched_status)();
319 VG_(exit)(1);
320}
321
sewardj2a99cf62004-11-24 10:44:19 +0000322/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000323Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000324{
njncf45fd42004-11-24 16:30:22 +0000325 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000326}
327
njn67516132005-03-22 04:02:43 +0000328Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000329{
330 return INSTR_PTR( VG_(threads)[tid].arch );
331}
332
njnea4b28c2004-11-30 16:04:58 +0000333
nethercote71980f02004-01-24 18:18:54 +0000334/*====================================================================*/
335/*=== Check we were launched by stage 1 ===*/
336/*====================================================================*/
337
338/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000339static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000340{
nethercoteebf1d862004-11-01 18:22:05 +0000341 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000342 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000343
344 for (; auxv->a_type != AT_NULL; auxv++)
345 switch(auxv->a_type) {
346 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000347 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000348 found |= 1;
349 break;
350
351 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000352 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000353 found |= 2;
354 break;
nethercote7f390022004-10-25 17:18:24 +0000355
356 case AT_PHDR:
357 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
358 break;
nethercote71980f02004-01-24 18:18:54 +0000359 }
360
nethercote361a14e2004-07-26 11:11:56 +0000361 if ( found != (1|2) ) {
362 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000363 exit(127);
364 }
nethercote31779c72004-07-30 21:50:15 +0000365 vg_assert(padfile >= 0);
366 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000367}
368
369
370/*====================================================================*/
371/*=== Address space determination ===*/
372/*====================================================================*/
373
nethercote7f390022004-10-25 17:18:24 +0000374extern char _start[];
375
nethercote31779c72004-07-30 21:50:15 +0000376static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000377{
nethercotea3c3cf22004-11-01 18:38:00 +0000378 Int ires;
379 void* vres;
380 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000381
nethercote7f390022004-10-25 17:18:24 +0000382 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
383 // this is a workable approximation
384 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000385 VG_(valgrind_base) = PGROUNDDN(&_start);
386 }
387
nethercote820bd8c2004-09-07 23:04:49 +0000388 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000389
nethercote31779c72004-07-30 21:50:15 +0000390 // This gives the client the largest possible address space while
391 // taking into account the tool's shadow needs.
392 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000393 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000394 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000395 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000396 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000397 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000398 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000399
nethercote31779c72004-07-30 21:50:15 +0000400 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000401 VG_(shadow_end) = VG_(valgrind_base);
402 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000403
nethercotee2097312004-06-27 12:29:56 +0000404#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
405
nethercote71980f02004-01-24 18:18:54 +0000406 if (0)
nethercotee2097312004-06-27 12:29:56 +0000407 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000408 "client_base %p (%dMB)\n"
409 "client_mapbase %p (%dMB)\n"
410 "client_end %p (%dMB)\n"
411 "shadow_base %p (%dMB)\n"
412 "shadow_end %p\n"
413 "valgrind_base %p (%dMB)\n"
414 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000415 VG_(client_base), SEGSIZE(client_base, client_mapbase),
416 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
417 VG_(client_end), SEGSIZE(client_end, shadow_base),
418 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000419 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000420 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
421 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000422 );
423
424#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000425
426 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000427 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000428 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000429 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000430
431 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000432 ires = munmap((void*)VG_(client_base), client_size);
433 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000434
435 // Map shadow memory.
436 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000437 if (shadow_size != 0) {
438 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000439 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000440 if ((void*)-1 == vres) {
441 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000442 "valgrind: Could not allocate address space (%p bytes)\n"
443 "valgrind: for shadow memory\n"
444 "valgrind: Possible causes:\n"
445 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
446 "valgrind: needs at least 1.5GB swap space.\n"
447 "valgrind: - Or, your virtual memory size may be limited (check\n"
448 "valgrind: with 'ulimit -v').\n"
449 "valgrind: - Or, your system may use a kernel that provides only a\n"
450 "valgrind: too-small (eg. 2GB) user address space.\n"
451 , (void*)shadow_size
452 );
nethercoted4722622004-08-30 19:36:42 +0000453 exit(1);
454 }
nethercotee567e702004-07-10 17:49:17 +0000455 }
nethercote71980f02004-01-24 18:18:54 +0000456}
457
458/*====================================================================*/
459/*=== Command line setup ===*/
460/*====================================================================*/
461
nethercote71980f02004-01-24 18:18:54 +0000462static char* get_file_clo(char* dir)
463{
464# define FLEN 512
465 Int fd, n;
466 struct stat s1;
467 char* f_clo = NULL;
468 char filename[FLEN];
469
470 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
471 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
472 if ( fd > 0 ) {
473 if ( 0 == fstat(fd, &s1) ) {
474 f_clo = malloc(s1.st_size+1);
475 vg_assert(f_clo);
476 n = read(fd, f_clo, s1.st_size);
477 if (n == -1) n = 0;
478 f_clo[n] = '\0';
479 }
480 close(fd);
481 }
482 return f_clo;
483# undef FLEN
484}
485
486static Int count_args(char* s)
487{
488 Int n = 0;
489 if (s) {
490 char* cp = s;
491 while (True) {
492 // We have alternating sequences: blanks, non-blanks, blanks...
493 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000494 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000495 if ( !*cp ) break;
496 n++;
njn0c0f32a2005-03-26 04:14:01 +0000497 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000498 }
499 }
500 return n;
501}
502
503/* add args out of environment, skipping multiple spaces and -- args */
504static char** copy_args( char* s, char** to )
505{
506 if (s) {
507 char* cp = s;
508 while (True) {
509 // We have alternating sequences: blanks, non-blanks, blanks...
510 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000511 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000512 if ( !*cp ) break;
513 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000514 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000515 if ( *cp ) *cp++ = '\0'; // terminate if necessary
516 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
517 }
518 }
519 return to;
520}
521
522// Augment command line with arguments from environment and .valgrindrc
523// files.
524static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
525{
nethercotef6a1d502004-08-09 12:21:57 +0000526 int vg_argc0 = *vg_argc_inout;
527 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000528
529 char* env_clo = getenv(VALGRINDOPTS);
530 char* f1_clo = get_file_clo( getenv("HOME") );
531 char* f2_clo = get_file_clo(".");
532
533 /* copy any extra args from file or environment, if present */
534 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
535 /* ' ' separated extra options */
536 char **from;
537 char **to;
thughescaca0022004-09-13 10:20:34 +0000538 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
539
540 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
541
nethercote71980f02004-01-24 18:18:54 +0000542 env_arg_count = count_args(env_clo);
543 f1_arg_count = count_args(f1_clo);
544 f2_arg_count = count_args(f2_clo);
545
546 if (0)
547 printf("extra-argc=%d %d %d\n",
548 env_arg_count, f1_arg_count, f2_arg_count);
549
550 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000551 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000552 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000553 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000554 vg_assert(vg_argv0);
555 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000556
557 /* copy argv[0] */
558 *to++ = *from++;
559
560 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
561 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
562 * to override less local ones. */
563 to = copy_args(f1_clo, to);
564 to = copy_args(env_clo, to);
565 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000566
567 // Free memory
568 free(f1_clo);
569 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000570
571 /* copy original arguments, stopping at command or -- */
572 while (*from) {
573 if (**from != '-')
574 break;
575 if (VG_STREQ(*from, "--")) {
576 from++; /* skip -- */
577 break;
578 }
579 *to++ = *from++;
580 }
581
582 /* add -- */
583 *to++ = "--";
584
nethercotef6a1d502004-08-09 12:21:57 +0000585 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000586
587 /* copy rest of original command line, then NULL */
588 while (*from) *to++ = *from++;
589 *to = NULL;
590 }
591
nethercotef6a1d502004-08-09 12:21:57 +0000592 *vg_argc_inout = vg_argc0;
593 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000594}
595
nethercotef6a1d502004-08-09 12:21:57 +0000596#define VG_CLO_SEP '\01'
597
nethercote71980f02004-01-24 18:18:54 +0000598static void get_command_line( int argc, char** argv,
599 Int* vg_argc_out, Char*** vg_argv_out,
600 char*** cl_argv_out )
601{
nethercotef6a1d502004-08-09 12:21:57 +0000602 int vg_argc0;
603 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000604 char** cl_argv;
605 char* env_clo = getenv(VALGRINDCLO);
606
607 if (env_clo != NULL && *env_clo != '\0') {
608 char *cp;
609 char **cpp;
610
nethercotef6a1d502004-08-09 12:21:57 +0000611 /* OK, VALGRINDCLO is set, which means we must be a child of another
612 Valgrind process using --trace-children, so we're getting all our
613 arguments from VALGRINDCLO, and the entire command line belongs to
614 the client (including argv[0]) */
615 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000616 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000617 if (*cp == VG_CLO_SEP)
618 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000619
nethercotef6a1d502004-08-09 12:21:57 +0000620 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
621 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000622
nethercotef6a1d502004-08-09 12:21:57 +0000623 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000624
625 *cpp++ = "valgrind"; /* nominal argv[0] */
626 *cpp++ = env_clo;
627
nethercotef6a1d502004-08-09 12:21:57 +0000628 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000629 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000630 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000631 *cp++ = '\0'; /* chop it up in place */
632 *cpp++ = cp;
633 }
634 }
635 *cpp = NULL;
636 cl_argv = argv;
637
638 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000639 Bool noaugment = False;
640
nethercote71980f02004-01-24 18:18:54 +0000641 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000642 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000643
nethercotef6a1d502004-08-09 12:21:57 +0000644 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000645 Char* arg = argv[vg_argc0];
646 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000647 break;
sewardjb5f6f512005-03-10 23:59:00 +0000648 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000649 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000650 break;
651 }
njn45270a22005-03-27 01:00:11 +0000652 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000653 }
nethercotef6a1d502004-08-09 12:21:57 +0000654 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000655
656 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000657 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000658 those extra args will already be present in VALGRINDCLO.
659 (We also don't do it when --command-line-only=yes.) */
660 if (!noaugment)
661 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000662 }
663
664 if (0) {
665 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000666 for (i = 0; i < vg_argc0; i++)
667 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000668 }
669
nethercotef6a1d502004-08-09 12:21:57 +0000670 *vg_argc_out = vg_argc0;
671 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000672 *cl_argv_out = cl_argv;
673}
674
675
676/*====================================================================*/
677/*=== Environment and stack setup ===*/
678/*====================================================================*/
679
680/* Scan a colon-separated list, and call a function on each element.
681 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000682 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000683 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000684
685 This routine will return True if (*func) returns True and False if
686 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000687*/
thughes4ad52d02004-06-27 17:37:21 +0000688static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000689{
690 char *cp, *entry;
691 int end;
692
693 if (colsep == NULL ||
694 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000695 return False;
nethercote71980f02004-01-24 18:18:54 +0000696
697 entry = cp = colsep;
698
699 do {
700 end = (*cp == '\0');
701
702 if (*cp == ':' || *cp == '\0') {
703 char save = *cp;
704
705 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000706 if ((*func)(entry)) {
707 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000708 return True;
thughes21942d92004-07-12 09:35:37 +0000709 }
nethercote71980f02004-01-24 18:18:54 +0000710 *cp = save;
711 entry = cp+1;
712 }
713 cp++;
714 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000715
716 return False;
717}
718
nethercote71980f02004-01-24 18:18:54 +0000719/* Prepare the client's environment. This is basically a copy of our
720 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000721 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000722
sewardjb5f6f512005-03-10 23:59:00 +0000723 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000724
725 Yummy. String hacking in C.
726
727 If this needs to handle any more variables it should be hacked
728 into something table driven.
729 */
730static char **fix_environment(char **origenv, const char *preload)
731{
732 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000733 static const char ld_preload[] = "LD_PRELOAD=";
734 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000735 static const int ld_preload_len = sizeof(ld_preload)-1;
736 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
737 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000738 char *inject_path;
739 int inject_path_len;
740 int vgliblen = strlen(VG_(libdir));
741 char **cpp;
742 char **ret;
743 int envc;
744 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
745
746 /* Find the vg_inject.so; also make room for the tool preload
747 library */
748 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
749 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000750 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000751
752 if (preload)
753 snprintf(inject_path, inject_path_len, "%s/%s:%s",
754 VG_(libdir), inject_so, preload);
755 else
756 snprintf(inject_path, inject_path_len, "%s/%s",
757 VG_(libdir), inject_so);
758
759 /* Count the original size of the env */
760 envc = 0; /* trailing NULL */
761 for (cpp = origenv; cpp && *cpp; cpp++)
762 envc++;
763
764 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000765 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000766 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000767
768 /* copy it over */
769 for (cpp = ret; *origenv; )
770 *cpp++ = *origenv++;
771 *cpp = NULL;
772
773 vg_assert(envc == (cpp - ret));
774
775 /* Walk over the new environment, mashing as we go */
776 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000777 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000778 int len = strlen(*cpp) + inject_path_len;
779 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000780 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000781
782 snprintf(cp, len, "%s%s:%s",
783 ld_preload, inject_path, (*cpp)+ld_preload_len);
784
785 *cpp = cp;
786
787 ld_preload_done = 1;
788 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
789 *cpp = "";
790 }
791 }
792
793 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000794 if (!ld_preload_done) {
795 int len = ld_preload_len + inject_path_len;
796 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000797 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000798
799 snprintf(cp, len, "%s%s",
800 ld_preload, inject_path);
801
802 ret[envc++] = cp;
803 }
804
sewardjb5f6f512005-03-10 23:59:00 +0000805 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000806 ret[envc] = NULL;
807
808 return ret;
809}
810
811extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000812
813/* Add a string onto the string table, and return its address */
814static char *copy_str(char **tab, const char *str)
815{
816 char *cp = *tab;
817 char *orig = cp;
818
819 while(*str)
820 *cp++ = *str++;
821 *cp++ = '\0';
822
823 if (0)
nethercote545fe672004-11-01 16:52:43 +0000824 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000825
826 *tab = cp;
827
828 return orig;
829}
830
831/*
832 This sets up the client's initial stack, containing the args,
833 environment and aux vector.
834
835 The format of the stack is:
836
837 higher address +-----------------+
838 | Trampoline code |
839 +-----------------+
840 | |
841 : string table :
842 | |
843 +-----------------+
844 | AT_NULL |
845 - -
846 | auxv |
847 +-----------------+
848 | NULL |
849 - -
850 | envp |
851 +-----------------+
852 | NULL |
853 - -
854 | argv |
855 +-----------------+
856 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000857 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000858 | undefined |
859 : :
860 */
nethercotec25c4492004-10-18 11:52:17 +0000861static Addr setup_client_stack(void* init_sp,
862 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000863 const struct exeinfo *info,
864 UInt** client_auxv)
865{
nethercotee567e702004-07-10 17:49:17 +0000866 void* res;
nethercote71980f02004-01-24 18:18:54 +0000867 char **cpp;
868 char *strtab; /* string table */
869 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000870 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000871 struct ume_auxv *auxv;
872 const struct ume_auxv *orig_auxv;
873 const struct ume_auxv *cauxv;
874 unsigned stringsize; /* total size of strings in bytes */
875 unsigned auxsize; /* total size of auxv in bytes */
876 int argc; /* total argc */
877 int envc; /* total number of env vars */
878 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000879 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000880
881 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000882 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000883
884 /* ==================== compute sizes ==================== */
885
886 /* first of all, work out how big the client stack will be */
887 stringsize = 0;
888
889 /* paste on the extra args if the loader needs them (ie, the #!
890 interpreter and its argument) */
891 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000892 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000893 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000894 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000895 }
nethercoted6a56872004-07-26 15:32:47 +0000896 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000897 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000898 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000899 }
900
901 /* now scan the args we're given... */
902 for (cpp = orig_argv; *cpp; cpp++) {
903 argc++;
904 stringsize += strlen(*cpp) + 1;
905 }
906
907 /* ...and the environment */
908 envc = 0;
909 for (cpp = orig_envp; cpp && *cpp; cpp++) {
910 envc++;
911 stringsize += strlen(*cpp) + 1;
912 }
913
914 /* now, how big is the auxv? */
915 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
916 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
917 if (cauxv->a_type == AT_PLATFORM)
918 stringsize += strlen(cauxv->u.a_ptr) + 1;
919 auxsize += sizeof(*cauxv);
920 }
921
922 /* OK, now we know how big the client stack is */
923 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000924 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000925 sizeof(char **)*argc + /* argv */
926 sizeof(char **) + /* terminal NULL */
927 sizeof(char **)*envc + /* envp */
928 sizeof(char **) + /* terminal NULL */
929 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000930 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000931 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000932
sewardj79048ce2005-02-18 08:28:32 +0000933 if (0) VG_(printf)("stacksize = %d\n", stacksize);
934
nethercotef84f6952004-07-15 14:58:33 +0000935 // decide where stack goes!
936 VG_(clstk_end) = VG_(client_end);
937
nethercote73b526f2004-10-31 18:48:21 +0000938 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000939
nethercote71980f02004-01-24 18:18:54 +0000940 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000941 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000942 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
943
nethercote71980f02004-01-24 18:18:54 +0000944 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000945 stringbase = strtab = (char *)(VG_(client_trampoline_code)
946 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000947
948 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000949
sewardj79048ce2005-02-18 08:28:32 +0000950 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000951 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000952 "clstk_base %p\n"
953 "clstk_end %p\n",
954 stringsize, auxsize, stacksize,
955 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000956
nethercote71980f02004-01-24 18:18:54 +0000957 /* ==================== allocate space ==================== */
958
959 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000960 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000961 PROT_READ | PROT_WRITE | PROT_EXEC,
962 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
963 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000964
965 /* ==================== copy client stack ==================== */
966
nethercotea3c3cf22004-11-01 18:38:00 +0000967 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000968
969 /* --- argc --- */
970 *ptr++ = argc; /* client argc */
971
972 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000973 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000974 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000975 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000976 }
nethercoted6a56872004-07-26 15:32:47 +0000977 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000978 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000979 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000980 }
981 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000982 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000983 }
984 *ptr++ = 0;
985
986 /* --- envp --- */
987 VG_(client_envp) = (Char **)ptr;
988 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000989 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000990 *ptr++ = 0;
991
992 /* --- auxv --- */
993 auxv = (struct ume_auxv *)ptr;
994 *client_auxv = (UInt *)auxv;
995
996 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
997 /* copy the entry... */
998 *auxv = *orig_auxv;
999
1000 /* ...and fix up the copy */
1001 switch(auxv->a_type) {
1002 case AT_PHDR:
1003 if (info->phdr == 0)
1004 auxv->a_type = AT_IGNORE;
1005 else
1006 auxv->u.a_val = info->phdr;
1007 break;
1008
1009 case AT_PHNUM:
1010 if (info->phdr == 0)
1011 auxv->a_type = AT_IGNORE;
1012 else
1013 auxv->u.a_val = info->phnum;
1014 break;
1015
1016 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001017 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001018 break;
1019
1020 case AT_PLATFORM: /* points to a platform description string */
1021 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1022 break;
1023
1024 case AT_ENTRY:
1025 auxv->u.a_val = info->entry;
1026 break;
1027
1028 case AT_IGNORE:
1029 case AT_EXECFD:
1030 case AT_PHENT:
1031 case AT_PAGESZ:
1032 case AT_FLAGS:
1033 case AT_NOTELF:
1034 case AT_UID:
1035 case AT_EUID:
1036 case AT_GID:
1037 case AT_EGID:
1038 case AT_CLKTCK:
1039 case AT_HWCAP:
1040 case AT_FPUCW:
1041 case AT_DCACHEBSIZE:
1042 case AT_ICACHEBSIZE:
1043 case AT_UCACHEBSIZE:
1044 /* All these are pointerless, so we don't need to do anything
1045 about them. */
1046 break;
1047
1048 case AT_SECURE:
1049 /* If this is 1, then it means that this program is running
1050 suid, and therefore the dynamic linker should be careful
1051 about LD_PRELOAD, etc. However, since stage1 (the thing
1052 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001053 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001054 set AT_SECURE to 0. */
1055 auxv->u.a_val = 0;
1056 break;
1057
1058 case AT_SYSINFO:
1059 /* Leave this unmolested for now, but we'll update it later
1060 when we set up the client trampoline code page */
1061 break;
1062
1063 case AT_SYSINFO_EHDR:
1064 /* Trash this, because we don't reproduce it */
1065 auxv->a_type = AT_IGNORE;
1066 break;
1067
1068 default:
1069 /* stomp out anything we don't know about */
1070 if (0)
nethercote545fe672004-11-01 16:52:43 +00001071 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001072 auxv->a_type = AT_IGNORE;
1073 break;
1074
1075 }
1076 }
1077 *auxv = *orig_auxv;
1078 vg_assert(auxv->a_type == AT_NULL);
1079
njnc6168192004-11-29 13:54:10 +00001080// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1081// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001082#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001083 /* --- trampoline page --- */
1084 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1085 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001086#endif
nethercotef84f6952004-07-15 14:58:33 +00001087
nethercote71980f02004-01-24 18:18:54 +00001088 vg_assert((strtab-stringbase) == stringsize);
1089
nethercote5ee67ca2004-06-22 14:00:09 +00001090 /* We know the initial ESP is pointing at argc/argv */
1091 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001092 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001093
sewardj79048ce2005-02-18 08:28:32 +00001094 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001095 return cl_esp;
1096}
1097
1098/*====================================================================*/
1099/*=== Find executable ===*/
1100/*====================================================================*/
1101
thughes4ad52d02004-06-27 17:37:21 +00001102static const char* executable_name;
1103
1104static Bool match_executable(const char *entry) {
1105 char buf[strlen(entry) + strlen(executable_name) + 2];
1106
1107 /* empty PATH element means . */
1108 if (*entry == '\0')
1109 entry = ".";
1110
1111 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1112
1113 if (access(buf, R_OK|X_OK) == 0) {
1114 executable_name = strdup(buf);
1115 vg_assert(NULL != executable_name);
1116 return True;
1117 }
1118 return False;
1119}
1120
nethercote71980f02004-01-24 18:18:54 +00001121static const char* find_executable(const char* exec)
1122{
1123 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001124 executable_name = exec;
1125 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001126 /* no '/' - we need to search the path */
1127 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001128 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001129 }
thughes4ad52d02004-06-27 17:37:21 +00001130 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001131}
1132
1133
1134/*====================================================================*/
1135/*=== Loading tools ===*/
1136/*====================================================================*/
1137
1138static void list_tools(void)
1139{
1140 DIR *dir = opendir(VG_(libdir));
1141 struct dirent *de;
1142 int first = 1;
1143
1144 if (dir == NULL) {
1145 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001146 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001147 return;
1148 }
1149
nethercotef4928da2004-06-15 10:54:40 +00001150 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001151 int len = strlen(de->d_name);
1152
njn063c5402004-11-22 16:58:05 +00001153 /* look for vgtool_TOOL.so names */
1154 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1155 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001156 VG_STREQ(de->d_name + len - 3, ".so")) {
1157 if (first) {
1158 fprintf(stderr, "Available tools:\n");
1159 first = 0;
1160 }
1161 de->d_name[len-3] = '\0';
1162 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001163 }
1164 }
1165
1166 closedir(dir);
1167
1168 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001169 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1170 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001171}
1172
1173
1174/* Find and load a tool, and check it looks ok. Also looks to see if there's
1175 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001176static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001177 ToolInfo** toolinfo_out, char **preloadpath_out )
1178{
1179 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001180 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001181 char buf[len];
1182 void* handle;
1183 ToolInfo* toolinfo;
1184 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001185
1186 // XXX: allowing full paths for --tool option -- does it make sense?
1187 // Doesn't allow for vgpreload_<tool>.so.
1188
1189 if (strchr(toolname, '/') != 0) {
1190 /* toolname contains '/', and so must be a pathname */
1191 handle = dlopen(toolname, RTLD_NOW);
1192 } else {
1193 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001194 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001195 handle = dlopen(buf, RTLD_NOW);
1196
1197 if (handle != NULL) {
1198 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1199 if (access(buf, R_OK) == 0) {
1200 preloadpath = strdup(buf);
1201 vg_assert(NULL != preloadpath);
1202 }
1203 }
1204 }
1205
1206 ok = (NULL != handle);
1207 if (!ok) {
1208 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1209 goto bad_load;
1210 }
1211
njn51d827b2005-05-09 01:02:08 +00001212 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001213 ok = (NULL != toolinfo);
1214 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001215 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001216 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1217 goto bad_load;
1218 }
1219
1220 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001221 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1222 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001223 if (!ok) {
1224 fprintf(stderr, "Error:\n"
1225 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001226 " Interface version used by core is: %d (size %d)\n"
1227 " Interface version used by tool is: %d (size %d)\n"
1228 " The version numbers must match.\n",
1229 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001230 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001231 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001232 toolinfo->sizeof_ToolInfo);
1233 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001234 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001235 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001236 else
nethercote996901a2004-08-03 13:29:09 +00001237 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001238 goto bad_load;
1239 }
1240
njn8a97c6d2005-03-31 04:37:24 +00001241 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001242 *toolinfo_out = toolinfo;
1243 *preloadpath_out = preloadpath;
1244 return;
1245
1246
1247 bad_load:
1248 if (handle != NULL)
1249 dlclose(handle);
1250
nethercotef4928da2004-06-15 10:54:40 +00001251 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001252 list_tools();
1253 exit(127);
1254}
1255
nethercotef4928da2004-06-15 10:54:40 +00001256
1257/*====================================================================*/
1258/*=== Command line errors ===*/
1259/*====================================================================*/
1260
njnbe9b47b2005-05-15 16:22:58 +00001261static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001262{
njnbe9b47b2005-05-15 16:22:58 +00001263 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001264 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001265}
1266
1267void VG_(bad_option) ( Char* opt )
1268{
njnbe9b47b2005-05-15 16:22:58 +00001269 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001270 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001271 VG_(printf)("valgrind: Use --help for more information.\n");
1272 VG_(exit)(1);
1273}
1274
nethercotef4928da2004-06-15 10:54:40 +00001275static void missing_prog ( void )
1276{
njnbe9b47b2005-05-15 16:22:58 +00001277 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001278 VG_(printf)("valgrind: no program specified\n");
1279 VG_(printf)("valgrind: Use --help for more information.\n");
1280 VG_(exit)(1);
1281}
1282
1283static void config_error ( Char* msg )
1284{
njnbe9b47b2005-05-15 16:22:58 +00001285 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001286 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1287 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1288 VG_(exit)(1);
1289}
1290
1291
nethercote71980f02004-01-24 18:18:54 +00001292/*====================================================================*/
1293/*=== Loading the client ===*/
1294/*====================================================================*/
1295
nethercotef4928da2004-06-15 10:54:40 +00001296static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001297 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1298{
1299 // If they didn't specify an executable with --exec, and didn't specify
1300 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001301 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001302 if (cl_argv[0] == NULL ||
1303 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1304 {
nethercotef4928da2004-06-15 10:54:40 +00001305 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001306 }
1307 }
1308
1309 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001310 info->exe_base = VG_(client_base);
1311 info->exe_end = VG_(client_end);
1312 info->argv = cl_argv;
1313
nethercotef4928da2004-06-15 10:54:40 +00001314 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001315 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001316 // Totally zero 'info' before continuing.
1317 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001318 } else {
1319 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001320 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001321 ret = do_exec(exec, info);
1322 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001323 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1324 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001325 exit(127);
1326 }
1327 }
1328
1329 /* Copy necessary bits of 'info' that were filled in */
1330 *client_eip = info->init_eip;
1331 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1332}
1333
nethercote969ecf12004-10-13 17:29:01 +00001334/*====================================================================*/
1335/*=== Address space unpadding ===*/
1336/*====================================================================*/
1337
1338typedef struct {
1339 char* killpad_start;
1340 char* killpad_end;
1341 struct stat* killpad_padstat;
1342} killpad_extra;
1343
1344static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1345 int maj, int min, int ino, void* ex)
1346{
1347 killpad_extra* extra = ex;
1348 void *b, *e;
1349 int res;
1350
1351 vg_assert(NULL != extra->killpad_padstat);
1352
1353 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1354 extra->killpad_padstat->st_ino != ino)
1355 return 1;
1356
1357 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1358 return 1;
1359
1360 if (segstart <= extra->killpad_start)
1361 b = extra->killpad_start;
1362 else
1363 b = segstart;
1364
1365 if (segend >= extra->killpad_end)
1366 e = extra->killpad_end;
1367 else
1368 e = segend;
1369
1370 res = munmap(b, (char *)e-(char *)b);
1371 vg_assert(0 == res);
1372
1373 return 1;
1374}
1375
1376// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001377static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001378{
1379 static struct stat padstat;
1380 killpad_extra extra;
1381 int res;
1382
sewardjb5f6f512005-03-10 23:59:00 +00001383 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001384
1385 res = fstat(padfile, &padstat);
1386 vg_assert(0 == res);
1387 extra.killpad_padstat = &padstat;
1388 extra.killpad_start = start;
1389 extra.killpad_end = end;
1390 foreach_map(killpad, &extra);
1391}
1392
sewardj2c5ffbe2005-03-12 13:32:06 +00001393static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001394{
1395 int res = close(padfile);
1396 vg_assert(0 == res);
1397}
1398
sewardj71bc3cb2005-05-19 00:25:45 +00001399/*====================================================================*/
1400/*=== Command-line: variables, processing, etc ===*/
1401/*====================================================================*/
1402
1403// See pub_{core,tool}_options.h for explanations of all these.
1404
sewardj2c5ffbe2005-03-12 13:32:06 +00001405static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001406{
njn25e49d8e72002-09-23 09:36:25 +00001407 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001408"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001409"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001410" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001411" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001412" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001413" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001414" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001415" -q --quiet run silently; only print error msgs\n"
1416" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001417" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001418" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001419" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001420" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001421"\n"
1422" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001423" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001424" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001425" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001426" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001427" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001428"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001429" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001430" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1431" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001432" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001433" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001434" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001435" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001436" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1437" --show-below-main=no|yes continue stack traces below main() [no]\n"
1438" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001439" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001440" --db-attach=no|yes start debugger when errors detected? [no]\n"
1441" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1442" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001443" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1444" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001445"\n";
njn7cf0bd32002-06-08 13:36:03 +00001446
njn25e49d8e72002-09-23 09:36:25 +00001447 Char* usage2 =
1448"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001449" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001450" --sanity-level=<number> level of sanity checking to do [1]\n"
1451" --single-step=no|yes translate each instr separately? [no]\n"
1452" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001453" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001454" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001455" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1456" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001457" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001458" --trace-syscalls=no|yes show all system calls? [no]\n"
1459" --trace-signals=no|yes show signal handling details? [no]\n"
1460" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001461" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001462" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001463" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001464#if 0
1465" --model-pthreads=yes|no model the pthreads library [no]\n"
1466#endif
1467" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001468"\n"
1469" --vex-iropt-verbosity 0 .. 9 [0]\n"
1470" --vex-iropt-level 0 .. 2 [2]\n"
1471" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001472" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1473" --vex-guest-max-insns 1 .. 100 [50]\n"
1474" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1475"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001476" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001477" 1000 0000 show conversion into IR\n"
1478" 0100 0000 show after initial opt\n"
1479" 0010 0000 show after instrumentation\n"
1480" 0001 0000 show after second opt\n"
1481" 0000 1000 show after tree building\n"
1482" 0000 0100 show selecting insns\n"
1483" 0000 0010 show after reg-alloc\n"
1484" 0000 0001 show final assembly\n"
1485"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001486" debugging options for Valgrind tools that report errors\n"
1487" --dump-error=<number> show translation for basic block associated\n"
1488" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001489"\n";
njn3e884182003-04-15 13:03:23 +00001490
1491 Char* usage3 =
1492"\n"
nethercote71980f02004-01-24 18:18:54 +00001493" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001494"\n"
njn53612422005-03-12 16:22:54 +00001495" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001496" and licensed under the GNU General Public License, version 2.\n"
1497" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001498"\n"
nethercote137bc552003-11-14 17:47:54 +00001499" Tools are copyright and licensed by their authors. See each\n"
1500" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001501"\n";
njn7cf0bd32002-06-08 13:36:03 +00001502
njnbe9b47b2005-05-15 16:22:58 +00001503 // Ensure the message goes to stdout
1504 VG_(clo_log_fd) = 1;
1505 vg_assert( !VG_(logging_to_socket) );
1506
fitzhardinge98abfc72003-12-16 02:05:15 +00001507 VG_(printf)(usage1);
1508 if (VG_(details).name) {
1509 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001510 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001511 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001512 else
1513 VG_(printf)(" (none)\n");
1514 }
nethercote6c999f22004-01-31 22:55:15 +00001515 if (debug_help) {
1516 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001517
nethercote6c999f22004-01-31 22:55:15 +00001518 if (VG_(details).name) {
1519 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1520
1521 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001522 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001523 else
1524 VG_(printf)(" (none)\n");
1525 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001526 }
nethercote421281e2003-11-20 16:20:55 +00001527 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001528 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001529}
sewardjde4a1d02002-03-22 01:27:54 +00001530
nethercote71980f02004-01-24 18:18:54 +00001531static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001532 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001533{
nethercote71980f02004-01-24 18:18:54 +00001534 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001535
sewardj8b635a42004-11-22 19:01:47 +00001536 LibVEX_default_VexControl(& VG_(clo_vex_control));
1537
nethercote71980f02004-01-24 18:18:54 +00001538 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001539 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001540
nethercotef6a1d502004-08-09 12:21:57 +00001541 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001542 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001543 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001544
nethercotef6a1d502004-08-09 12:21:57 +00001545 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1546 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001547 *need_help = 1;
1548
nethercotef6a1d502004-08-09 12:21:57 +00001549 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001550 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001551
nethercotef6c99d72004-11-09 14:35:43 +00001552 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001553 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001554
nethercotef6a1d502004-08-09 12:21:57 +00001555 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1556 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001557 }
1558 }
nethercote71980f02004-01-24 18:18:54 +00001559}
1560
nethercote5ee67ca2004-06-22 14:00:09 +00001561static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001562{
nethercotef8548672004-06-21 12:42:35 +00001563 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001564 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001565 enum {
1566 VgLogTo_Fd,
1567 VgLogTo_File,
1568 VgLogTo_FileExactly,
1569 VgLogTo_Socket
1570 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001571
nethercotee1730692003-11-20 10:38:07 +00001572 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001573 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001574
sewardj19d81412002-06-03 01:10:40 +00001575 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001576 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001577 config_error("Please use absolute paths in "
1578 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001579
njnc6168192004-11-29 13:54:10 +00001580// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001581#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001582 {
sewardjb5f6f512005-03-10 23:59:00 +00001583 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001584 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1585 switch(auxp[0]) {
1586 case AT_SYSINFO:
1587 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1588 break;
1589 }
1590 }
1591 }
1592#endif
sewardjde4a1d02002-03-22 01:27:54 +00001593
nethercotef6a1d502004-08-09 12:21:57 +00001594 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001595
nethercotef6a1d502004-08-09 12:21:57 +00001596 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001597 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001598
thughes3bfd5a02004-07-18 08:05:44 +00001599 /* Look for a colon in the switch name */
1600 while (*colon && *colon != ':' && *colon != '=')
1601 colon++;
nethercote71980f02004-01-24 18:18:54 +00001602
1603 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001604 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001605 if (VG_CLO_STREQN(2, arg, "--") &&
1606 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1607 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1608 {
1609 // prefix matches, convert "--toolname:foo" to "--foo"
1610 if (0)
1611 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001612 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001613 arg[0] = '-';
1614 arg[1] = '-';
1615
1616 } else {
1617 // prefix doesn't match, skip to next arg
1618 continue;
1619 }
1620 }
1621
fitzhardinge98abfc72003-12-16 02:05:15 +00001622 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001623 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1624 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1625 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001626
njn45270a22005-03-27 01:00:11 +00001627 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001628
nethercote71980f02004-01-24 18:18:54 +00001629 else if (VG_CLO_STREQ(arg, "-v") ||
1630 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001631 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001632
nethercote71980f02004-01-24 18:18:54 +00001633 else if (VG_CLO_STREQ(arg, "-q") ||
1634 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001635 VG_(clo_verbosity)--;
1636
sewardj1cf558c2005-04-25 01:36:56 +00001637 else if (VG_CLO_STREQ(arg, "-d")) {
1638 /* do nothing */
1639 }
1640
sewardj71bc3cb2005-05-19 00:25:45 +00001641 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001642 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1643 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1644 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1645 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1646 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1647 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1648 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001649 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001650 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1651 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1652 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1653 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1654 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1655 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1656 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1657 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1658 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001659 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001660 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1661 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1662 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1663 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1664 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001665
njn45270a22005-03-27 01:00:11 +00001666 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1667 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001668
njn45270a22005-03-27 01:00:11 +00001669 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1670 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1671 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1672 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1673 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001674
njn45270a22005-03-27 01:00:11 +00001675 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001676 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001677 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001678 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001679 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001680 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001681 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001682 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001683 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001684 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001685 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001686 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1687
nethercotef8548672004-06-21 12:42:35 +00001688 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001689 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001690 VG_(clo_log_name) = NULL;
1691 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001692 }
1693
nethercotef8548672004-06-21 12:42:35 +00001694 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001695 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001696 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001697 }
njnd6bc3c32005-03-27 00:44:31 +00001698
sewardj603d4102005-01-11 14:01:02 +00001699 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001700 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001701 VG_(clo_log_name) = &arg[19];
1702 }
sewardjde4a1d02002-03-22 01:27:54 +00001703
nethercotef8548672004-06-21 12:42:35 +00001704 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001705 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001706 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001707 }
1708
nethercote71980f02004-01-24 18:18:54 +00001709 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001710 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001711 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001712 VG_(message)(Vg_UserMsg,
1713 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001714 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001715 }
nethercote71980f02004-01-24 18:18:54 +00001716 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001717 VG_(clo_n_suppressions)++;
1718 }
sewardjde4a1d02002-03-22 01:27:54 +00001719
sewardjfa8ec112005-01-19 11:55:34 +00001720 /* "stuvwxyz" --> stuvwxyz (binary) */
1721 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1722 Int j;
1723 char* opt = & arg[14];
1724
1725 if (8 != VG_(strlen)(opt)) {
1726 VG_(message)(Vg_UserMsg,
1727 "--trace-flags argument must have 8 digits");
1728 VG_(bad_option)(arg);
1729 }
1730 for (j = 0; j < 8; j++) {
1731 if ('0' == opt[j]) { /* do nothing */ }
1732 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1733 else {
1734 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1735 "contain 0s and 1s");
1736 VG_(bad_option)(arg);
1737 }
1738 }
1739 }
1740
1741 /* "stuvwxyz" --> stuvwxyz (binary) */
1742 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001743 Int j;
nethercote71980f02004-01-24 18:18:54 +00001744 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001745
sewardj2a99cf62004-11-24 10:44:19 +00001746 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001747 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001748 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001749 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001750 }
sewardj8b635a42004-11-22 19:01:47 +00001751 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001752 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001753 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001754 else {
sewardjfa8ec112005-01-19 11:55:34 +00001755 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001756 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001757 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001758 }
1759 }
1760 }
sewardjde4a1d02002-03-22 01:27:54 +00001761
njn45270a22005-03-27 01:00:11 +00001762 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001763
sewardjd153fae2005-01-10 17:24:47 +00001764 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1765 VG_(clo_gen_suppressions) = 0;
1766 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1767 VG_(clo_gen_suppressions) = 1;
1768 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1769 VG_(clo_gen_suppressions) = 2;
1770
nethercote71980f02004-01-24 18:18:54 +00001771 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001772 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001773 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001774 }
njn8c0b3bb2005-03-12 21:20:39 +00001775 skip_arg:
1776 if (arg != vg_argv[i])
1777 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001778 }
1779
sewardj998d40d2004-12-06 14:24:52 +00001780 /* Make VEX control parameters sane */
1781
1782 if (VG_(clo_vex_control).guest_chase_thresh
1783 >= VG_(clo_vex_control).guest_max_insns)
1784 VG_(clo_vex_control).guest_chase_thresh
1785 = VG_(clo_vex_control).guest_max_insns - 1;
1786
1787 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1788 VG_(clo_vex_control).guest_chase_thresh = 0;
1789
1790 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001791
njnf9ebf672003-05-12 21:41:30 +00001792 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001793 VG_(clo_verbosity) = 0;
1794
nethercote04d0fbc2004-01-26 16:48:06 +00001795 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001796 VG_(message)(Vg_UserMsg, "");
1797 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001798 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001799 VG_(message)(Vg_UserMsg,
1800 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001801 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001802 }
1803
njnbe9b47b2005-05-15 16:22:58 +00001804 if (VG_(clo_gen_suppressions) > 0 &&
1805 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1806 VG_(message)(Vg_UserMsg,
1807 "Can't use --gen-suppressions= with this tool,");
1808 VG_(message)(Vg_UserMsg,
1809 "as it doesn't generate errors.");
1810 VG_(bad_option)("--gen-suppressions=");
1811 }
1812
sewardj71bc3cb2005-05-19 00:25:45 +00001813 /* If we've been asked to emit XML, mash around various other
1814 options so as to constrain the output somewhat, and to remove
1815 any need for user input during the run. */
1816 if (VG_(clo_xml)) {
1817 /* Disable suppression generation (requires user input) */
1818 VG_(clo_gen_suppressions) = 0;
1819 /* Disable attaching to GDB (requires user input) */
1820 VG_(clo_db_attach) = False;
1821 /* Set a known verbosity level */
1822 VG_(clo_verbosity) = 1;
1823 /* Disable error limits (this might be a bad idea!) */
1824 VG_(clo_error_limit) = False;
1825 /* Disable emulation warnings */
1826 VG_(clo_show_emwarns) = False;
1827 /* Disable waiting for GDB to debug Valgrind */
1828 VG_(clo_wait_for_gdb) = False;
1829 /* No file-descriptor leak checking yet */
1830 VG_(clo_track_fds) = False;
1831 /* Also, we want to set options for the leak checker, but that
1832 will have to be done in Memcheck's flag-handling code, not
1833 here. */
1834 }
1835
njnbe9b47b2005-05-15 16:22:58 +00001836 /* All non-logging-related options have been checked. If the logging
1837 option specified is ok, we can switch to it, as we know we won't
1838 have to generate any other command-line-related error messages.
1839 (So far we should be still attached to stderr, so we can show on
1840 the terminal any problems to do with processing command line
1841 opts.)
1842
1843 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001844 should be connected to whatever sink has been selected, and we
1845 indiscriminately chuck stuff into it without worrying what the
1846 nature of it is. Oh the wonder of Unix streams. */
1847
njnbe9b47b2005-05-15 16:22:58 +00001848 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1849 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001850
njnbe9b47b2005-05-15 16:22:58 +00001851 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001852
sewardj4cf05692002-10-27 20:28:29 +00001853 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001854 vg_assert(VG_(clo_log_name) == NULL);
1855 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001856 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001857
sewardj4cf05692002-10-27 20:28:29 +00001858 case VgLogTo_File: {
1859 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001860 Int seq = 0;
1861 Int pid = VG_(getpid)();
1862
nethercotef8548672004-06-21 12:42:35 +00001863 vg_assert(VG_(clo_log_name) != NULL);
1864 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001865
nethercote71980f02004-01-24 18:18:54 +00001866 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001867 if (seq == 0)
1868 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001869 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001870 else
1871 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001872 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001873 seq++;
1874
njnbe9b47b2005-05-15 16:22:58 +00001875 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001876 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001877 = VG_(open)(logfilename,
1878 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1879 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001880 if (eventually_log_fd >= 0) {
1881 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001882 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001883 } else {
njnbe9b47b2005-05-15 16:22:58 +00001884 // If the file already existed, we try the next name. If it
1885 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001886 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001887 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001888 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001889 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001890 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001891 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001892 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001893 }
1894 }
1895 }
sewardj603d4102005-01-11 14:01:02 +00001896 break; /* switch (VG_(clo_log_to)) */
1897 }
1898
1899 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001900 vg_assert(VG_(clo_log_name) != NULL);
1901 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001902
1903 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001904 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001905 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1906 VKI_S_IRUSR|VKI_S_IWUSR);
1907 if (eventually_log_fd >= 0) {
1908 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001909 } else {
sewardj603d4102005-01-11 14:01:02 +00001910 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001911 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001912 VG_(clo_log_name));
1913 VG_(bad_option)(
1914 "--log-file-exactly=<file> (didn't work out for some reason.)");
1915 /*NOTREACHED*/
1916 }
1917 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001918 }
1919
1920 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001921 vg_assert(VG_(clo_log_name) != NULL);
1922 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1923 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1924 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001925 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001926 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001927 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001928 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001929 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001930 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001931 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001932 }
nethercotef8548672004-06-21 12:42:35 +00001933 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001935 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001936 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001937 VG_(message)(Vg_UserMsg,
1938 "Log messages will sent to stderr instead." );
1939 VG_(message)(Vg_UserMsg,
1940 "" );
1941 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001942 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001943 } else {
nethercotef8548672004-06-21 12:42:35 +00001944 vg_assert(eventually_log_fd > 0);
1945 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001946 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001947 }
sewardj73cf3bc2002-11-03 03:20:15 +00001948 break;
1949 }
sewardj4cf05692002-10-27 20:28:29 +00001950 }
1951
sewardj71bc3cb2005-05-19 00:25:45 +00001952
1953 /* Check that the requested tool actually supports XML output. */
1954 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1955 VG_(clo_xml) = False;
1956 VG_(message)(Vg_UserMsg,
1957 "Currently only Memcheck supports XML output.");
1958 VG_(bad_option)("--xml=yes");
1959 /*NOTREACHED*/
1960 }
1961
njnbe9b47b2005-05-15 16:22:58 +00001962 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1963 // XXX: this is more or less duplicating the behaviour of the calls to
1964 // VG_(safe_fd)() above, although this does not close the original fd.
1965 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1966 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001967 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001968 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001969 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1970 else {
nethercotef8548672004-06-21 12:42:35 +00001971 VG_(clo_log_fd) = eventually_log_fd;
1972 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001973 }
1974
sewardj4cf05692002-10-27 20:28:29 +00001975 /* Ok, the logging sink is running now. Print a suitable preamble.
1976 If logging to file or a socket, write details of parent PID and
1977 command line args, to help people trying to interpret the
1978 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001979
sewardj71bc3cb2005-05-19 00:25:45 +00001980 if (VG_(clo_xml)) {
1981 VG_(message)(Vg_UserMsg, "");
1982 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1983 VG_(message)(Vg_UserMsg, "");
1984 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1985 VG_(message)(Vg_UserMsg, "");
1986 }
1987
1988 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1989 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1990
sewardj83adf412002-05-01 01:25:45 +00001991 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001992 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001993 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1994 xpre,
njnd04b7c62002-10-03 14:05:52 +00001995 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001996 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001997 NULL == VG_(details).version
1998 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001999 VG_(details).description,
2000 xpost);
2001 VG_(message)(Vg_UserMsg, "%s%s%s",
2002 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00002003
njnd04b7c62002-10-03 14:05:52 +00002004 /* Core details */
2005 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002006 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
2007 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00002008 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002009 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
2010 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00002011 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002012 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
2013 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00002014 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002015 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
2016 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00002017 }
2018
njnbe9b47b2005-05-15 16:22:58 +00002019 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002020 VG_(message)(Vg_UserMsg, "");
2021 VG_(message)(Vg_UserMsg,
2022 "My PID = %d, parent PID = %d. Prog and args are:",
2023 VG_(getpid)(), VG_(getppid)() );
2024 for (i = 0; i < VG_(client_argc); i++)
2025 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2026 }
sewardj71bc3cb2005-05-19 00:25:45 +00002027 else
2028 if (VG_(clo_xml)) {
2029 VG_(message)(Vg_UserMsg, "");
2030 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
2031 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00002032 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00002033 VG_(message)(Vg_UserMsg, "");
2034 VG_(message)(Vg_UserMsg, "<argv>");
2035 for (i = 0; i < VG_(client_argc); i++)
2036 VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
2037 VG_(message)(Vg_UserMsg, "</argv>");
2038 }
sewardj4cf05692002-10-27 20:28:29 +00002039
sewardjde4a1d02002-03-22 01:27:54 +00002040 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002041 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00002042 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002043 VG_(message)(Vg_DebugMsg, "");
2044 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2045 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002046 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002047 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002048
njn1fd5eb22005-03-13 05:43:23 +00002049 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002050 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002051 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002052 }
nethercotea70f7352004-04-18 12:08:46 +00002053
njn1fd5eb22005-03-13 05:43:23 +00002054 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002055 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2056 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002057 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002058 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002059# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002060 Char version_buf[BUF_LEN];
2061 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002062 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002063 if (n > 0) {
2064 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002065 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002066 } else {
njn1fd5eb22005-03-13 05:43:23 +00002067 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002068 }
2069 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002070# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002071 }
sewardjde4a1d02002-03-22 01:27:54 +00002072 }
2073
fitzhardinge98abfc72003-12-16 02:05:15 +00002074 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002075 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002076 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002077 needs one, load the default */
2078 static const Char default_supp[] = "default.supp";
2079 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2080 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2081 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2082 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2083 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002084 }
2085}
2086
nethercotef6a1d502004-08-09 12:21:57 +00002087// Build the string for VALGRINDCLO.
2088Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2089{
2090 /* If we're tracing the children, then we need to start it
2091 with our starter+arguments, which are copied into VALGRINDCLO,
2092 except the --exec= option is changed if present.
2093 */
2094 Int i;
2095 Char *exec;
2096 Char *cp;
2097 Char *optvar;
2098 Int optlen, execlen;
2099
2100 // All these allocated blocks are not free - because we're either
2101 // going to exec, or panic when we fail.
2102
2103 // Create --exec= option: "--exec=<exename>"
2104 exec = VG_(arena_malloc)(VG_AR_CORE,
2105 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2106 vg_assert(NULL != exec);
2107 VG_(sprintf)(exec, "--exec=%s", exename);
2108
2109 // Allocate space for optvar (may overestimate by counting --exec twice,
2110 // no matter)
2111 optlen = 1;
2112 for (i = 0; i < vg_argc; i++)
2113 optlen += VG_(strlen)(vg_argv[i]) + 1;
2114 optlen += VG_(strlen)(exec)+1;
2115 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2116
2117 // Copy all valgrind args except the old --exec (if present)
2118 // VG_CLO_SEP is the separator.
2119 cp = optvar;
2120 for (i = 1; i < vg_argc; i++) {
2121 Char *arg = vg_argv[i];
2122
2123 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2124 // don't copy existing --exec= arg
2125 } else if (VG_(strcmp)(arg, "--") == 0) {
2126 // stop at "--"
2127 break;
2128 } else {
2129 // copy non "--exec" arg
2130 Int len = VG_(strlen)(arg);
2131 VG_(memcpy)(cp, arg, len);
2132 cp += len;
2133 *cp++ = VG_CLO_SEP;
2134 }
2135 }
2136 // Add the new --exec= option
2137 execlen = VG_(strlen)(exec);
2138 VG_(memcpy)(cp, exec, execlen);
2139 cp += execlen;
2140 *cp++ = VG_CLO_SEP;
2141
2142 *cp = '\0';
2143
2144 return optvar;
2145}
2146
2147// Build "/proc/self/fd/<execfd>".
2148Char* VG_(build_child_exename)( void )
2149{
2150 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2151 vg_assert(NULL != exename);
2152 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2153 return exename;
2154}
2155
sewardjde4a1d02002-03-22 01:27:54 +00002156
nethercote71980f02004-01-24 18:18:54 +00002157/*====================================================================*/
2158/*=== File descriptor setup ===*/
2159/*====================================================================*/
2160
2161static void setup_file_descriptors(void)
2162{
2163 struct vki_rlimit rl;
2164
2165 /* Get the current file descriptor limits. */
2166 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2167 rl.rlim_cur = 1024;
2168 rl.rlim_max = 1024;
2169 }
2170
2171 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002172 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2173 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002174 } else {
2175 rl.rlim_cur = rl.rlim_max;
2176 }
2177
2178 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002179 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2180 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002181
2182 /* Update the soft limit. */
2183 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2184
nethercotef6a1d502004-08-09 12:21:57 +00002185 if (vgexecfd != -1)
2186 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002187 if (VG_(clexecfd) != -1)
2188 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2189}
2190
nethercote71980f02004-01-24 18:18:54 +00002191/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002192/*=== Initialise program data/text, etc. ===*/
2193/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002194
sewardjb5f6f512005-03-10 23:59:00 +00002195static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2196 UInt dev, UInt ino, ULong foffset,
2197 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002198{
nethercote71980f02004-01-24 18:18:54 +00002199 /* Only record valgrind mappings for now, without loading any
2200 symbols. This is so we know where the free space is before we
2201 start allocating more memory (note: heap is OK, it's just mmap
2202 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002203 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002204 VG_(debugLog)(2, "main",
2205 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002206 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002207 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002208 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2209 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002210 /* update VG_(valgrind_last) if it looks wrong */
2211 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002212 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002213 }
sewardjde4a1d02002-03-22 01:27:54 +00002214}
2215
nethercote71980f02004-01-24 18:18:54 +00002216// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002217Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002218
sewardjb5f6f512005-03-10 23:59:00 +00002219/*
2220 This second pass adds in client mappings, and loads symbol tables
2221 for all interesting mappings. The trouble is that things can
2222 change as we go, because we're calling the Tool to track memory as
2223 we find it.
2224
2225 So for Valgrind mappings, we don't replace any mappings which
2226 aren't still identical (which will include the .so mappings, so we
2227 will load their symtabs)>
2228 */
2229static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2230 UInt dev, UInt ino, ULong foffset,
2231 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002232{
nethercote71980f02004-01-24 18:18:54 +00002233 UInt flags;
2234 Bool is_stack_segment;
2235 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002236
nethercote71980f02004-01-24 18:18:54 +00002237 is_stack_segment
2238 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002239
sewardj8c615892005-04-25 02:38:28 +00002240 VG_(debugLog)(2, "main",
2241 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002242 (void*)start, (void*)(start+size), prot, is_stack_segment,
2243 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002244
nethercote71980f02004-01-24 18:18:54 +00002245 if (is_stack_segment)
2246 flags = SF_STACK | SF_GROWDOWN;
2247 else
2248 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002249
nethercote71980f02004-01-24 18:18:54 +00002250 if (filename != NULL)
2251 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002252
sewardjb5f6f512005-03-10 23:59:00 +00002253#if 0
2254 // This needs to be fixed properly. jrs 20050307
2255 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2256 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002257
sewardjb5f6f512005-03-10 23:59:00 +00002258 /* We have to be a bit careful about inserting new mappings into
2259 the Valgrind part of the address space. We're actively
2260 changing things as we parse these mappings, particularly in
2261 shadow memory, and so we don't want to overwrite those
2262 changes. Therefore, we only insert/update a mapping if it is
2263 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002264
sewardjb5f6f512005-03-10 23:59:00 +00002265 NOTE: we're only talking about the Segment list mapping
2266 metadata; this doesn't actually mmap anything more. */
2267 if (filename || (s && s->addr == start && s->len == size)) {
2268 flags |= SF_VALGRIND;
2269 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2270 } else {
2271 /* assert range is already mapped */
2272 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2273 }
2274 } else
2275#endif
2276 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2277
2278 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2279 VG_TRACK( new_mem_startup, start, size,
2280 !!(prot & VKI_PROT_READ),
2281 !!(prot & VKI_PROT_WRITE),
2282 !!(prot & VKI_PROT_EXEC));
2283 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002284
nethercote71980f02004-01-24 18:18:54 +00002285 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002286 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002287 vg_assert(0 != r_esp);
2288 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002289 if (0) {
2290 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002291 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002292 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2293 r_esp, start+size);
2294 }
nethercote71980f02004-01-24 18:18:54 +00002295 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002296 // what's this for?
2297 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002298 }
sewardjde4a1d02002-03-22 01:27:54 +00002299}
2300
2301
nethercote71980f02004-01-24 18:18:54 +00002302/*====================================================================*/
2303/*=== Sanity check machinery (permanently engaged) ===*/
2304/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002305
2306/* A fast sanity check -- suitable for calling circa once per
2307 millisecond. */
2308
nethercote885dd912004-08-03 23:14:00 +00002309void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002310{
sewardjb5f6f512005-03-10 23:59:00 +00002311 ThreadId tid;
2312
njn37cea302002-09-30 11:24:00 +00002313 VGP_PUSHCC(VgpCoreCheapSanity);
2314
nethercote27fec902004-06-16 21:26:32 +00002315 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002316
2317 /* --- First do all the tests that we can do quickly. ---*/
2318
nethercote297effd2004-08-02 15:07:57 +00002319 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002320
njn25e49d8e72002-09-23 09:36:25 +00002321 /* Check stuff pertaining to the memory check system. */
2322
2323 /* Check that nobody has spuriously claimed that the first or
2324 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002325 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002326 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002327 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002328 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002329 }
njn25e49d8e72002-09-23 09:36:25 +00002330
2331 /* --- Now some more expensive checks. ---*/
2332
2333 /* Once every 25 times, check some more expensive stuff. */
2334 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002335 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002336 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002337
njn37cea302002-09-30 11:24:00 +00002338 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002339 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002340
2341# if 0
2342 { void zzzmemscan(void); zzzmemscan(); }
2343# endif
2344
nethercote297effd2004-08-02 15:07:57 +00002345 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002346 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002347
2348 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002349 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002350 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002351 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002352 }
sewardjb5f6f512005-03-10 23:59:00 +00002353
2354 /* Check that Segments and /proc/self/maps match up */
2355 //vg_assert(VG_(sanity_check_memory)());
2356
2357 /* Look for stack overruns. Visit all threads. */
2358 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002359 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002360
2361 if (VG_(threads)[tid].status == VgTs_Empty ||
2362 VG_(threads)[tid].status == VgTs_Zombie)
2363 continue;
2364
2365 remains = VGA_(stack_unused)(tid);
2366 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002367 VG_(message)(Vg_DebugMsg,
2368 "WARNING: Thread %d is within %d bytes "
2369 "of running out of stack!",
2370 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002371 }
2372
njn25e49d8e72002-09-23 09:36:25 +00002373 /*
nethercote297effd2004-08-02 15:07:57 +00002374 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002375 */
njn37cea302002-09-30 11:24:00 +00002376 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002377 }
2378
nethercote27fec902004-06-16 21:26:32 +00002379 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002380 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002381 /* Check sanity of the low-level memory manager. Note that bugs
2382 in the client's code can cause this to fail, so we don't do
2383 this check unless specially asked for. And because it's
2384 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002385 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002386 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002387 }
njn37cea302002-09-30 11:24:00 +00002388 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002389}
nethercote71980f02004-01-24 18:18:54 +00002390
2391
2392/*====================================================================*/
2393/*=== main() ===*/
2394/*====================================================================*/
2395
nethercotec314eba2004-07-15 12:59:41 +00002396/*
2397 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002398 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002399 loads the client executable (and the dynamic linker, if necessary)
2400 into the client part, and calls into Valgrind proper.
2401
2402 The code is careful not to allow spurious mappings to appear in the
2403 wrong parts of the address space. In particular, to make sure
2404 dlopen puts things in the right place, it will pad out the forbidden
2405 chunks of address space so that dlopen is forced to put things where
2406 we want them.
2407
2408 The memory map it creates is:
2409
njn311c5d82005-05-15 21:03:42 +00002410 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002411 | client address space |
2412 : :
2413 : :
2414 | client stack |
2415 client_end +-------------------------+
2416 | redzone |
2417 shadow_base +-------------------------+
2418 | |
nethercote996901a2004-08-03 13:29:09 +00002419 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002420 | (may be 0 sized) |
2421 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002422 valgrind_base +-------------------------+
2423 | kickstart executable |
2424 | valgrind heap vvvvvvvvv| (barely used)
2425 - -
2426 | valgrind .so files |
2427 | and mappings |
2428 - -
2429 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002430 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002431 : kernel :
2432
2433 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2434 VG_(mmap)(), we need to build the segment skip-list, so we know where
2435 we can put things. However, building that structure requires
2436 allocating memory. So we need to a bootstrapping process. It's done
2437 by making VG_(arena_malloc)() have a special static superblock that's
2438 used for the first 1MB's worth of allocations. This is enough to
2439 build the segment skip-list.
2440*/
2441
thughes4ad52d02004-06-27 17:37:21 +00002442
sewardj1cf558c2005-04-25 01:36:56 +00002443/* This may be needed before m_mylibc is OK to run. */
2444static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2445{
2446 while (True) {
2447 if (*s1 == 0 && *s2 == 0) return 0;
2448 if (*s1 == 0) return -1;
2449 if (*s2 == 0) return 1;
2450
2451 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2452 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2453
2454 s1++; s2++;
2455 }
2456}
2457
2458
sewardjb5f6f512005-03-10 23:59:00 +00002459int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002460{
2461 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002462 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002463 const char *exec = NULL;
2464 char *preload; /* tool-specific LD_PRELOAD .so */
2465 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002466 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002467 struct exeinfo info;
2468 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002469 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002470 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002471 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002472 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002473 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002474
2475 //============================================================
2476 // Nb: startup is complex. Prerequisites are shown at every step.
2477 //
2478 // *** Be very careful when messing with the order ***
2479 //============================================================
2480
sewardj1cf558c2005-04-25 01:36:56 +00002481 //--------------------------------------------------------------
2482 // Start up the logging mechanism
2483 // p: none
2484 //--------------------------------------------------------------
2485 /* Start the debugging-log system ASAP. First find out how many
2486 "-d"s were specified. This is a pre-scan of the command line. */
2487 loglevel = 0;
2488 for (i = 1; i < argc; i++) {
2489 if (argv[i][0] != '-')
2490 break;
2491 if (0 == local_strcmp(argv[i], "--"))
2492 break;
2493 if (0 == local_strcmp(argv[i], "-d"))
2494 loglevel++;
2495 }
2496
2497 /* ... and start the debug logger. Now we can safely emit logging
2498 messages all through startup. */
2499 VG_(debugLog_startup)(loglevel, "Stage 2");
2500
nethercotef4928da2004-06-15 10:54:40 +00002501 //============================================================
2502 // Command line argument handling order:
2503 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002504 // (including the tool-specific usage)
2505 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002506 // * Then, if client is missing, abort with error msg
2507 // * Then, if any cmdline args are bad, abort with error msg
2508 //============================================================
2509
fitzhardingeb50068f2004-02-24 23:42:55 +00002510 // Get the current process datasize rlimit, and set it to zero.
2511 // This prevents any internal uses of brk() from having any effect.
2512 // We remember the old value so we can restore it on exec, so that
2513 // child processes will have a reasonable brk value.
2514 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2515 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2516 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002517
2518 // Get the current process stack rlimit.
2519 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2520
nethercote71980f02004-01-24 18:18:54 +00002521 //--------------------------------------------------------------
2522 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002523 // p: none
nethercote71980f02004-01-24 18:18:54 +00002524 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002525 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002526 {
sewardj1fbc1a52005-04-25 02:05:54 +00002527 void* init_sp = argv - 1;
2528 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002529 }
2530
2531 //--------------------------------------------------------------
2532 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002533 // p: none
nethercote71980f02004-01-24 18:18:54 +00002534 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002535 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002536 if (cp != NULL)
2537 VG_(libdir) = cp;
2538 }
2539
2540 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002541 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2542 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002543 // p: none
nethercote71980f02004-01-24 18:18:54 +00002544 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002545 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002546 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002547 pre_process_cmd_line_options(&need_help, &tool, &exec);
2548
2549 //==============================================================
2550 // Nb: once a tool is specified, the tool.so must be loaded even if
2551 // they specified --help or didn't specify a client program.
2552 //==============================================================
2553
2554 //--------------------------------------------------------------
2555 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002556 // p: set-libdir [for VG_(libdir)]
2557 // p: pre_process_cmd_line_options() [for 'tool']
2558 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002559 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002560 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002561
2562 //==============================================================
2563 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002564 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002565 //==============================================================
2566
2567 //--------------------------------------------------------------
2568 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002569 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002570 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002571 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002572 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002573
2574 //--------------------------------------------------------------
2575 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002576 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2577 // p: layout_remaining_space [so there's space]
2578 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002579 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002580 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002581
2582 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002583 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002584 // p: layout_remaining_space() [everything must be mapped in before now]
2585 // p: load_client() [ditto]
2586 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002587 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2588 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002589
2590 //--------------------------------------------------------------
2591 // Set up client's environment
2592 // p: set-libdir [for VG_(libdir)]
2593 // p: load_tool() [for 'preload']
2594 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002595 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002596 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002597
2598 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002599 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002600 // p: load_client() [for 'info']
2601 // p: fix_environment() [for 'env']
2602 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002603 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002604 {
sewardj1fbc1a52005-04-25 02:05:54 +00002605 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002606
sewardj1fbc1a52005-04-25 02:05:54 +00002607 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2608 &client_auxv);
2609 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002610 }
nethercote71980f02004-01-24 18:18:54 +00002611
sewardj1fbc1a52005-04-25 02:05:54 +00002612 VG_(debugLog)(2, "main",
2613 "Client info: "
2614 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2615 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2616 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002617
2618 //==============================================================
2619 // Finished setting up operating environment. Now initialise
2620 // Valgrind. (This is where the old VG_(main)() started.)
2621 //==============================================================
2622
2623 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002624 // setup file descriptors
2625 // p: n/a
2626 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002627 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002628 setup_file_descriptors();
2629
2630 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002631 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002632 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002633 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002634 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002635 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2636
2637 //==============================================================
2638 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2639 //==============================================================
2640
2641 //--------------------------------------------------------------
2642 // Init tool: pre_clo_init, process cmd line, post_clo_init
2643 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002644 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002645 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2646 // p: parse_procselfmaps [so VG segments are setup so tool can
2647 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002648 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002649 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002650 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002651 VG_(sanity_check_needs)();
2652
nethercotef4928da2004-06-15 10:54:40 +00002653 // If --tool and --help/--help-debug was given, now give the core+tool
2654 // help message
nethercotef4928da2004-06-15 10:54:40 +00002655 if (need_help) {
2656 usage(/*--help-debug?*/2 == need_help);
2657 }
nethercotec314eba2004-07-15 12:59:41 +00002658 process_cmd_line_options(client_auxv, tool);
2659
njn51d827b2005-05-09 01:02:08 +00002660 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002661
2662 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002663 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002664 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002665 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002666 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002667 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002668 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002669 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002670 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002671 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002672
sewardj21c6d0f2005-05-02 10:33:44 +00002673#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002674 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002675 // Protect client trampoline page (which is also sysinfo stuff)
2676 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002677 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002678 {
2679 Segment *seg;
2680 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2681 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002682
sewardjb5f6f512005-03-10 23:59:00 +00002683 /* Make sure this segment isn't treated as stack */
2684 seg = VG_(find_segment)(VG_(client_trampoline_code));
2685 if (seg)
2686 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2687 }
sewardj21c6d0f2005-05-02 10:33:44 +00002688#endif
sewardjb5f6f512005-03-10 23:59:00 +00002689
nethercotec314eba2004-07-15 12:59:41 +00002690 //==============================================================
2691 // Can use VG_(map)() after segments set up
2692 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002693
2694 //--------------------------------------------------------------
2695 // Allow GDB attach
2696 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2697 //--------------------------------------------------------------
2698 /* Hook to delay things long enough so we can get the pid and
2699 attach GDB in another shell. */
2700 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002701 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002702 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2703 /* jrs 20050206: I don't understand why this works on x86. On
2704 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2705 work. */
2706 /* do "jump *$eip" to skip this in gdb (x86) */
2707 //VG_(do_syscall0)(__NR_pause);
2708 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002709 }
2710
sewardjb5d320c2005-03-13 18:57:15 +00002711 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002712 // Search for file descriptors that are inherited from our parent
2713 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2714 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002715 if (VG_(clo_track_fds)) {
2716 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002717 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002718 }
nethercote71980f02004-01-24 18:18:54 +00002719
2720 //--------------------------------------------------------------
2721 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002722 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2723 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002724 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002725 VG_(scheduler_init)();
2726
2727 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002728 // Initialise the pthread model
2729 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002730 // load_client() [for 'client_eip']
2731 // setup_client_stack() [for 'sp_at_startup']
2732 // setup_scheduler() [for the rest of state 1 stuff]
2733 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002734 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002735 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002736
2737 // Tell the tool that we just wrote to the registers.
2738 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2739 sizeof(VexGuestArchState));
2740
sewardj2a99cf62004-11-24 10:44:19 +00002741 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002742 // Initialise the pthread model
2743 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002744 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002745 //if (VG_(clo_model_pthreads))
2746 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002747
2748 //--------------------------------------------------------------
2749 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002750 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002751 //--------------------------------------------------------------
2752 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002753 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002754 VG_(sigstartup_actions)();
2755
2756 //--------------------------------------------------------------
2757 // Perhaps we're profiling Valgrind?
2758 // p: process_cmd_line_options() [for VG_(clo_profile)]
2759 // p: others?
2760 //
2761 // XXX: this seems to be broken? It always says the tool wasn't built
2762 // for profiling; vg_profile.c's functions don't seem to be overriding
2763 // vg_dummy_profile.c's?
2764 //
2765 // XXX: want this as early as possible. Looking for --profile
2766 // in pre_process_cmd_line_options() could get it earlier.
2767 //--------------------------------------------------------------
2768 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002769 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002770
2771 VGP_PUSHCC(VgpStartup);
2772
2773 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002774 // Read suppression file
2775 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2776 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002777 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2778 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002779 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002780 }
nethercote71980f02004-01-24 18:18:54 +00002781
2782 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002783 // Initialise translation table and translation cache
2784 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2785 // aren't identified as part of the client, which would waste
2786 // > 20M of virtual address space.]
2787 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002788 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002789 VG_(init_tt_tc)();
2790
2791 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002792 // Read debug info to find glibc entry points to intercept
2793 // p: parse_procselfmaps? [XXX for debug info?]
2794 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2795 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002796 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002797 VG_(setup_code_redirect_table)();
2798
2799 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002800 // Verbosity message
2801 // p: end_rdtsc_calibration [so startup message is printed first]
2802 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002803 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002804 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2805 if (VG_(clo_verbosity) > 0)
2806 VG_(message)(Vg_UserMsg, "");
2807
2808 //--------------------------------------------------------------
2809 // Setup pointercheck
2810 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2811 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002812 if (VG_(clo_pointercheck))
2813 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002814
nethercote71980f02004-01-24 18:18:54 +00002815 //--------------------------------------------------------------
2816 // Run!
2817 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002818 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002819
sewardjb5f6f512005-03-10 23:59:00 +00002820 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002821
sewardj71bc3cb2005-05-19 00:25:45 +00002822 if (VG_(clo_xml)) {
2823 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2824 VG_(message)(Vg_UserMsg, "");
2825 }
2826
sewardj1fbc1a52005-04-25 02:05:54 +00002827 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002828 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002829
sewardjb5f6f512005-03-10 23:59:00 +00002830 abort();
2831}
2832
2833
2834/* Do everything which needs doing when the last thread exits */
2835void VG_(shutdown_actions)(ThreadId tid)
2836{
2837 vg_assert(tid == VG_(master_tid));
2838 vg_assert(VG_(is_running_thread)(tid));
2839
2840 // Wait for all other threads to exit.
2841 VGA_(reap_threads)(tid);
2842
2843 VG_(clo_model_pthreads) = False;
2844
2845 // Clean the client up before the final report
2846 VGA_(final_tidyup)(tid);
2847
2848 // OK, done
2849 VG_(exit_thread)(tid);
2850
2851 /* should be no threads left */
2852 vg_assert(VG_(count_living_threads)() == 0);
2853
2854 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002855 //--------------------------------------------------------------
2856 // Finalisation: cleanup, messages, etc. Order no so important, only
2857 // affects what order the messages come.
2858 //--------------------------------------------------------------
2859 if (VG_(clo_verbosity) > 0)
2860 VG_(message)(Vg_UserMsg, "");
2861
sewardj71bc3cb2005-05-19 00:25:45 +00002862 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002863 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2864 VG_(show_error_counts_as_XML)();
2865 VG_(message)(Vg_UserMsg, "");
2866 }
sewardj71bc3cb2005-05-19 00:25:45 +00002867 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2868 VG_(message)(Vg_UserMsg, "");
2869 }
2870
nethercote71980f02004-01-24 18:18:54 +00002871 /* Print out file descriptor summary and stats. */
2872 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002873 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002874
njn95ec8702004-11-22 16:46:13 +00002875 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002876 VG_(show_all_errors)();
2877
njn51d827b2005-05-09 01:02:08 +00002878 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002879
sewardj71bc3cb2005-05-19 00:25:45 +00002880 if (VG_(clo_xml)) {
2881 VG_(message)(Vg_UserMsg, "");
2882 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2883 VG_(message)(Vg_UserMsg, "");
2884 }
2885
nethercote885dd912004-08-03 23:14:00 +00002886 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002887
2888 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002889 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002890
nethercote71980f02004-01-24 18:18:54 +00002891 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002892 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002893 if (VG_(clo_profile_flags) > 0)
2894 VG_(show_BB_profile)();
2895
sewardj8b635a42004-11-22 19:01:47 +00002896 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002897 if (0)
2898 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002899}
sewardj8b635a42004-11-22 19:01:47 +00002900
sewardjde4a1d02002-03-22 01:27:54 +00002901/*--------------------------------------------------------------------*/
2902/*--- end vg_main.c ---*/
2903/*--------------------------------------------------------------------*/