blob: 5910e36fce1685c779c603b2dd806a0ba0fad63a [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"
njn2521d322005-05-08 14:45:13 +000040#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000042#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000043
44#include <dirent.h>
45#include <dlfcn.h>
46#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000047#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000049#include <string.h>
50#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000051#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000052#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <sys/wait.h>
54#include <unistd.h>
55
sewardjb5f6f512005-03-10 23:59:00 +000056#include "memcheck/memcheck.h"
57
thughes74b8de22004-04-22 18:12:31 +000058#ifndef AT_DCACHEBSIZE
59#define AT_DCACHEBSIZE 19
60#endif /* AT_DCACHEBSIZE */
61
62#ifndef AT_ICACHEBSIZE
63#define AT_ICACHEBSIZE 20
64#endif /* AT_ICACHEBSIZE */
65
66#ifndef AT_UCACHEBSIZE
67#define AT_UCACHEBSIZE 21
68#endif /* AT_UCACHEBSIZE */
69
nethercote71980f02004-01-24 18:18:54 +000070#ifndef AT_SYSINFO
71#define AT_SYSINFO 32
72#endif /* AT_SYSINFO */
73
74#ifndef AT_SYSINFO_EHDR
75#define AT_SYSINFO_EHDR 33
76#endif /* AT_SYSINFO_EHDR */
77
78#ifndef AT_SECURE
79#define AT_SECURE 23 /* secure mode boolean */
80#endif /* AT_SECURE */
81
nethercote71980f02004-01-24 18:18:54 +000082/* redzone gap between client address space and shadow */
83#define REDZONE_SIZE (1 * 1024*1024)
84
85/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000086#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000087
nethercotee2097312004-06-27 12:29:56 +000088/* Proportion of client space for its heap (rest is for mmaps + stack) */
89#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000090
njn14319cc2005-03-13 06:26:22 +000091/* Number of file descriptors that Valgrind tries to reserve for
92 it's own use - just a small constant. */
93#define N_RESERVED_FDS (10)
94
nethercote71980f02004-01-24 18:18:54 +000095/*====================================================================*/
96/*=== Global entities not referenced from generated code ===*/
97/*====================================================================*/
98
sewardjde4a1d02002-03-22 01:27:54 +000099/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000100 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000101 ------------------------------------------------------------------ */
102
nethercote71980f02004-01-24 18:18:54 +0000103/* Client address space, lowest to highest (see top of ume.c) */
104Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000105Addr VG_(client_end);
106Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000107Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(clstk_base);
109Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000110
111Addr VG_(brk_base); /* start of brk */
112Addr VG_(brk_limit); /* current brk */
113
nethercote996901a2004-08-03 13:29:09 +0000114Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000115Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000116
117Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000118
nethercote820bd8c2004-09-07 23:04:49 +0000119// Note that VG_(valgrind_last) names the last byte of the section, whereas
120// the VG_(*_end) vars name the byte one past the end of the section.
121Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000122
nethercote73b526f2004-10-31 18:48:21 +0000123struct vki_rlimit VG_(client_rlimit_data);
124struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000125
fitzhardinge98abfc72003-12-16 02:05:15 +0000126/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000127static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000128
129/* client executable */
130Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000131
132/* Path to library directory */
133const Char *VG_(libdir) = VG_LIBDIR;
134
135/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000136static Int vg_argc;
137static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000138
sewardjb5f6f512005-03-10 23:59:00 +0000139/* The master thread the one which will be responsible for mopping
140 everything up at exit. Normally it is tid 1, since that's the
141 first thread created, but it may be something else after a
142 fork(). */
143ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000144
thughesad1c9562004-06-26 11:27:52 +0000145/* Application-visible file descriptor limits */
146Int VG_(fd_soft_limit) = -1;
147Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000148
nethercote4ad74312004-10-26 09:59:49 +0000149/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000150 envp[] as extracted from the client's stack at startup-time. */
151Int VG_(client_argc);
152Char** VG_(client_argv);
153Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000154
sewardj51ac0872004-12-21 01:20:49 +0000155
sewardjde4a1d02002-03-22 01:27:54 +0000156/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000157 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000158 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000159
sewardjde4a1d02002-03-22 01:27:54 +0000160/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000161ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* Tell the logging mechanism whether we are logging to a file
164 descriptor or a socket descriptor. */
njnbe9b47b2005-05-15 16:22:58 +0000165Bool VG_(logging_to_socket) = False;
nethercote71980f02004-01-24 18:18:54 +0000166
sewardj73cf3bc2002-11-03 03:20:15 +0000167
nethercote71980f02004-01-24 18:18:54 +0000168/*====================================================================*/
169/*=== Counters, for profiling purposes only ===*/
170/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000171
sewardjde4a1d02002-03-22 01:27:54 +0000172/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000173static UInt sanity_fast_count = 0;
174static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000175
nethercote3a42fb82004-08-03 18:08:50 +0000176static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000177{
nethercote3a42fb82004-08-03 18:08:50 +0000178 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000179 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000180 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000181 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000182
nethercote3a42fb82004-08-03 18:08:50 +0000183 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000184 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000185
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(message)(Vg_DebugMsg,
187 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000188 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000189
njn9271cbc2005-03-13 05:38:25 +0000190 VG_(print_ExeContext_stats)();
191
nethercote3a42fb82004-08-03 18:08:50 +0000192 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000193 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000194 VG_(message)(Vg_DebugMsg, "");
195 VG_(message)(Vg_DebugMsg,
196 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000197 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000198 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000199 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000200 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000201 }
nethercote71980f02004-01-24 18:18:54 +0000202}
203
204
205/*====================================================================*/
206/*=== Miscellaneous global functions ===*/
207/*====================================================================*/
208
nethercotecf97ffb2004-09-09 13:40:31 +0000209static Int ptrace_setregs(Int pid, ThreadId tid)
210{
sewardj2a99cf62004-11-24 10:44:19 +0000211 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000212}
213
nethercote04d0fbc2004-01-26 16:48:06 +0000214/* Start debugger and get it to attach to this process. Called if the
215 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000216 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000217 meaningfully get the debugger to continue the program, though; to
218 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000219void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000220{
221 Int pid;
222
223 if ((pid = fork()) == 0) {
224 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000225 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000226
227 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000228 Int status;
229 Int res;
230
nethercote71980f02004-01-24 18:18:54 +0000231 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
232 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000233 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000234 kill(pid, SIGSTOP) == 0 &&
235 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000236 Char pidbuf[15];
237 Char file[30];
238 Char buf[100];
239 Char *bufptr;
240 Char *cmdptr;
241
242 VG_(sprintf)(pidbuf, "%d", pid);
243 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
244
245 bufptr = buf;
246 cmdptr = VG_(clo_db_command);
247
248 while (*cmdptr) {
249 switch (*cmdptr) {
250 case '%':
251 switch (*++cmdptr) {
252 case 'f':
253 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
254 bufptr += VG_(strlen)(file);
255 cmdptr++;
256 break;
257 case 'p':
258 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
259 bufptr += VG_(strlen)(pidbuf);
260 cmdptr++;
261 break;
262 default:
263 *bufptr++ = *cmdptr++;
264 break;
265 }
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 }
272
273 *bufptr++ = '\0';
274
275 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000276 res = VG_(system)(buf);
277 if (res == 0) {
278 VG_(message)(Vg_UserMsg, "");
279 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000280 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000281 } else {
282 VG_(message)(Vg_UserMsg, "Apparently failed!");
283 VG_(message)(Vg_UserMsg, "");
284 }
285 }
286
nethercote73b526f2004-10-31 18:48:21 +0000287 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000288 VG_(waitpid)(pid, &status, 0);
289 }
290}
291
292
293/* Print some helpful-ish text about unimplemented things, and give
294 up. */
295void VG_(unimplemented) ( Char* msg )
296{
297 VG_(message)(Vg_UserMsg, "");
298 VG_(message)(Vg_UserMsg,
299 "Valgrind detected that your program requires");
300 VG_(message)(Vg_UserMsg,
301 "the following unimplemented functionality:");
302 VG_(message)(Vg_UserMsg, " %s", msg);
303 VG_(message)(Vg_UserMsg,
304 "This may be because the functionality is hard to implement,");
305 VG_(message)(Vg_UserMsg,
306 "or because no reasonable program would behave this way,");
307 VG_(message)(Vg_UserMsg,
308 "or because nobody has yet needed it. In any case, let us know at");
309 VG_(message)(Vg_UserMsg,
310 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
311 VG_(message)(Vg_UserMsg,
312 "");
313 VG_(message)(Vg_UserMsg,
314 "Valgrind has to exit now. Sorry. Bye!");
315 VG_(message)(Vg_UserMsg,
316 "");
317 VG_(pp_sched_status)();
318 VG_(exit)(1);
319}
320
sewardj2a99cf62004-11-24 10:44:19 +0000321/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000322Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000323{
njncf45fd42004-11-24 16:30:22 +0000324 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000325}
326
njn67516132005-03-22 04:02:43 +0000327Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000328{
329 return INSTR_PTR( VG_(threads)[tid].arch );
330}
331
njnea4b28c2004-11-30 16:04:58 +0000332
nethercote71980f02004-01-24 18:18:54 +0000333/*====================================================================*/
334/*=== Check we were launched by stage 1 ===*/
335/*====================================================================*/
336
337/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000338static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000339{
nethercoteebf1d862004-11-01 18:22:05 +0000340 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000341 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000342
343 for (; auxv->a_type != AT_NULL; auxv++)
344 switch(auxv->a_type) {
345 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000346 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000347 found |= 1;
348 break;
349
350 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000351 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 2;
353 break;
nethercote7f390022004-10-25 17:18:24 +0000354
355 case AT_PHDR:
356 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
357 break;
nethercote71980f02004-01-24 18:18:54 +0000358 }
359
nethercote361a14e2004-07-26 11:11:56 +0000360 if ( found != (1|2) ) {
361 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000362 exit(127);
363 }
nethercote31779c72004-07-30 21:50:15 +0000364 vg_assert(padfile >= 0);
365 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000366}
367
368
369/*====================================================================*/
370/*=== Address space determination ===*/
371/*====================================================================*/
372
nethercote7f390022004-10-25 17:18:24 +0000373extern char _start[];
374
nethercote31779c72004-07-30 21:50:15 +0000375static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000376{
nethercotea3c3cf22004-11-01 18:38:00 +0000377 Int ires;
378 void* vres;
379 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000380
nethercote7f390022004-10-25 17:18:24 +0000381 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
382 // this is a workable approximation
383 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000384 VG_(valgrind_base) = PGROUNDDN(&_start);
385 }
386
nethercote820bd8c2004-09-07 23:04:49 +0000387 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000388
nethercote31779c72004-07-30 21:50:15 +0000389 // This gives the client the largest possible address space while
390 // taking into account the tool's shadow needs.
391 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000392 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000393 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000394 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000395 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000396 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000397 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000398
nethercote31779c72004-07-30 21:50:15 +0000399 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000400 VG_(shadow_end) = VG_(valgrind_base);
401 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000402
nethercotee2097312004-06-27 12:29:56 +0000403#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
404
nethercote71980f02004-01-24 18:18:54 +0000405 if (0)
nethercotee2097312004-06-27 12:29:56 +0000406 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000407 "client_base %p (%dMB)\n"
408 "client_mapbase %p (%dMB)\n"
409 "client_end %p (%dMB)\n"
410 "shadow_base %p (%dMB)\n"
411 "shadow_end %p\n"
412 "valgrind_base %p (%dMB)\n"
413 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000414 VG_(client_base), SEGSIZE(client_base, client_mapbase),
415 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
416 VG_(client_end), SEGSIZE(client_end, shadow_base),
417 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000418 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000419 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
420 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000421 );
422
423#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000424
425 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000426 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000427 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000428 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000431 ires = munmap((void*)VG_(client_base), client_size);
432 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000433
434 // Map shadow memory.
435 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000436 if (shadow_size != 0) {
437 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000438 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000439 if ((void*)-1 == vres) {
440 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000441 "valgrind: Could not allocate address space (%p bytes)\n"
442 "valgrind: for shadow memory\n"
443 "valgrind: Possible causes:\n"
444 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
445 "valgrind: needs at least 1.5GB swap space.\n"
446 "valgrind: - Or, your virtual memory size may be limited (check\n"
447 "valgrind: with 'ulimit -v').\n"
448 "valgrind: - Or, your system may use a kernel that provides only a\n"
449 "valgrind: too-small (eg. 2GB) user address space.\n"
450 , (void*)shadow_size
451 );
nethercoted4722622004-08-30 19:36:42 +0000452 exit(1);
453 }
nethercotee567e702004-07-10 17:49:17 +0000454 }
nethercote71980f02004-01-24 18:18:54 +0000455}
456
457/*====================================================================*/
458/*=== Command line setup ===*/
459/*====================================================================*/
460
461/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
462static 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);
566
567 /* copy original arguments, stopping at command or -- */
568 while (*from) {
569 if (**from != '-')
570 break;
571 if (VG_STREQ(*from, "--")) {
572 from++; /* skip -- */
573 break;
574 }
575 *to++ = *from++;
576 }
577
578 /* add -- */
579 *to++ = "--";
580
nethercotef6a1d502004-08-09 12:21:57 +0000581 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000582
583 /* copy rest of original command line, then NULL */
584 while (*from) *to++ = *from++;
585 *to = NULL;
586 }
587
nethercotef6a1d502004-08-09 12:21:57 +0000588 *vg_argc_inout = vg_argc0;
589 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000590}
591
nethercotef6a1d502004-08-09 12:21:57 +0000592#define VG_CLO_SEP '\01'
593
nethercote71980f02004-01-24 18:18:54 +0000594static void get_command_line( int argc, char** argv,
595 Int* vg_argc_out, Char*** vg_argv_out,
596 char*** cl_argv_out )
597{
nethercotef6a1d502004-08-09 12:21:57 +0000598 int vg_argc0;
599 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000600 char** cl_argv;
601 char* env_clo = getenv(VALGRINDCLO);
602
603 if (env_clo != NULL && *env_clo != '\0') {
604 char *cp;
605 char **cpp;
606
nethercotef6a1d502004-08-09 12:21:57 +0000607 /* OK, VALGRINDCLO is set, which means we must be a child of another
608 Valgrind process using --trace-children, so we're getting all our
609 arguments from VALGRINDCLO, and the entire command line belongs to
610 the client (including argv[0]) */
611 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000612 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000613 if (*cp == VG_CLO_SEP)
614 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000615
nethercotef6a1d502004-08-09 12:21:57 +0000616 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
617 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000618
nethercotef6a1d502004-08-09 12:21:57 +0000619 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000620
621 *cpp++ = "valgrind"; /* nominal argv[0] */
622 *cpp++ = env_clo;
623
nethercotef6a1d502004-08-09 12:21:57 +0000624 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000625 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000626 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000627 *cp++ = '\0'; /* chop it up in place */
628 *cpp++ = cp;
629 }
630 }
631 *cpp = NULL;
632 cl_argv = argv;
633
634 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000635 Bool noaugment = False;
636
nethercote71980f02004-01-24 18:18:54 +0000637 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000638 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000639
nethercotef6a1d502004-08-09 12:21:57 +0000640 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000641 Char* arg = argv[vg_argc0];
642 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000643 break;
sewardjb5f6f512005-03-10 23:59:00 +0000644 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000645 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000646 break;
647 }
njn45270a22005-03-27 01:00:11 +0000648 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000649 }
nethercotef6a1d502004-08-09 12:21:57 +0000650 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000651
652 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000653 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000654 those extra args will already be present in VALGRINDCLO.
655 (We also don't do it when --command-line-only=yes.) */
656 if (!noaugment)
657 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000658 }
659
660 if (0) {
661 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000662 for (i = 0; i < vg_argc0; i++)
663 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000664 }
665
nethercotef6a1d502004-08-09 12:21:57 +0000666 *vg_argc_out = vg_argc0;
667 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000668 *cl_argv_out = cl_argv;
669}
670
671
672/*====================================================================*/
673/*=== Environment and stack setup ===*/
674/*====================================================================*/
675
676/* Scan a colon-separated list, and call a function on each element.
677 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000678 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000679 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000680
681 This routine will return True if (*func) returns True and False if
682 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000683*/
thughes4ad52d02004-06-27 17:37:21 +0000684static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000685{
686 char *cp, *entry;
687 int end;
688
689 if (colsep == NULL ||
690 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000691 return False;
nethercote71980f02004-01-24 18:18:54 +0000692
693 entry = cp = colsep;
694
695 do {
696 end = (*cp == '\0');
697
698 if (*cp == ':' || *cp == '\0') {
699 char save = *cp;
700
701 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000702 if ((*func)(entry)) {
703 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000704 return True;
thughes21942d92004-07-12 09:35:37 +0000705 }
nethercote71980f02004-01-24 18:18:54 +0000706 *cp = save;
707 entry = cp+1;
708 }
709 cp++;
710 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000711
712 return False;
713}
714
nethercote71980f02004-01-24 18:18:54 +0000715/* Prepare the client's environment. This is basically a copy of our
716 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000717 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000718
sewardjb5f6f512005-03-10 23:59:00 +0000719 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000720
721 Yummy. String hacking in C.
722
723 If this needs to handle any more variables it should be hacked
724 into something table driven.
725 */
726static char **fix_environment(char **origenv, const char *preload)
727{
728 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000729 static const char ld_preload[] = "LD_PRELOAD=";
730 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000731 static const int ld_preload_len = sizeof(ld_preload)-1;
732 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
733 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000734 char *inject_path;
735 int inject_path_len;
736 int vgliblen = strlen(VG_(libdir));
737 char **cpp;
738 char **ret;
739 int envc;
740 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
741
742 /* Find the vg_inject.so; also make room for the tool preload
743 library */
744 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
745 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000746 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000747
748 if (preload)
749 snprintf(inject_path, inject_path_len, "%s/%s:%s",
750 VG_(libdir), inject_so, preload);
751 else
752 snprintf(inject_path, inject_path_len, "%s/%s",
753 VG_(libdir), inject_so);
754
755 /* Count the original size of the env */
756 envc = 0; /* trailing NULL */
757 for (cpp = origenv; cpp && *cpp; cpp++)
758 envc++;
759
760 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000761 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000762 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000763
764 /* copy it over */
765 for (cpp = ret; *origenv; )
766 *cpp++ = *origenv++;
767 *cpp = NULL;
768
769 vg_assert(envc == (cpp - ret));
770
771 /* Walk over the new environment, mashing as we go */
772 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000773 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000774 int len = strlen(*cpp) + inject_path_len;
775 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000776 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000777
778 snprintf(cp, len, "%s%s:%s",
779 ld_preload, inject_path, (*cpp)+ld_preload_len);
780
781 *cpp = cp;
782
783 ld_preload_done = 1;
784 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
785 *cpp = "";
786 }
787 }
788
789 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000790 if (!ld_preload_done) {
791 int len = ld_preload_len + inject_path_len;
792 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000793 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000794
795 snprintf(cp, len, "%s%s",
796 ld_preload, inject_path);
797
798 ret[envc++] = cp;
799 }
800
sewardjb5f6f512005-03-10 23:59:00 +0000801 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000802 ret[envc] = NULL;
803
804 return ret;
805}
806
807extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000808
809/* Add a string onto the string table, and return its address */
810static char *copy_str(char **tab, const char *str)
811{
812 char *cp = *tab;
813 char *orig = cp;
814
815 while(*str)
816 *cp++ = *str++;
817 *cp++ = '\0';
818
819 if (0)
nethercote545fe672004-11-01 16:52:43 +0000820 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000821
822 *tab = cp;
823
824 return orig;
825}
826
827/*
828 This sets up the client's initial stack, containing the args,
829 environment and aux vector.
830
831 The format of the stack is:
832
833 higher address +-----------------+
834 | Trampoline code |
835 +-----------------+
836 | |
837 : string table :
838 | |
839 +-----------------+
840 | AT_NULL |
841 - -
842 | auxv |
843 +-----------------+
844 | NULL |
845 - -
846 | envp |
847 +-----------------+
848 | NULL |
849 - -
850 | argv |
851 +-----------------+
852 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000853 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000854 | undefined |
855 : :
856 */
nethercotec25c4492004-10-18 11:52:17 +0000857static Addr setup_client_stack(void* init_sp,
858 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000859 const struct exeinfo *info,
860 UInt** client_auxv)
861{
nethercotee567e702004-07-10 17:49:17 +0000862 void* res;
nethercote71980f02004-01-24 18:18:54 +0000863 char **cpp;
864 char *strtab; /* string table */
865 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000866 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000867 struct ume_auxv *auxv;
868 const struct ume_auxv *orig_auxv;
869 const struct ume_auxv *cauxv;
870 unsigned stringsize; /* total size of strings in bytes */
871 unsigned auxsize; /* total size of auxv in bytes */
872 int argc; /* total argc */
873 int envc; /* total number of env vars */
874 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000875 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000876
877 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000878 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000879
880 /* ==================== compute sizes ==================== */
881
882 /* first of all, work out how big the client stack will be */
883 stringsize = 0;
884
885 /* paste on the extra args if the loader needs them (ie, the #!
886 interpreter and its argument) */
887 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000888 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000889 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000890 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000891 }
nethercoted6a56872004-07-26 15:32:47 +0000892 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000893 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000894 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000895 }
896
897 /* now scan the args we're given... */
898 for (cpp = orig_argv; *cpp; cpp++) {
899 argc++;
900 stringsize += strlen(*cpp) + 1;
901 }
902
903 /* ...and the environment */
904 envc = 0;
905 for (cpp = orig_envp; cpp && *cpp; cpp++) {
906 envc++;
907 stringsize += strlen(*cpp) + 1;
908 }
909
910 /* now, how big is the auxv? */
911 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
912 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
913 if (cauxv->a_type == AT_PLATFORM)
914 stringsize += strlen(cauxv->u.a_ptr) + 1;
915 auxsize += sizeof(*cauxv);
916 }
917
918 /* OK, now we know how big the client stack is */
919 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000920 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000921 sizeof(char **)*argc + /* argv */
922 sizeof(char **) + /* terminal NULL */
923 sizeof(char **)*envc + /* envp */
924 sizeof(char **) + /* terminal NULL */
925 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000926 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000927 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000928
sewardj79048ce2005-02-18 08:28:32 +0000929 if (0) VG_(printf)("stacksize = %d\n", stacksize);
930
nethercotef84f6952004-07-15 14:58:33 +0000931 // decide where stack goes!
932 VG_(clstk_end) = VG_(client_end);
933
nethercote73b526f2004-10-31 18:48:21 +0000934 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000935
nethercote71980f02004-01-24 18:18:54 +0000936 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000937 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000938 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
939
nethercote71980f02004-01-24 18:18:54 +0000940 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000941 stringbase = strtab = (char *)(VG_(client_trampoline_code)
942 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000943
944 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000945
sewardj79048ce2005-02-18 08:28:32 +0000946 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000947 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000948 "clstk_base %p\n"
949 "clstk_end %p\n",
950 stringsize, auxsize, stacksize,
951 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000952
nethercote71980f02004-01-24 18:18:54 +0000953 /* ==================== allocate space ==================== */
954
955 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000956 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000957 PROT_READ | PROT_WRITE | PROT_EXEC,
958 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
959 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000960
961 /* ==================== copy client stack ==================== */
962
nethercotea3c3cf22004-11-01 18:38:00 +0000963 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000964
965 /* --- argc --- */
966 *ptr++ = argc; /* client argc */
967
968 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000969 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000970 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000971 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000972 }
nethercoted6a56872004-07-26 15:32:47 +0000973 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000974 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000975 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000976 }
977 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000978 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000979 }
980 *ptr++ = 0;
981
982 /* --- envp --- */
983 VG_(client_envp) = (Char **)ptr;
984 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000985 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000986 *ptr++ = 0;
987
988 /* --- auxv --- */
989 auxv = (struct ume_auxv *)ptr;
990 *client_auxv = (UInt *)auxv;
991
992 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
993 /* copy the entry... */
994 *auxv = *orig_auxv;
995
996 /* ...and fix up the copy */
997 switch(auxv->a_type) {
998 case AT_PHDR:
999 if (info->phdr == 0)
1000 auxv->a_type = AT_IGNORE;
1001 else
1002 auxv->u.a_val = info->phdr;
1003 break;
1004
1005 case AT_PHNUM:
1006 if (info->phdr == 0)
1007 auxv->a_type = AT_IGNORE;
1008 else
1009 auxv->u.a_val = info->phnum;
1010 break;
1011
1012 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001013 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001014 break;
1015
1016 case AT_PLATFORM: /* points to a platform description string */
1017 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1018 break;
1019
1020 case AT_ENTRY:
1021 auxv->u.a_val = info->entry;
1022 break;
1023
1024 case AT_IGNORE:
1025 case AT_EXECFD:
1026 case AT_PHENT:
1027 case AT_PAGESZ:
1028 case AT_FLAGS:
1029 case AT_NOTELF:
1030 case AT_UID:
1031 case AT_EUID:
1032 case AT_GID:
1033 case AT_EGID:
1034 case AT_CLKTCK:
1035 case AT_HWCAP:
1036 case AT_FPUCW:
1037 case AT_DCACHEBSIZE:
1038 case AT_ICACHEBSIZE:
1039 case AT_UCACHEBSIZE:
1040 /* All these are pointerless, so we don't need to do anything
1041 about them. */
1042 break;
1043
1044 case AT_SECURE:
1045 /* If this is 1, then it means that this program is running
1046 suid, and therefore the dynamic linker should be careful
1047 about LD_PRELOAD, etc. However, since stage1 (the thing
1048 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001049 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001050 set AT_SECURE to 0. */
1051 auxv->u.a_val = 0;
1052 break;
1053
1054 case AT_SYSINFO:
1055 /* Leave this unmolested for now, but we'll update it later
1056 when we set up the client trampoline code page */
1057 break;
1058
1059 case AT_SYSINFO_EHDR:
1060 /* Trash this, because we don't reproduce it */
1061 auxv->a_type = AT_IGNORE;
1062 break;
1063
1064 default:
1065 /* stomp out anything we don't know about */
1066 if (0)
nethercote545fe672004-11-01 16:52:43 +00001067 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001068 auxv->a_type = AT_IGNORE;
1069 break;
1070
1071 }
1072 }
1073 *auxv = *orig_auxv;
1074 vg_assert(auxv->a_type == AT_NULL);
1075
njnc6168192004-11-29 13:54:10 +00001076// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1077// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001078#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001079 /* --- trampoline page --- */
1080 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1081 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001082#endif
nethercotef84f6952004-07-15 14:58:33 +00001083
nethercote71980f02004-01-24 18:18:54 +00001084 vg_assert((strtab-stringbase) == stringsize);
1085
nethercote5ee67ca2004-06-22 14:00:09 +00001086 /* We know the initial ESP is pointing at argc/argv */
1087 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001088 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001089
sewardj79048ce2005-02-18 08:28:32 +00001090 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001091 return cl_esp;
1092}
1093
1094/*====================================================================*/
1095/*=== Find executable ===*/
1096/*====================================================================*/
1097
thughes4ad52d02004-06-27 17:37:21 +00001098static const char* executable_name;
1099
1100static Bool match_executable(const char *entry) {
1101 char buf[strlen(entry) + strlen(executable_name) + 2];
1102
1103 /* empty PATH element means . */
1104 if (*entry == '\0')
1105 entry = ".";
1106
1107 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1108
1109 if (access(buf, R_OK|X_OK) == 0) {
1110 executable_name = strdup(buf);
1111 vg_assert(NULL != executable_name);
1112 return True;
1113 }
1114 return False;
1115}
1116
nethercote71980f02004-01-24 18:18:54 +00001117static const char* find_executable(const char* exec)
1118{
1119 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001120 executable_name = exec;
1121 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001122 /* no '/' - we need to search the path */
1123 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001124 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001125 }
thughes4ad52d02004-06-27 17:37:21 +00001126 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001127}
1128
1129
1130/*====================================================================*/
1131/*=== Loading tools ===*/
1132/*====================================================================*/
1133
1134static void list_tools(void)
1135{
1136 DIR *dir = opendir(VG_(libdir));
1137 struct dirent *de;
1138 int first = 1;
1139
1140 if (dir == NULL) {
1141 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001142 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001143 return;
1144 }
1145
nethercotef4928da2004-06-15 10:54:40 +00001146 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001147 int len = strlen(de->d_name);
1148
njn063c5402004-11-22 16:58:05 +00001149 /* look for vgtool_TOOL.so names */
1150 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1151 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001152 VG_STREQ(de->d_name + len - 3, ".so")) {
1153 if (first) {
1154 fprintf(stderr, "Available tools:\n");
1155 first = 0;
1156 }
1157 de->d_name[len-3] = '\0';
1158 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001159 }
1160 }
1161
1162 closedir(dir);
1163
1164 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001165 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1166 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001167}
1168
1169
1170/* Find and load a tool, and check it looks ok. Also looks to see if there's
1171 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001172static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001173 ToolInfo** toolinfo_out, char **preloadpath_out )
1174{
1175 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001176 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001177 char buf[len];
1178 void* handle;
1179 ToolInfo* toolinfo;
1180 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001181
1182 // XXX: allowing full paths for --tool option -- does it make sense?
1183 // Doesn't allow for vgpreload_<tool>.so.
1184
1185 if (strchr(toolname, '/') != 0) {
1186 /* toolname contains '/', and so must be a pathname */
1187 handle = dlopen(toolname, RTLD_NOW);
1188 } else {
1189 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001190 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001191 handle = dlopen(buf, RTLD_NOW);
1192
1193 if (handle != NULL) {
1194 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1195 if (access(buf, R_OK) == 0) {
1196 preloadpath = strdup(buf);
1197 vg_assert(NULL != preloadpath);
1198 }
1199 }
1200 }
1201
1202 ok = (NULL != handle);
1203 if (!ok) {
1204 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1205 goto bad_load;
1206 }
1207
njn51d827b2005-05-09 01:02:08 +00001208 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001209 ok = (NULL != toolinfo);
1210 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001211 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001212 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1213 goto bad_load;
1214 }
1215
1216 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001217 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1218 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001219 if (!ok) {
1220 fprintf(stderr, "Error:\n"
1221 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001222 " Interface version used by core is: %d (size %d)\n"
1223 " Interface version used by tool is: %d (size %d)\n"
1224 " The version numbers must match.\n",
1225 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001226 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001227 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001228 toolinfo->sizeof_ToolInfo);
1229 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001230 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001231 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001232 else
nethercote996901a2004-08-03 13:29:09 +00001233 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001234 goto bad_load;
1235 }
1236
njn8a97c6d2005-03-31 04:37:24 +00001237 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001238 *toolinfo_out = toolinfo;
1239 *preloadpath_out = preloadpath;
1240 return;
1241
1242
1243 bad_load:
1244 if (handle != NULL)
1245 dlclose(handle);
1246
nethercotef4928da2004-06-15 10:54:40 +00001247 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001248 list_tools();
1249 exit(127);
1250}
1251
nethercotef4928da2004-06-15 10:54:40 +00001252
1253/*====================================================================*/
1254/*=== Command line errors ===*/
1255/*====================================================================*/
1256
njnbe9b47b2005-05-15 16:22:58 +00001257static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001258{
njnbe9b47b2005-05-15 16:22:58 +00001259 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001260 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001261}
1262
1263void VG_(bad_option) ( Char* opt )
1264{
njnbe9b47b2005-05-15 16:22:58 +00001265 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001266 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001267 VG_(printf)("valgrind: Use --help for more information.\n");
1268 VG_(exit)(1);
1269}
1270
nethercotef4928da2004-06-15 10:54:40 +00001271static void missing_prog ( void )
1272{
njnbe9b47b2005-05-15 16:22:58 +00001273 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001274 VG_(printf)("valgrind: no program specified\n");
1275 VG_(printf)("valgrind: Use --help for more information.\n");
1276 VG_(exit)(1);
1277}
1278
1279static void config_error ( Char* msg )
1280{
njnbe9b47b2005-05-15 16:22:58 +00001281 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001282 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1283 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1284 VG_(exit)(1);
1285}
1286
1287
nethercote71980f02004-01-24 18:18:54 +00001288/*====================================================================*/
1289/*=== Loading the client ===*/
1290/*====================================================================*/
1291
nethercotef4928da2004-06-15 10:54:40 +00001292static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001293 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1294{
1295 // If they didn't specify an executable with --exec, and didn't specify
1296 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001297 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001298 if (cl_argv[0] == NULL ||
1299 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1300 {
nethercotef4928da2004-06-15 10:54:40 +00001301 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001302 }
1303 }
1304
1305 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001306 info->exe_base = VG_(client_base);
1307 info->exe_end = VG_(client_end);
1308 info->argv = cl_argv;
1309
nethercotef4928da2004-06-15 10:54:40 +00001310 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001311 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001312 // Totally zero 'info' before continuing.
1313 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001314 } else {
1315 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001316 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001317 ret = do_exec(exec, info);
1318 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001319 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1320 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001321 exit(127);
1322 }
1323 }
1324
1325 /* Copy necessary bits of 'info' that were filled in */
1326 *client_eip = info->init_eip;
1327 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1328}
1329
nethercote969ecf12004-10-13 17:29:01 +00001330/*====================================================================*/
1331/*=== Address space unpadding ===*/
1332/*====================================================================*/
1333
1334typedef struct {
1335 char* killpad_start;
1336 char* killpad_end;
1337 struct stat* killpad_padstat;
1338} killpad_extra;
1339
1340static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1341 int maj, int min, int ino, void* ex)
1342{
1343 killpad_extra* extra = ex;
1344 void *b, *e;
1345 int res;
1346
1347 vg_assert(NULL != extra->killpad_padstat);
1348
1349 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1350 extra->killpad_padstat->st_ino != ino)
1351 return 1;
1352
1353 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1354 return 1;
1355
1356 if (segstart <= extra->killpad_start)
1357 b = extra->killpad_start;
1358 else
1359 b = segstart;
1360
1361 if (segend >= extra->killpad_end)
1362 e = extra->killpad_end;
1363 else
1364 e = segend;
1365
1366 res = munmap(b, (char *)e-(char *)b);
1367 vg_assert(0 == res);
1368
1369 return 1;
1370}
1371
1372// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001373static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001374{
1375 static struct stat padstat;
1376 killpad_extra extra;
1377 int res;
1378
sewardjb5f6f512005-03-10 23:59:00 +00001379 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001380
1381 res = fstat(padfile, &padstat);
1382 vg_assert(0 == res);
1383 extra.killpad_padstat = &padstat;
1384 extra.killpad_start = start;
1385 extra.killpad_end = end;
1386 foreach_map(killpad, &extra);
1387}
1388
sewardj2c5ffbe2005-03-12 13:32:06 +00001389static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001390{
1391 int res = close(padfile);
1392 vg_assert(0 == res);
1393}
1394
sewardj71bc3cb2005-05-19 00:25:45 +00001395/*====================================================================*/
1396/*=== Command-line: variables, processing, etc ===*/
1397/*====================================================================*/
1398
1399// See pub_{core,tool}_options.h for explanations of all these.
1400
sewardj2c5ffbe2005-03-12 13:32:06 +00001401static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001402{
njn25e49d8e72002-09-23 09:36:25 +00001403 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001404"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001405"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001406" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001407" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001408" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001409" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001410" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001411" -q --quiet run silently; only print error msgs\n"
1412" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001413" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001414" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001415" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001416" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001417"\n"
1418" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001419" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001420" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001421" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001422" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001423" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001424"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001425" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001426" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1427" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001428" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001429" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001430" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001431" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001432" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1433" --show-below-main=no|yes continue stack traces below main() [no]\n"
1434" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001435" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001436" --db-attach=no|yes start debugger when errors detected? [no]\n"
1437" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1438" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001439" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1440" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001441"\n";
njn7cf0bd32002-06-08 13:36:03 +00001442
njn25e49d8e72002-09-23 09:36:25 +00001443 Char* usage2 =
1444"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001445" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001446" --sanity-level=<number> level of sanity checking to do [1]\n"
1447" --single-step=no|yes translate each instr separately? [no]\n"
1448" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001449" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001450" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001451" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1452" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001453" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001454" --trace-syscalls=no|yes show all system calls? [no]\n"
1455" --trace-signals=no|yes show signal handling details? [no]\n"
1456" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001457" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001458" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001459" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001460#if 0
1461" --model-pthreads=yes|no model the pthreads library [no]\n"
1462#endif
1463" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001464"\n"
1465" --vex-iropt-verbosity 0 .. 9 [0]\n"
1466" --vex-iropt-level 0 .. 2 [2]\n"
1467" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001468" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1469" --vex-guest-max-insns 1 .. 100 [50]\n"
1470" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1471"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001472" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001473" 1000 0000 show conversion into IR\n"
1474" 0100 0000 show after initial opt\n"
1475" 0010 0000 show after instrumentation\n"
1476" 0001 0000 show after second opt\n"
1477" 0000 1000 show after tree building\n"
1478" 0000 0100 show selecting insns\n"
1479" 0000 0010 show after reg-alloc\n"
1480" 0000 0001 show final assembly\n"
1481"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001482" debugging options for Valgrind tools that report errors\n"
1483" --dump-error=<number> show translation for basic block associated\n"
1484" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001485"\n";
njn3e884182003-04-15 13:03:23 +00001486
1487 Char* usage3 =
1488"\n"
nethercote71980f02004-01-24 18:18:54 +00001489" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001490"\n"
njn53612422005-03-12 16:22:54 +00001491" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001492" and licensed under the GNU General Public License, version 2.\n"
1493" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001494"\n"
nethercote137bc552003-11-14 17:47:54 +00001495" Tools are copyright and licensed by their authors. See each\n"
1496" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001497"\n";
njn7cf0bd32002-06-08 13:36:03 +00001498
njnbe9b47b2005-05-15 16:22:58 +00001499 // Ensure the message goes to stdout
1500 VG_(clo_log_fd) = 1;
1501 vg_assert( !VG_(logging_to_socket) );
1502
fitzhardinge98abfc72003-12-16 02:05:15 +00001503 VG_(printf)(usage1);
1504 if (VG_(details).name) {
1505 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001506 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001507 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001508 else
1509 VG_(printf)(" (none)\n");
1510 }
nethercote6c999f22004-01-31 22:55:15 +00001511 if (debug_help) {
1512 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001513
nethercote6c999f22004-01-31 22:55:15 +00001514 if (VG_(details).name) {
1515 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1516
1517 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001518 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001519 else
1520 VG_(printf)(" (none)\n");
1521 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001522 }
nethercote421281e2003-11-20 16:20:55 +00001523 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001524 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001525}
sewardjde4a1d02002-03-22 01:27:54 +00001526
nethercote71980f02004-01-24 18:18:54 +00001527static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001528 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001529{
nethercote71980f02004-01-24 18:18:54 +00001530 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001531
sewardj8b635a42004-11-22 19:01:47 +00001532 LibVEX_default_VexControl(& VG_(clo_vex_control));
1533
nethercote71980f02004-01-24 18:18:54 +00001534 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001535 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001536
nethercotef6a1d502004-08-09 12:21:57 +00001537 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001538 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001539 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001540
nethercotef6a1d502004-08-09 12:21:57 +00001541 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1542 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001543 *need_help = 1;
1544
nethercotef6a1d502004-08-09 12:21:57 +00001545 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001546 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001547
nethercotef6c99d72004-11-09 14:35:43 +00001548 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001549 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001550
nethercotef6a1d502004-08-09 12:21:57 +00001551 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1552 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001553 }
1554 }
nethercote71980f02004-01-24 18:18:54 +00001555}
1556
nethercote5ee67ca2004-06-22 14:00:09 +00001557static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001558{
nethercotef8548672004-06-21 12:42:35 +00001559 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001560 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001561 enum {
1562 VgLogTo_Fd,
1563 VgLogTo_File,
1564 VgLogTo_FileExactly,
1565 VgLogTo_Socket
1566 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001567
nethercotee1730692003-11-20 10:38:07 +00001568 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001569 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001570
sewardj19d81412002-06-03 01:10:40 +00001571 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001572 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001573 config_error("Please use absolute paths in "
1574 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001575
njnc6168192004-11-29 13:54:10 +00001576// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001577#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001578 {
sewardjb5f6f512005-03-10 23:59:00 +00001579 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001580 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1581 switch(auxp[0]) {
1582 case AT_SYSINFO:
1583 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1584 break;
1585 }
1586 }
1587 }
1588#endif
sewardjde4a1d02002-03-22 01:27:54 +00001589
nethercotef6a1d502004-08-09 12:21:57 +00001590 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001593 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001594
thughes3bfd5a02004-07-18 08:05:44 +00001595 /* Look for a colon in the switch name */
1596 while (*colon && *colon != ':' && *colon != '=')
1597 colon++;
nethercote71980f02004-01-24 18:18:54 +00001598
1599 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001600 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001601 if (VG_CLO_STREQN(2, arg, "--") &&
1602 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1603 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1604 {
1605 // prefix matches, convert "--toolname:foo" to "--foo"
1606 if (0)
1607 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001608 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001609 arg[0] = '-';
1610 arg[1] = '-';
1611
1612 } else {
1613 // prefix doesn't match, skip to next arg
1614 continue;
1615 }
1616 }
1617
fitzhardinge98abfc72003-12-16 02:05:15 +00001618 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001619 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1620 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1621 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001622
njn45270a22005-03-27 01:00:11 +00001623 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001624
nethercote71980f02004-01-24 18:18:54 +00001625 else if (VG_CLO_STREQ(arg, "-v") ||
1626 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001627 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001628
nethercote71980f02004-01-24 18:18:54 +00001629 else if (VG_CLO_STREQ(arg, "-q") ||
1630 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001631 VG_(clo_verbosity)--;
1632
sewardj1cf558c2005-04-25 01:36:56 +00001633 else if (VG_CLO_STREQ(arg, "-d")) {
1634 /* do nothing */
1635 }
1636
sewardj71bc3cb2005-05-19 00:25:45 +00001637 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001638 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1639 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1640 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1641 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1642 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1643 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1644 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001645 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001646 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1647 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1648 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1649 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1650 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1651 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1652 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1653 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1654 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001655 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001656 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1657 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1658 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1659 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1660 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001661
njn45270a22005-03-27 01:00:11 +00001662 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1663 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001664
njn45270a22005-03-27 01:00:11 +00001665 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1666 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1667 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1668 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1669 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001670
njn45270a22005-03-27 01:00:11 +00001671 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001672 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001673 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001674 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001675 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001676 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001677 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001678 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001679 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001680 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001681 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001682 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1683
nethercotef8548672004-06-21 12:42:35 +00001684 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001685 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001686 VG_(clo_log_name) = NULL;
1687 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001688 }
1689
nethercotef8548672004-06-21 12:42:35 +00001690 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001691 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001692 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001693 }
njnd6bc3c32005-03-27 00:44:31 +00001694
sewardj603d4102005-01-11 14:01:02 +00001695 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001696 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001697 VG_(clo_log_name) = &arg[19];
1698 }
sewardjde4a1d02002-03-22 01:27:54 +00001699
nethercotef8548672004-06-21 12:42:35 +00001700 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001701 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001702 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001703 }
1704
nethercote71980f02004-01-24 18:18:54 +00001705 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001706 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001707 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001708 VG_(message)(Vg_UserMsg,
1709 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001710 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001711 }
nethercote71980f02004-01-24 18:18:54 +00001712 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001713 VG_(clo_n_suppressions)++;
1714 }
sewardjde4a1d02002-03-22 01:27:54 +00001715
sewardjfa8ec112005-01-19 11:55:34 +00001716 /* "stuvwxyz" --> stuvwxyz (binary) */
1717 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1718 Int j;
1719 char* opt = & arg[14];
1720
1721 if (8 != VG_(strlen)(opt)) {
1722 VG_(message)(Vg_UserMsg,
1723 "--trace-flags argument must have 8 digits");
1724 VG_(bad_option)(arg);
1725 }
1726 for (j = 0; j < 8; j++) {
1727 if ('0' == opt[j]) { /* do nothing */ }
1728 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1729 else {
1730 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1731 "contain 0s and 1s");
1732 VG_(bad_option)(arg);
1733 }
1734 }
1735 }
1736
1737 /* "stuvwxyz" --> stuvwxyz (binary) */
1738 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001739 Int j;
nethercote71980f02004-01-24 18:18:54 +00001740 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001741
sewardj2a99cf62004-11-24 10:44:19 +00001742 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001743 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001744 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001745 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001746 }
sewardj8b635a42004-11-22 19:01:47 +00001747 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001748 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001749 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001750 else {
sewardjfa8ec112005-01-19 11:55:34 +00001751 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001752 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001753 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001754 }
1755 }
1756 }
sewardjde4a1d02002-03-22 01:27:54 +00001757
njn45270a22005-03-27 01:00:11 +00001758 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001759
sewardjd153fae2005-01-10 17:24:47 +00001760 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1761 VG_(clo_gen_suppressions) = 0;
1762 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1763 VG_(clo_gen_suppressions) = 1;
1764 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1765 VG_(clo_gen_suppressions) = 2;
1766
nethercote71980f02004-01-24 18:18:54 +00001767 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001768 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001769 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001770 }
njn8c0b3bb2005-03-12 21:20:39 +00001771 skip_arg:
1772 if (arg != vg_argv[i])
1773 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001774 }
1775
sewardj998d40d2004-12-06 14:24:52 +00001776 /* Make VEX control parameters sane */
1777
1778 if (VG_(clo_vex_control).guest_chase_thresh
1779 >= VG_(clo_vex_control).guest_max_insns)
1780 VG_(clo_vex_control).guest_chase_thresh
1781 = VG_(clo_vex_control).guest_max_insns - 1;
1782
1783 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1784 VG_(clo_vex_control).guest_chase_thresh = 0;
1785
1786 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001787
njnf9ebf672003-05-12 21:41:30 +00001788 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001789 VG_(clo_verbosity) = 0;
1790
nethercote04d0fbc2004-01-26 16:48:06 +00001791 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001792 VG_(message)(Vg_UserMsg, "");
1793 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001794 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001795 VG_(message)(Vg_UserMsg,
1796 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001797 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001798 }
1799
njnbe9b47b2005-05-15 16:22:58 +00001800 if (VG_(clo_gen_suppressions) > 0 &&
1801 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1802 VG_(message)(Vg_UserMsg,
1803 "Can't use --gen-suppressions= with this tool,");
1804 VG_(message)(Vg_UserMsg,
1805 "as it doesn't generate errors.");
1806 VG_(bad_option)("--gen-suppressions=");
1807 }
1808
sewardj71bc3cb2005-05-19 00:25:45 +00001809 /* If we've been asked to emit XML, mash around various other
1810 options so as to constrain the output somewhat, and to remove
1811 any need for user input during the run. */
1812 if (VG_(clo_xml)) {
1813 /* Disable suppression generation (requires user input) */
1814 VG_(clo_gen_suppressions) = 0;
1815 /* Disable attaching to GDB (requires user input) */
1816 VG_(clo_db_attach) = False;
1817 /* Set a known verbosity level */
1818 VG_(clo_verbosity) = 1;
1819 /* Disable error limits (this might be a bad idea!) */
1820 VG_(clo_error_limit) = False;
1821 /* Disable emulation warnings */
1822 VG_(clo_show_emwarns) = False;
1823 /* Disable waiting for GDB to debug Valgrind */
1824 VG_(clo_wait_for_gdb) = False;
1825 /* No file-descriptor leak checking yet */
1826 VG_(clo_track_fds) = False;
1827 /* Also, we want to set options for the leak checker, but that
1828 will have to be done in Memcheck's flag-handling code, not
1829 here. */
1830 }
1831
njnbe9b47b2005-05-15 16:22:58 +00001832 /* All non-logging-related options have been checked. If the logging
1833 option specified is ok, we can switch to it, as we know we won't
1834 have to generate any other command-line-related error messages.
1835 (So far we should be still attached to stderr, so we can show on
1836 the terminal any problems to do with processing command line
1837 opts.)
1838
1839 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001840 should be connected to whatever sink has been selected, and we
1841 indiscriminately chuck stuff into it without worrying what the
1842 nature of it is. Oh the wonder of Unix streams. */
1843
njnbe9b47b2005-05-15 16:22:58 +00001844 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1845 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001846
njnbe9b47b2005-05-15 16:22:58 +00001847 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001848
sewardj4cf05692002-10-27 20:28:29 +00001849 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001850 vg_assert(VG_(clo_log_name) == NULL);
1851 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001852 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001853
sewardj4cf05692002-10-27 20:28:29 +00001854 case VgLogTo_File: {
1855 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001856 Int seq = 0;
1857 Int pid = VG_(getpid)();
1858
nethercotef8548672004-06-21 12:42:35 +00001859 vg_assert(VG_(clo_log_name) != NULL);
1860 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001861
nethercote71980f02004-01-24 18:18:54 +00001862 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001863 if (seq == 0)
1864 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001865 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001866 else
1867 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001868 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001869 seq++;
1870
njnbe9b47b2005-05-15 16:22:58 +00001871 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001872 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001873 = VG_(open)(logfilename,
1874 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1875 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001876 if (eventually_log_fd >= 0) {
1877 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001878 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001879 } else {
njnbe9b47b2005-05-15 16:22:58 +00001880 // If the file already existed, we try the next name. If it
1881 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001882 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001883 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001884 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001885 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001886 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001887 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001888 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001889 }
1890 }
1891 }
sewardj603d4102005-01-11 14:01:02 +00001892 break; /* switch (VG_(clo_log_to)) */
1893 }
1894
1895 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001896 vg_assert(VG_(clo_log_name) != NULL);
1897 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001898
1899 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001900 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001901 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1902 VKI_S_IRUSR|VKI_S_IWUSR);
1903 if (eventually_log_fd >= 0) {
1904 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001905 } else {
sewardj603d4102005-01-11 14:01:02 +00001906 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001907 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001908 VG_(clo_log_name));
1909 VG_(bad_option)(
1910 "--log-file-exactly=<file> (didn't work out for some reason.)");
1911 /*NOTREACHED*/
1912 }
1913 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001914 }
1915
1916 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001917 vg_assert(VG_(clo_log_name) != NULL);
1918 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1919 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1920 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001921 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001922 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001923 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001924 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001925 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001926 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001927 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001928 }
nethercotef8548672004-06-21 12:42:35 +00001929 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001930 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001931 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001932 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001933 VG_(message)(Vg_UserMsg,
1934 "Log messages will sent to stderr instead." );
1935 VG_(message)(Vg_UserMsg,
1936 "" );
1937 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001938 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001939 } else {
nethercotef8548672004-06-21 12:42:35 +00001940 vg_assert(eventually_log_fd > 0);
1941 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001942 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001943 }
sewardj73cf3bc2002-11-03 03:20:15 +00001944 break;
1945 }
sewardj4cf05692002-10-27 20:28:29 +00001946 }
1947
sewardj71bc3cb2005-05-19 00:25:45 +00001948
1949 /* Check that the requested tool actually supports XML output. */
1950 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1951 VG_(clo_xml) = False;
1952 VG_(message)(Vg_UserMsg,
1953 "Currently only Memcheck supports XML output.");
1954 VG_(bad_option)("--xml=yes");
1955 /*NOTREACHED*/
1956 }
1957
njnbe9b47b2005-05-15 16:22:58 +00001958 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1959 // XXX: this is more or less duplicating the behaviour of the calls to
1960 // VG_(safe_fd)() above, although this does not close the original fd.
1961 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1962 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001963 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001964 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001965 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1966 else {
nethercotef8548672004-06-21 12:42:35 +00001967 VG_(clo_log_fd) = eventually_log_fd;
1968 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001969 }
1970
sewardj4cf05692002-10-27 20:28:29 +00001971 /* Ok, the logging sink is running now. Print a suitable preamble.
1972 If logging to file or a socket, write details of parent PID and
1973 command line args, to help people trying to interpret the
1974 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001975
sewardj71bc3cb2005-05-19 00:25:45 +00001976 if (VG_(clo_xml)) {
1977 VG_(message)(Vg_UserMsg, "");
1978 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1979 VG_(message)(Vg_UserMsg, "");
1980 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1981 VG_(message)(Vg_UserMsg, "");
1982 }
1983
1984 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1985 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1986
sewardj83adf412002-05-01 01:25:45 +00001987 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001988 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001989 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1990 xpre,
njnd04b7c62002-10-03 14:05:52 +00001991 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001992 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001993 NULL == VG_(details).version
1994 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001995 VG_(details).description,
1996 xpost);
1997 VG_(message)(Vg_UserMsg, "%s%s%s",
1998 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001999
njnd04b7c62002-10-03 14:05:52 +00002000 /* Core details */
2001 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002002 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
2003 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00002004 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002005 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
2006 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00002007 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002008 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
2009 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00002010 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002011 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
2012 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00002013 }
2014
njnbe9b47b2005-05-15 16:22:58 +00002015 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002016 VG_(message)(Vg_UserMsg, "");
2017 VG_(message)(Vg_UserMsg,
2018 "My PID = %d, parent PID = %d. Prog and args are:",
2019 VG_(getpid)(), VG_(getppid)() );
2020 for (i = 0; i < VG_(client_argc); i++)
2021 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2022 }
sewardj71bc3cb2005-05-19 00:25:45 +00002023 else
2024 if (VG_(clo_xml)) {
2025 VG_(message)(Vg_UserMsg, "");
2026 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
2027 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
2028 VG_(message)(Vg_UserMsg, "");
2029 VG_(message)(Vg_UserMsg, "<argv>");
2030 for (i = 0; i < VG_(client_argc); i++)
2031 VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
2032 VG_(message)(Vg_UserMsg, "</argv>");
2033 }
sewardj4cf05692002-10-27 20:28:29 +00002034
sewardjde4a1d02002-03-22 01:27:54 +00002035 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002036 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00002037 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002038 VG_(message)(Vg_DebugMsg, "");
2039 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2040 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002041 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002042 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002043
njn1fd5eb22005-03-13 05:43:23 +00002044 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002045 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002046 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002047 }
nethercotea70f7352004-04-18 12:08:46 +00002048
njn1fd5eb22005-03-13 05:43:23 +00002049 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002050 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2051 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002052 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002053 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002054# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002055 Char version_buf[BUF_LEN];
2056 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002057 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002058 if (n > 0) {
2059 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002060 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002061 } else {
njn1fd5eb22005-03-13 05:43:23 +00002062 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002063 }
2064 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002065# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002066 }
sewardjde4a1d02002-03-22 01:27:54 +00002067 }
2068
fitzhardinge98abfc72003-12-16 02:05:15 +00002069 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002070 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002071 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002072 needs one, load the default */
2073 static const Char default_supp[] = "default.supp";
2074 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2075 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2076 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2077 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2078 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002079 }
2080}
2081
nethercotef6a1d502004-08-09 12:21:57 +00002082// Build the string for VALGRINDCLO.
2083Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2084{
2085 /* If we're tracing the children, then we need to start it
2086 with our starter+arguments, which are copied into VALGRINDCLO,
2087 except the --exec= option is changed if present.
2088 */
2089 Int i;
2090 Char *exec;
2091 Char *cp;
2092 Char *optvar;
2093 Int optlen, execlen;
2094
2095 // All these allocated blocks are not free - because we're either
2096 // going to exec, or panic when we fail.
2097
2098 // Create --exec= option: "--exec=<exename>"
2099 exec = VG_(arena_malloc)(VG_AR_CORE,
2100 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2101 vg_assert(NULL != exec);
2102 VG_(sprintf)(exec, "--exec=%s", exename);
2103
2104 // Allocate space for optvar (may overestimate by counting --exec twice,
2105 // no matter)
2106 optlen = 1;
2107 for (i = 0; i < vg_argc; i++)
2108 optlen += VG_(strlen)(vg_argv[i]) + 1;
2109 optlen += VG_(strlen)(exec)+1;
2110 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2111
2112 // Copy all valgrind args except the old --exec (if present)
2113 // VG_CLO_SEP is the separator.
2114 cp = optvar;
2115 for (i = 1; i < vg_argc; i++) {
2116 Char *arg = vg_argv[i];
2117
2118 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2119 // don't copy existing --exec= arg
2120 } else if (VG_(strcmp)(arg, "--") == 0) {
2121 // stop at "--"
2122 break;
2123 } else {
2124 // copy non "--exec" arg
2125 Int len = VG_(strlen)(arg);
2126 VG_(memcpy)(cp, arg, len);
2127 cp += len;
2128 *cp++ = VG_CLO_SEP;
2129 }
2130 }
2131 // Add the new --exec= option
2132 execlen = VG_(strlen)(exec);
2133 VG_(memcpy)(cp, exec, execlen);
2134 cp += execlen;
2135 *cp++ = VG_CLO_SEP;
2136
2137 *cp = '\0';
2138
2139 return optvar;
2140}
2141
2142// Build "/proc/self/fd/<execfd>".
2143Char* VG_(build_child_exename)( void )
2144{
2145 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2146 vg_assert(NULL != exename);
2147 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2148 return exename;
2149}
2150
sewardjde4a1d02002-03-22 01:27:54 +00002151
nethercote71980f02004-01-24 18:18:54 +00002152/*====================================================================*/
2153/*=== File descriptor setup ===*/
2154/*====================================================================*/
2155
2156static void setup_file_descriptors(void)
2157{
2158 struct vki_rlimit rl;
2159
2160 /* Get the current file descriptor limits. */
2161 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2162 rl.rlim_cur = 1024;
2163 rl.rlim_max = 1024;
2164 }
2165
2166 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002167 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2168 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002169 } else {
2170 rl.rlim_cur = rl.rlim_max;
2171 }
2172
2173 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002174 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2175 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002176
2177 /* Update the soft limit. */
2178 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2179
nethercotef6a1d502004-08-09 12:21:57 +00002180 if (vgexecfd != -1)
2181 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002182 if (VG_(clexecfd) != -1)
2183 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2184}
2185
nethercote71980f02004-01-24 18:18:54 +00002186/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002187/*=== Initialise program data/text, etc. ===*/
2188/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002189
sewardjb5f6f512005-03-10 23:59:00 +00002190static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2191 UInt dev, UInt ino, ULong foffset,
2192 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002193{
nethercote71980f02004-01-24 18:18:54 +00002194 /* Only record valgrind mappings for now, without loading any
2195 symbols. This is so we know where the free space is before we
2196 start allocating more memory (note: heap is OK, it's just mmap
2197 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002198 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002199 VG_(debugLog)(2, "main",
2200 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002201 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002202 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002203 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2204 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002205 /* update VG_(valgrind_last) if it looks wrong */
2206 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002207 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002208 }
sewardjde4a1d02002-03-22 01:27:54 +00002209}
2210
nethercote71980f02004-01-24 18:18:54 +00002211// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002212Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002213
sewardjb5f6f512005-03-10 23:59:00 +00002214/*
2215 This second pass adds in client mappings, and loads symbol tables
2216 for all interesting mappings. The trouble is that things can
2217 change as we go, because we're calling the Tool to track memory as
2218 we find it.
2219
2220 So for Valgrind mappings, we don't replace any mappings which
2221 aren't still identical (which will include the .so mappings, so we
2222 will load their symtabs)>
2223 */
2224static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2225 UInt dev, UInt ino, ULong foffset,
2226 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002227{
nethercote71980f02004-01-24 18:18:54 +00002228 UInt flags;
2229 Bool is_stack_segment;
2230 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002231
nethercote71980f02004-01-24 18:18:54 +00002232 is_stack_segment
2233 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002234
sewardj8c615892005-04-25 02:38:28 +00002235 VG_(debugLog)(2, "main",
2236 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002237 (void*)start, (void*)(start+size), prot, is_stack_segment,
2238 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002239
nethercote71980f02004-01-24 18:18:54 +00002240 if (is_stack_segment)
2241 flags = SF_STACK | SF_GROWDOWN;
2242 else
2243 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002244
nethercote71980f02004-01-24 18:18:54 +00002245 if (filename != NULL)
2246 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002247
sewardjb5f6f512005-03-10 23:59:00 +00002248#if 0
2249 // This needs to be fixed properly. jrs 20050307
2250 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2251 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002252
sewardjb5f6f512005-03-10 23:59:00 +00002253 /* We have to be a bit careful about inserting new mappings into
2254 the Valgrind part of the address space. We're actively
2255 changing things as we parse these mappings, particularly in
2256 shadow memory, and so we don't want to overwrite those
2257 changes. Therefore, we only insert/update a mapping if it is
2258 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002259
sewardjb5f6f512005-03-10 23:59:00 +00002260 NOTE: we're only talking about the Segment list mapping
2261 metadata; this doesn't actually mmap anything more. */
2262 if (filename || (s && s->addr == start && s->len == size)) {
2263 flags |= SF_VALGRIND;
2264 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2265 } else {
2266 /* assert range is already mapped */
2267 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2268 }
2269 } else
2270#endif
2271 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2272
2273 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2274 VG_TRACK( new_mem_startup, start, size,
2275 !!(prot & VKI_PROT_READ),
2276 !!(prot & VKI_PROT_WRITE),
2277 !!(prot & VKI_PROT_EXEC));
2278 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002279
nethercote71980f02004-01-24 18:18:54 +00002280 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002281 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002282 vg_assert(0 != r_esp);
2283 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002284 if (0) {
2285 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002286 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002287 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2288 r_esp, start+size);
2289 }
nethercote71980f02004-01-24 18:18:54 +00002290 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002291 // what's this for?
2292 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002293 }
sewardjde4a1d02002-03-22 01:27:54 +00002294}
2295
2296
nethercote71980f02004-01-24 18:18:54 +00002297/*====================================================================*/
2298/*=== Sanity check machinery (permanently engaged) ===*/
2299/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002300
2301/* A fast sanity check -- suitable for calling circa once per
2302 millisecond. */
2303
nethercote885dd912004-08-03 23:14:00 +00002304void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002305{
sewardjb5f6f512005-03-10 23:59:00 +00002306 ThreadId tid;
2307
njn37cea302002-09-30 11:24:00 +00002308 VGP_PUSHCC(VgpCoreCheapSanity);
2309
nethercote27fec902004-06-16 21:26:32 +00002310 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002311
2312 /* --- First do all the tests that we can do quickly. ---*/
2313
nethercote297effd2004-08-02 15:07:57 +00002314 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002315
njn25e49d8e72002-09-23 09:36:25 +00002316 /* Check stuff pertaining to the memory check system. */
2317
2318 /* Check that nobody has spuriously claimed that the first or
2319 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002320 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002321 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002322 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002323 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002324 }
njn25e49d8e72002-09-23 09:36:25 +00002325
2326 /* --- Now some more expensive checks. ---*/
2327
2328 /* Once every 25 times, check some more expensive stuff. */
2329 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002330 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002331 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002332
njn37cea302002-09-30 11:24:00 +00002333 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002334 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002335
2336# if 0
2337 { void zzzmemscan(void); zzzmemscan(); }
2338# endif
2339
nethercote297effd2004-08-02 15:07:57 +00002340 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002341 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002342
2343 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002344 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002345 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002346 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002347 }
sewardjb5f6f512005-03-10 23:59:00 +00002348
2349 /* Check that Segments and /proc/self/maps match up */
2350 //vg_assert(VG_(sanity_check_memory)());
2351
2352 /* Look for stack overruns. Visit all threads. */
2353 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002354 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002355
2356 if (VG_(threads)[tid].status == VgTs_Empty ||
2357 VG_(threads)[tid].status == VgTs_Zombie)
2358 continue;
2359
2360 remains = VGA_(stack_unused)(tid);
2361 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002362 VG_(message)(Vg_DebugMsg,
2363 "WARNING: Thread %d is within %d bytes "
2364 "of running out of stack!",
2365 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002366 }
2367
njn25e49d8e72002-09-23 09:36:25 +00002368 /*
nethercote297effd2004-08-02 15:07:57 +00002369 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002370 */
njn37cea302002-09-30 11:24:00 +00002371 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002372 }
2373
nethercote27fec902004-06-16 21:26:32 +00002374 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002375 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002376 /* Check sanity of the low-level memory manager. Note that bugs
2377 in the client's code can cause this to fail, so we don't do
2378 this check unless specially asked for. And because it's
2379 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002380 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002381 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002382 }
njn37cea302002-09-30 11:24:00 +00002383 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002384}
nethercote71980f02004-01-24 18:18:54 +00002385
2386
2387/*====================================================================*/
2388/*=== main() ===*/
2389/*====================================================================*/
2390
nethercotec314eba2004-07-15 12:59:41 +00002391/*
2392 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002393 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002394 loads the client executable (and the dynamic linker, if necessary)
2395 into the client part, and calls into Valgrind proper.
2396
2397 The code is careful not to allow spurious mappings to appear in the
2398 wrong parts of the address space. In particular, to make sure
2399 dlopen puts things in the right place, it will pad out the forbidden
2400 chunks of address space so that dlopen is forced to put things where
2401 we want them.
2402
2403 The memory map it creates is:
2404
njn311c5d82005-05-15 21:03:42 +00002405 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002406 | client address space |
2407 : :
2408 : :
2409 | client stack |
2410 client_end +-------------------------+
2411 | redzone |
2412 shadow_base +-------------------------+
2413 | |
nethercote996901a2004-08-03 13:29:09 +00002414 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002415 | (may be 0 sized) |
2416 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002417 valgrind_base +-------------------------+
2418 | kickstart executable |
2419 | valgrind heap vvvvvvvvv| (barely used)
2420 - -
2421 | valgrind .so files |
2422 | and mappings |
2423 - -
2424 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002425 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002426 : kernel :
2427
2428 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2429 VG_(mmap)(), we need to build the segment skip-list, so we know where
2430 we can put things. However, building that structure requires
2431 allocating memory. So we need to a bootstrapping process. It's done
2432 by making VG_(arena_malloc)() have a special static superblock that's
2433 used for the first 1MB's worth of allocations. This is enough to
2434 build the segment skip-list.
2435*/
2436
thughes4ad52d02004-06-27 17:37:21 +00002437
sewardj1cf558c2005-04-25 01:36:56 +00002438/* This may be needed before m_mylibc is OK to run. */
2439static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2440{
2441 while (True) {
2442 if (*s1 == 0 && *s2 == 0) return 0;
2443 if (*s1 == 0) return -1;
2444 if (*s2 == 0) return 1;
2445
2446 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2447 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2448
2449 s1++; s2++;
2450 }
2451}
2452
2453
sewardjb5f6f512005-03-10 23:59:00 +00002454int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002455{
2456 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002457 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002458 const char *exec = NULL;
2459 char *preload; /* tool-specific LD_PRELOAD .so */
2460 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002461 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002462 struct exeinfo info;
2463 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002464 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002465 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002466 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002467 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002468 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002469
2470 //============================================================
2471 // Nb: startup is complex. Prerequisites are shown at every step.
2472 //
2473 // *** Be very careful when messing with the order ***
2474 //============================================================
2475
sewardj1cf558c2005-04-25 01:36:56 +00002476 //--------------------------------------------------------------
2477 // Start up the logging mechanism
2478 // p: none
2479 //--------------------------------------------------------------
2480 /* Start the debugging-log system ASAP. First find out how many
2481 "-d"s were specified. This is a pre-scan of the command line. */
2482 loglevel = 0;
2483 for (i = 1; i < argc; i++) {
2484 if (argv[i][0] != '-')
2485 break;
2486 if (0 == local_strcmp(argv[i], "--"))
2487 break;
2488 if (0 == local_strcmp(argv[i], "-d"))
2489 loglevel++;
2490 }
2491
2492 /* ... and start the debug logger. Now we can safely emit logging
2493 messages all through startup. */
2494 VG_(debugLog_startup)(loglevel, "Stage 2");
2495
nethercotef4928da2004-06-15 10:54:40 +00002496 //============================================================
2497 // Command line argument handling order:
2498 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002499 // (including the tool-specific usage)
2500 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002501 // * Then, if client is missing, abort with error msg
2502 // * Then, if any cmdline args are bad, abort with error msg
2503 //============================================================
2504
fitzhardingeb50068f2004-02-24 23:42:55 +00002505 // Get the current process datasize rlimit, and set it to zero.
2506 // This prevents any internal uses of brk() from having any effect.
2507 // We remember the old value so we can restore it on exec, so that
2508 // child processes will have a reasonable brk value.
2509 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2510 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2511 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002512
2513 // Get the current process stack rlimit.
2514 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2515
nethercote71980f02004-01-24 18:18:54 +00002516 //--------------------------------------------------------------
2517 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002518 // p: none
nethercote71980f02004-01-24 18:18:54 +00002519 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002520 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002521 {
sewardj1fbc1a52005-04-25 02:05:54 +00002522 void* init_sp = argv - 1;
2523 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002524 }
2525
2526 //--------------------------------------------------------------
2527 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002528 // p: none
nethercote71980f02004-01-24 18:18:54 +00002529 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002530 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002531 if (cp != NULL)
2532 VG_(libdir) = cp;
2533 }
2534
2535 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002536 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2537 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002538 // p: none
nethercote71980f02004-01-24 18:18:54 +00002539 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002540 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002541 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002542 pre_process_cmd_line_options(&need_help, &tool, &exec);
2543
2544 //==============================================================
2545 // Nb: once a tool is specified, the tool.so must be loaded even if
2546 // they specified --help or didn't specify a client program.
2547 //==============================================================
2548
2549 //--------------------------------------------------------------
2550 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002551 // p: set-libdir [for VG_(libdir)]
2552 // p: pre_process_cmd_line_options() [for 'tool']
2553 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002554 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002555 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002556
2557 //==============================================================
2558 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002559 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002560 //==============================================================
2561
2562 //--------------------------------------------------------------
2563 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002564 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002565 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002566 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002567 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002568
2569 //--------------------------------------------------------------
2570 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002571 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2572 // p: layout_remaining_space [so there's space]
2573 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002574 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002575 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002576
2577 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002578 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002579 // p: layout_remaining_space() [everything must be mapped in before now]
2580 // p: load_client() [ditto]
2581 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002582 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2583 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002584
2585 //--------------------------------------------------------------
2586 // Set up client's environment
2587 // p: set-libdir [for VG_(libdir)]
2588 // p: load_tool() [for 'preload']
2589 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002590 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002591 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002592
2593 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002594 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002595 // p: load_client() [for 'info']
2596 // p: fix_environment() [for 'env']
2597 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002598 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002599 {
sewardj1fbc1a52005-04-25 02:05:54 +00002600 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002601
sewardj1fbc1a52005-04-25 02:05:54 +00002602 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2603 &client_auxv);
2604 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002605 }
nethercote71980f02004-01-24 18:18:54 +00002606
sewardj1fbc1a52005-04-25 02:05:54 +00002607 VG_(debugLog)(2, "main",
2608 "Client info: "
2609 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2610 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2611 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002612
2613 //==============================================================
2614 // Finished setting up operating environment. Now initialise
2615 // Valgrind. (This is where the old VG_(main)() started.)
2616 //==============================================================
2617
2618 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002619 // setup file descriptors
2620 // p: n/a
2621 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002622 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002623 setup_file_descriptors();
2624
2625 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002626 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002627 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002628 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002629 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002630 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2631
2632 //==============================================================
2633 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2634 //==============================================================
2635
2636 //--------------------------------------------------------------
2637 // Init tool: pre_clo_init, process cmd line, post_clo_init
2638 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002639 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002640 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2641 // p: parse_procselfmaps [so VG segments are setup so tool can
2642 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002643 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002644 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002645 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002646 VG_(sanity_check_needs)();
2647
nethercotef4928da2004-06-15 10:54:40 +00002648 // If --tool and --help/--help-debug was given, now give the core+tool
2649 // help message
nethercotef4928da2004-06-15 10:54:40 +00002650 if (need_help) {
2651 usage(/*--help-debug?*/2 == need_help);
2652 }
nethercotec314eba2004-07-15 12:59:41 +00002653 process_cmd_line_options(client_auxv, tool);
2654
njn51d827b2005-05-09 01:02:08 +00002655 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002656
2657 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002658 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002659 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002660 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002661 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002662 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002663 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002664 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002665 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002666 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002667
sewardj21c6d0f2005-05-02 10:33:44 +00002668#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002669 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002670 // Protect client trampoline page (which is also sysinfo stuff)
2671 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002672 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002673 {
2674 Segment *seg;
2675 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2676 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002677
sewardjb5f6f512005-03-10 23:59:00 +00002678 /* Make sure this segment isn't treated as stack */
2679 seg = VG_(find_segment)(VG_(client_trampoline_code));
2680 if (seg)
2681 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2682 }
sewardj21c6d0f2005-05-02 10:33:44 +00002683#endif
sewardjb5f6f512005-03-10 23:59:00 +00002684
nethercotec314eba2004-07-15 12:59:41 +00002685 //==============================================================
2686 // Can use VG_(map)() after segments set up
2687 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002688
2689 //--------------------------------------------------------------
2690 // Allow GDB attach
2691 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2692 //--------------------------------------------------------------
2693 /* Hook to delay things long enough so we can get the pid and
2694 attach GDB in another shell. */
2695 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002696 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002697 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2698 /* jrs 20050206: I don't understand why this works on x86. On
2699 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2700 work. */
2701 /* do "jump *$eip" to skip this in gdb (x86) */
2702 //VG_(do_syscall0)(__NR_pause);
2703 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002704 }
2705
sewardjb5d320c2005-03-13 18:57:15 +00002706 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002707 // Search for file descriptors that are inherited from our parent
2708 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2709 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002710 if (VG_(clo_track_fds)) {
2711 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002712 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002713 }
nethercote71980f02004-01-24 18:18:54 +00002714
2715 //--------------------------------------------------------------
2716 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002717 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2718 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002719 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002720 VG_(scheduler_init)();
2721
2722 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002723 // Initialise the pthread model
2724 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002725 // load_client() [for 'client_eip']
2726 // setup_client_stack() [for 'sp_at_startup']
2727 // setup_scheduler() [for the rest of state 1 stuff]
2728 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002729 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002730 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002731
2732 // Tell the tool that we just wrote to the registers.
2733 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2734 sizeof(VexGuestArchState));
2735
sewardj2a99cf62004-11-24 10:44:19 +00002736 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002737 // Initialise the pthread model
2738 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002739 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002740 //if (VG_(clo_model_pthreads))
2741 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002742
2743 //--------------------------------------------------------------
2744 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002745 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002746 //--------------------------------------------------------------
2747 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002748 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002749 VG_(sigstartup_actions)();
2750
2751 //--------------------------------------------------------------
2752 // Perhaps we're profiling Valgrind?
2753 // p: process_cmd_line_options() [for VG_(clo_profile)]
2754 // p: others?
2755 //
2756 // XXX: this seems to be broken? It always says the tool wasn't built
2757 // for profiling; vg_profile.c's functions don't seem to be overriding
2758 // vg_dummy_profile.c's?
2759 //
2760 // XXX: want this as early as possible. Looking for --profile
2761 // in pre_process_cmd_line_options() could get it earlier.
2762 //--------------------------------------------------------------
2763 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002764 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002765
2766 VGP_PUSHCC(VgpStartup);
2767
2768 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002769 // Read suppression file
2770 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2771 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002772 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2773 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002774 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002775 }
nethercote71980f02004-01-24 18:18:54 +00002776
2777 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002778 // Initialise translation table and translation cache
2779 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2780 // aren't identified as part of the client, which would waste
2781 // > 20M of virtual address space.]
2782 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002783 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002784 VG_(init_tt_tc)();
2785
2786 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002787 // Read debug info to find glibc entry points to intercept
2788 // p: parse_procselfmaps? [XXX for debug info?]
2789 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2790 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002791 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002792 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002793 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002794
2795 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002796 // Verbosity message
2797 // p: end_rdtsc_calibration [so startup message is printed first]
2798 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002799 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002800 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2801 if (VG_(clo_verbosity) > 0)
2802 VG_(message)(Vg_UserMsg, "");
2803
2804 //--------------------------------------------------------------
2805 // Setup pointercheck
2806 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2807 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002808 if (VG_(clo_pointercheck))
2809 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002810
nethercote71980f02004-01-24 18:18:54 +00002811 //--------------------------------------------------------------
2812 // Run!
2813 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002814 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002815
sewardjb5f6f512005-03-10 23:59:00 +00002816 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002817
sewardj71bc3cb2005-05-19 00:25:45 +00002818 if (VG_(clo_xml)) {
2819 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2820 VG_(message)(Vg_UserMsg, "");
2821 }
2822
sewardj1fbc1a52005-04-25 02:05:54 +00002823 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002824 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002825
sewardjb5f6f512005-03-10 23:59:00 +00002826 abort();
2827}
2828
2829
2830/* Do everything which needs doing when the last thread exits */
2831void VG_(shutdown_actions)(ThreadId tid)
2832{
2833 vg_assert(tid == VG_(master_tid));
2834 vg_assert(VG_(is_running_thread)(tid));
2835
2836 // Wait for all other threads to exit.
2837 VGA_(reap_threads)(tid);
2838
2839 VG_(clo_model_pthreads) = False;
2840
2841 // Clean the client up before the final report
2842 VGA_(final_tidyup)(tid);
2843
2844 // OK, done
2845 VG_(exit_thread)(tid);
2846
2847 /* should be no threads left */
2848 vg_assert(VG_(count_living_threads)() == 0);
2849
2850 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002851 //--------------------------------------------------------------
2852 // Finalisation: cleanup, messages, etc. Order no so important, only
2853 // affects what order the messages come.
2854 //--------------------------------------------------------------
2855 if (VG_(clo_verbosity) > 0)
2856 VG_(message)(Vg_UserMsg, "");
2857
sewardj71bc3cb2005-05-19 00:25:45 +00002858 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002859 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2860 VG_(show_error_counts_as_XML)();
2861 VG_(message)(Vg_UserMsg, "");
2862 }
sewardj71bc3cb2005-05-19 00:25:45 +00002863 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2864 VG_(message)(Vg_UserMsg, "");
2865 }
2866
nethercote71980f02004-01-24 18:18:54 +00002867 /* Print out file descriptor summary and stats. */
2868 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002869 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002870
njn95ec8702004-11-22 16:46:13 +00002871 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002872 VG_(show_all_errors)();
2873
njn51d827b2005-05-09 01:02:08 +00002874 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002875
sewardj71bc3cb2005-05-19 00:25:45 +00002876 if (VG_(clo_xml)) {
2877 VG_(message)(Vg_UserMsg, "");
2878 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2879 VG_(message)(Vg_UserMsg, "");
2880 }
2881
nethercote885dd912004-08-03 23:14:00 +00002882 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002883
2884 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002885 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002886
nethercote71980f02004-01-24 18:18:54 +00002887 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002888 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002889 if (VG_(clo_profile_flags) > 0)
2890 VG_(show_BB_profile)();
2891
sewardj8b635a42004-11-22 19:01:47 +00002892 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002893 if (0)
2894 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002895}
sewardj8b635a42004-11-22 19:01:47 +00002896
sewardjde4a1d02002-03-22 01:27:54 +00002897/*--------------------------------------------------------------------*/
2898/*--- end vg_main.c ---*/
2899/*--------------------------------------------------------------------*/