blob: a18a69f52195e77a284ae83f783235abdd359581 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
39#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000040#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000041#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000042
43#include <dirent.h>
44#include <dlfcn.h>
45#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000046#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000047#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000048#include <string.h>
49#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000050#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000051#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000052#include <sys/wait.h>
53#include <unistd.h>
54
sewardjb5f6f512005-03-10 23:59:00 +000055#include "memcheck/memcheck.h"
56
thughes74b8de22004-04-22 18:12:31 +000057#ifndef AT_DCACHEBSIZE
58#define AT_DCACHEBSIZE 19
59#endif /* AT_DCACHEBSIZE */
60
61#ifndef AT_ICACHEBSIZE
62#define AT_ICACHEBSIZE 20
63#endif /* AT_ICACHEBSIZE */
64
65#ifndef AT_UCACHEBSIZE
66#define AT_UCACHEBSIZE 21
67#endif /* AT_UCACHEBSIZE */
68
nethercote71980f02004-01-24 18:18:54 +000069#ifndef AT_SYSINFO
70#define AT_SYSINFO 32
71#endif /* AT_SYSINFO */
72
73#ifndef AT_SYSINFO_EHDR
74#define AT_SYSINFO_EHDR 33
75#endif /* AT_SYSINFO_EHDR */
76
77#ifndef AT_SECURE
78#define AT_SECURE 23 /* secure mode boolean */
79#endif /* AT_SECURE */
80
nethercote71980f02004-01-24 18:18:54 +000081/* redzone gap between client address space and shadow */
82#define REDZONE_SIZE (1 * 1024*1024)
83
84/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000085#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000086
nethercotee2097312004-06-27 12:29:56 +000087/* Proportion of client space for its heap (rest is for mmaps + stack) */
88#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000089
njn14319cc2005-03-13 06:26:22 +000090/* Number of file descriptors that Valgrind tries to reserve for
91 it's own use - just a small constant. */
92#define N_RESERVED_FDS (10)
93
94/* Default debugger command. */
95#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
96
nethercote71980f02004-01-24 18:18:54 +000097/*====================================================================*/
98/*=== Global entities not referenced from generated code ===*/
99/*====================================================================*/
100
sewardjde4a1d02002-03-22 01:27:54 +0000101/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000102 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000103 ------------------------------------------------------------------ */
104
nethercote71980f02004-01-24 18:18:54 +0000105/* Client address space, lowest to highest (see top of ume.c) */
106Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000107Addr VG_(client_end);
108Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000109Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000110Addr VG_(clstk_base);
111Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000112
113Addr VG_(brk_base); /* start of brk */
114Addr VG_(brk_limit); /* current brk */
115
nethercote996901a2004-08-03 13:29:09 +0000116Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000117Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000118
119Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000120
nethercote820bd8c2004-09-07 23:04:49 +0000121// Note that VG_(valgrind_last) names the last byte of the section, whereas
122// the VG_(*_end) vars name the byte one past the end of the section.
123Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
nethercote73b526f2004-10-31 18:48:21 +0000125struct vki_rlimit VG_(client_rlimit_data);
126struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000127
fitzhardinge98abfc72003-12-16 02:05:15 +0000128/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000129static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000130
131/* client executable */
132Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000133
134/* Path to library directory */
135const Char *VG_(libdir) = VG_LIBDIR;
136
137/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000138static Int vg_argc;
139static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000140
sewardjb5f6f512005-03-10 23:59:00 +0000141/* The master thread the one which will be responsible for mopping
142 everything up at exit. Normally it is tid 1, since that's the
143 first thread created, but it may be something else after a
144 fork(). */
145ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000146
thughesad1c9562004-06-26 11:27:52 +0000147/* Application-visible file descriptor limits */
148Int VG_(fd_soft_limit) = -1;
149Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000150
nethercote4ad74312004-10-26 09:59:49 +0000151/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000152 envp[] as extracted from the client's stack at startup-time. */
153Int VG_(client_argc);
154Char** VG_(client_argv);
155Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000156
sewardj51ac0872004-12-21 01:20:49 +0000157
sewardjde4a1d02002-03-22 01:27:54 +0000158/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000159 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000160 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000161
sewardjde4a1d02002-03-22 01:27:54 +0000162/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000163ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000164
nethercote71980f02004-01-24 18:18:54 +0000165/* Tell the logging mechanism whether we are logging to a file
166 descriptor or a socket descriptor. */
njnbe9b47b2005-05-15 16:22:58 +0000167Bool VG_(logging_to_socket) = False;
nethercote71980f02004-01-24 18:18:54 +0000168
sewardj73cf3bc2002-11-03 03:20:15 +0000169
nethercote71980f02004-01-24 18:18:54 +0000170/*====================================================================*/
171/*=== Counters, for profiling purposes only ===*/
172/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000173
sewardjde4a1d02002-03-22 01:27:54 +0000174/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000175static UInt sanity_fast_count = 0;
176static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000177
nethercote3a42fb82004-08-03 18:08:50 +0000178static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000179{
nethercote3a42fb82004-08-03 18:08:50 +0000180 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000181 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000183 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000184
nethercote3a42fb82004-08-03 18:08:50 +0000185 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000186 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000187
nethercote71980f02004-01-24 18:18:54 +0000188 VG_(message)(Vg_DebugMsg,
189 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000190 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000191
njn9271cbc2005-03-13 05:38:25 +0000192 VG_(print_ExeContext_stats)();
193
nethercote3a42fb82004-08-03 18:08:50 +0000194 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000195 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000196 VG_(message)(Vg_DebugMsg, "");
197 VG_(message)(Vg_DebugMsg,
198 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000199 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000200 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000201 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000202 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000203 }
nethercote71980f02004-01-24 18:18:54 +0000204}
205
206
207/*====================================================================*/
208/*=== Miscellaneous global functions ===*/
209/*====================================================================*/
210
nethercotecf97ffb2004-09-09 13:40:31 +0000211static Int ptrace_setregs(Int pid, ThreadId tid)
212{
sewardj2a99cf62004-11-24 10:44:19 +0000213 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000214}
215
nethercote04d0fbc2004-01-26 16:48:06 +0000216/* Start debugger and get it to attach to this process. Called if the
217 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000218 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000219 meaningfully get the debugger to continue the program, though; to
220 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000221void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000222{
223 Int pid;
224
225 if ((pid = fork()) == 0) {
226 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000227 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000228
229 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000230 Int status;
231 Int res;
232
nethercote71980f02004-01-24 18:18:54 +0000233 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
234 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000235 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000236 kill(pid, SIGSTOP) == 0 &&
237 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000238 Char pidbuf[15];
239 Char file[30];
240 Char buf[100];
241 Char *bufptr;
242 Char *cmdptr;
243
244 VG_(sprintf)(pidbuf, "%d", pid);
245 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
246
247 bufptr = buf;
248 cmdptr = VG_(clo_db_command);
249
250 while (*cmdptr) {
251 switch (*cmdptr) {
252 case '%':
253 switch (*++cmdptr) {
254 case 'f':
255 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
256 bufptr += VG_(strlen)(file);
257 cmdptr++;
258 break;
259 case 'p':
260 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
261 bufptr += VG_(strlen)(pidbuf);
262 cmdptr++;
263 break;
264 default:
265 *bufptr++ = *cmdptr++;
266 break;
267 }
268 break;
269 default:
270 *bufptr++ = *cmdptr++;
271 break;
272 }
273 }
274
275 *bufptr++ = '\0';
276
277 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000278 res = VG_(system)(buf);
279 if (res == 0) {
280 VG_(message)(Vg_UserMsg, "");
281 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000282 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000283 } else {
284 VG_(message)(Vg_UserMsg, "Apparently failed!");
285 VG_(message)(Vg_UserMsg, "");
286 }
287 }
288
nethercote73b526f2004-10-31 18:48:21 +0000289 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000290 VG_(waitpid)(pid, &status, 0);
291 }
292}
293
294
295/* Print some helpful-ish text about unimplemented things, and give
296 up. */
297void VG_(unimplemented) ( Char* msg )
298{
299 VG_(message)(Vg_UserMsg, "");
300 VG_(message)(Vg_UserMsg,
301 "Valgrind detected that your program requires");
302 VG_(message)(Vg_UserMsg,
303 "the following unimplemented functionality:");
304 VG_(message)(Vg_UserMsg, " %s", msg);
305 VG_(message)(Vg_UserMsg,
306 "This may be because the functionality is hard to implement,");
307 VG_(message)(Vg_UserMsg,
308 "or because no reasonable program would behave this way,");
309 VG_(message)(Vg_UserMsg,
310 "or because nobody has yet needed it. In any case, let us know at");
311 VG_(message)(Vg_UserMsg,
312 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
313 VG_(message)(Vg_UserMsg,
314 "");
315 VG_(message)(Vg_UserMsg,
316 "Valgrind has to exit now. Sorry. Bye!");
317 VG_(message)(Vg_UserMsg,
318 "");
319 VG_(pp_sched_status)();
320 VG_(exit)(1);
321}
322
sewardj2a99cf62004-11-24 10:44:19 +0000323/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000324Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000325{
njncf45fd42004-11-24 16:30:22 +0000326 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000327}
328
njn67516132005-03-22 04:02:43 +0000329Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000330{
331 return INSTR_PTR( VG_(threads)[tid].arch );
332}
333
njnea4b28c2004-11-30 16:04:58 +0000334
nethercote71980f02004-01-24 18:18:54 +0000335/*====================================================================*/
336/*=== Check we were launched by stage 1 ===*/
337/*====================================================================*/
338
339/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000340static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000341{
nethercoteebf1d862004-11-01 18:22:05 +0000342 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000343 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000344
345 for (; auxv->a_type != AT_NULL; auxv++)
346 switch(auxv->a_type) {
347 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000348 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000349 found |= 1;
350 break;
351
352 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000353 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000354 found |= 2;
355 break;
nethercote7f390022004-10-25 17:18:24 +0000356
357 case AT_PHDR:
358 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
359 break;
nethercote71980f02004-01-24 18:18:54 +0000360 }
361
nethercote361a14e2004-07-26 11:11:56 +0000362 if ( found != (1|2) ) {
363 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000364 exit(127);
365 }
nethercote31779c72004-07-30 21:50:15 +0000366 vg_assert(padfile >= 0);
367 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000368}
369
370
371/*====================================================================*/
372/*=== Address space determination ===*/
373/*====================================================================*/
374
nethercote7f390022004-10-25 17:18:24 +0000375extern char _start[];
376
nethercote31779c72004-07-30 21:50:15 +0000377static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000378{
nethercotea3c3cf22004-11-01 18:38:00 +0000379 Int ires;
380 void* vres;
381 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000382
nethercote7f390022004-10-25 17:18:24 +0000383 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
384 // this is a workable approximation
385 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000386 VG_(valgrind_base) = PGROUNDDN(&_start);
387 }
388
nethercote820bd8c2004-09-07 23:04:49 +0000389 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000390
nethercote31779c72004-07-30 21:50:15 +0000391 // This gives the client the largest possible address space while
392 // taking into account the tool's shadow needs.
393 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000394 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000395 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000396 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000397 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000398 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000399 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000400
nethercote31779c72004-07-30 21:50:15 +0000401 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000402 VG_(shadow_end) = VG_(valgrind_base);
403 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000404
nethercotee2097312004-06-27 12:29:56 +0000405#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
406
nethercote71980f02004-01-24 18:18:54 +0000407 if (0)
nethercotee2097312004-06-27 12:29:56 +0000408 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000409 "client_base %p (%dMB)\n"
410 "client_mapbase %p (%dMB)\n"
411 "client_end %p (%dMB)\n"
412 "shadow_base %p (%dMB)\n"
413 "shadow_end %p\n"
414 "valgrind_base %p (%dMB)\n"
415 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000416 VG_(client_base), SEGSIZE(client_base, client_mapbase),
417 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
418 VG_(client_end), SEGSIZE(client_end, shadow_base),
419 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000420 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000421 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
422 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000423 );
424
425#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000426
427 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000428 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000429 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000430 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000431
432 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000433 ires = munmap((void*)VG_(client_base), client_size);
434 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000435
436 // Map shadow memory.
437 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000438 if (shadow_size != 0) {
439 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000440 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000441 if ((void*)-1 == vres) {
442 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000443 "valgrind: Could not allocate address space (%p bytes)\n"
444 "valgrind: for shadow memory\n"
445 "valgrind: Possible causes:\n"
446 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
447 "valgrind: needs at least 1.5GB swap space.\n"
448 "valgrind: - Or, your virtual memory size may be limited (check\n"
449 "valgrind: with 'ulimit -v').\n"
450 "valgrind: - Or, your system may use a kernel that provides only a\n"
451 "valgrind: too-small (eg. 2GB) user address space.\n"
452 , (void*)shadow_size
453 );
nethercoted4722622004-08-30 19:36:42 +0000454 exit(1);
455 }
nethercotee567e702004-07-10 17:49:17 +0000456 }
nethercote71980f02004-01-24 18:18:54 +0000457}
458
459/*====================================================================*/
460/*=== Command line setup ===*/
461/*====================================================================*/
462
463/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
464static char* get_file_clo(char* dir)
465{
466# define FLEN 512
467 Int fd, n;
468 struct stat s1;
469 char* f_clo = NULL;
470 char filename[FLEN];
471
472 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
473 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
474 if ( fd > 0 ) {
475 if ( 0 == fstat(fd, &s1) ) {
476 f_clo = malloc(s1.st_size+1);
477 vg_assert(f_clo);
478 n = read(fd, f_clo, s1.st_size);
479 if (n == -1) n = 0;
480 f_clo[n] = '\0';
481 }
482 close(fd);
483 }
484 return f_clo;
485# undef FLEN
486}
487
488static Int count_args(char* s)
489{
490 Int n = 0;
491 if (s) {
492 char* cp = s;
493 while (True) {
494 // We have alternating sequences: blanks, non-blanks, blanks...
495 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000496 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000497 if ( !*cp ) break;
498 n++;
njn0c0f32a2005-03-26 04:14:01 +0000499 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000500 }
501 }
502 return n;
503}
504
505/* add args out of environment, skipping multiple spaces and -- args */
506static char** copy_args( char* s, char** to )
507{
508 if (s) {
509 char* cp = s;
510 while (True) {
511 // We have alternating sequences: blanks, non-blanks, blanks...
512 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000513 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000514 if ( !*cp ) break;
515 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000516 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000517 if ( *cp ) *cp++ = '\0'; // terminate if necessary
518 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
519 }
520 }
521 return to;
522}
523
524// Augment command line with arguments from environment and .valgrindrc
525// files.
526static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
527{
nethercotef6a1d502004-08-09 12:21:57 +0000528 int vg_argc0 = *vg_argc_inout;
529 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000530
531 char* env_clo = getenv(VALGRINDOPTS);
532 char* f1_clo = get_file_clo( getenv("HOME") );
533 char* f2_clo = get_file_clo(".");
534
535 /* copy any extra args from file or environment, if present */
536 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
537 /* ' ' separated extra options */
538 char **from;
539 char **to;
thughescaca0022004-09-13 10:20:34 +0000540 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
541
542 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
543
nethercote71980f02004-01-24 18:18:54 +0000544 env_arg_count = count_args(env_clo);
545 f1_arg_count = count_args(f1_clo);
546 f2_arg_count = count_args(f2_clo);
547
548 if (0)
549 printf("extra-argc=%d %d %d\n",
550 env_arg_count, f1_arg_count, f2_arg_count);
551
552 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000553 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000554 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000555 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000556 vg_assert(vg_argv0);
557 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000558
559 /* copy argv[0] */
560 *to++ = *from++;
561
562 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
563 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
564 * to override less local ones. */
565 to = copy_args(f1_clo, to);
566 to = copy_args(env_clo, to);
567 to = copy_args(f2_clo, to);
568
569 /* copy original arguments, stopping at command or -- */
570 while (*from) {
571 if (**from != '-')
572 break;
573 if (VG_STREQ(*from, "--")) {
574 from++; /* skip -- */
575 break;
576 }
577 *to++ = *from++;
578 }
579
580 /* add -- */
581 *to++ = "--";
582
nethercotef6a1d502004-08-09 12:21:57 +0000583 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000584
585 /* copy rest of original command line, then NULL */
586 while (*from) *to++ = *from++;
587 *to = NULL;
588 }
589
nethercotef6a1d502004-08-09 12:21:57 +0000590 *vg_argc_inout = vg_argc0;
591 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000592}
593
nethercotef6a1d502004-08-09 12:21:57 +0000594#define VG_CLO_SEP '\01'
595
nethercote71980f02004-01-24 18:18:54 +0000596static void get_command_line( int argc, char** argv,
597 Int* vg_argc_out, Char*** vg_argv_out,
598 char*** cl_argv_out )
599{
nethercotef6a1d502004-08-09 12:21:57 +0000600 int vg_argc0;
601 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000602 char** cl_argv;
603 char* env_clo = getenv(VALGRINDCLO);
604
605 if (env_clo != NULL && *env_clo != '\0') {
606 char *cp;
607 char **cpp;
608
nethercotef6a1d502004-08-09 12:21:57 +0000609 /* OK, VALGRINDCLO is set, which means we must be a child of another
610 Valgrind process using --trace-children, so we're getting all our
611 arguments from VALGRINDCLO, and the entire command line belongs to
612 the client (including argv[0]) */
613 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000614 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000615 if (*cp == VG_CLO_SEP)
616 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000617
nethercotef6a1d502004-08-09 12:21:57 +0000618 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
619 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000620
nethercotef6a1d502004-08-09 12:21:57 +0000621 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000622
623 *cpp++ = "valgrind"; /* nominal argv[0] */
624 *cpp++ = env_clo;
625
nethercotef6a1d502004-08-09 12:21:57 +0000626 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000627 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000628 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000629 *cp++ = '\0'; /* chop it up in place */
630 *cpp++ = cp;
631 }
632 }
633 *cpp = NULL;
634 cl_argv = argv;
635
636 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000637 Bool noaugment = False;
638
nethercote71980f02004-01-24 18:18:54 +0000639 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000640 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000641
nethercotef6a1d502004-08-09 12:21:57 +0000642 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000643 Char* arg = argv[vg_argc0];
644 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000645 break;
sewardjb5f6f512005-03-10 23:59:00 +0000646 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000647 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000648 break;
649 }
njn45270a22005-03-27 01:00:11 +0000650 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000651 }
nethercotef6a1d502004-08-09 12:21:57 +0000652 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000653
654 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000655 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000656 those extra args will already be present in VALGRINDCLO.
657 (We also don't do it when --command-line-only=yes.) */
658 if (!noaugment)
659 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000660 }
661
662 if (0) {
663 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000664 for (i = 0; i < vg_argc0; i++)
665 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000666 }
667
nethercotef6a1d502004-08-09 12:21:57 +0000668 *vg_argc_out = vg_argc0;
669 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000670 *cl_argv_out = cl_argv;
671}
672
673
674/*====================================================================*/
675/*=== Environment and stack setup ===*/
676/*====================================================================*/
677
678/* Scan a colon-separated list, and call a function on each element.
679 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000680 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000681 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000682
683 This routine will return True if (*func) returns True and False if
684 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000685*/
thughes4ad52d02004-06-27 17:37:21 +0000686static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000687{
688 char *cp, *entry;
689 int end;
690
691 if (colsep == NULL ||
692 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000693 return False;
nethercote71980f02004-01-24 18:18:54 +0000694
695 entry = cp = colsep;
696
697 do {
698 end = (*cp == '\0');
699
700 if (*cp == ':' || *cp == '\0') {
701 char save = *cp;
702
703 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000704 if ((*func)(entry)) {
705 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000706 return True;
thughes21942d92004-07-12 09:35:37 +0000707 }
nethercote71980f02004-01-24 18:18:54 +0000708 *cp = save;
709 entry = cp+1;
710 }
711 cp++;
712 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000713
714 return False;
715}
716
nethercote71980f02004-01-24 18:18:54 +0000717/* Prepare the client's environment. This is basically a copy of our
718 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000719 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000720
sewardjb5f6f512005-03-10 23:59:00 +0000721 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000722
723 Yummy. String hacking in C.
724
725 If this needs to handle any more variables it should be hacked
726 into something table driven.
727 */
728static char **fix_environment(char **origenv, const char *preload)
729{
730 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000731 static const char ld_preload[] = "LD_PRELOAD=";
732 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000733 static const int ld_preload_len = sizeof(ld_preload)-1;
734 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
735 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000736 char *inject_path;
737 int inject_path_len;
738 int vgliblen = strlen(VG_(libdir));
739 char **cpp;
740 char **ret;
741 int envc;
742 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
743
744 /* Find the vg_inject.so; also make room for the tool preload
745 library */
746 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
747 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000748 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000749
750 if (preload)
751 snprintf(inject_path, inject_path_len, "%s/%s:%s",
752 VG_(libdir), inject_so, preload);
753 else
754 snprintf(inject_path, inject_path_len, "%s/%s",
755 VG_(libdir), inject_so);
756
757 /* Count the original size of the env */
758 envc = 0; /* trailing NULL */
759 for (cpp = origenv; cpp && *cpp; cpp++)
760 envc++;
761
762 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000763 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000764 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000765
766 /* copy it over */
767 for (cpp = ret; *origenv; )
768 *cpp++ = *origenv++;
769 *cpp = NULL;
770
771 vg_assert(envc == (cpp - ret));
772
773 /* Walk over the new environment, mashing as we go */
774 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000775 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000776 int len = strlen(*cpp) + inject_path_len;
777 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000778 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000779
780 snprintf(cp, len, "%s%s:%s",
781 ld_preload, inject_path, (*cpp)+ld_preload_len);
782
783 *cpp = cp;
784
785 ld_preload_done = 1;
786 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
787 *cpp = "";
788 }
789 }
790
791 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000792 if (!ld_preload_done) {
793 int len = ld_preload_len + inject_path_len;
794 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000795 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000796
797 snprintf(cp, len, "%s%s",
798 ld_preload, inject_path);
799
800 ret[envc++] = cp;
801 }
802
sewardjb5f6f512005-03-10 23:59:00 +0000803 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000804 ret[envc] = NULL;
805
806 return ret;
807}
808
809extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000810
811/* Add a string onto the string table, and return its address */
812static char *copy_str(char **tab, const char *str)
813{
814 char *cp = *tab;
815 char *orig = cp;
816
817 while(*str)
818 *cp++ = *str++;
819 *cp++ = '\0';
820
821 if (0)
nethercote545fe672004-11-01 16:52:43 +0000822 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000823
824 *tab = cp;
825
826 return orig;
827}
828
829/*
830 This sets up the client's initial stack, containing the args,
831 environment and aux vector.
832
833 The format of the stack is:
834
835 higher address +-----------------+
836 | Trampoline code |
837 +-----------------+
838 | |
839 : string table :
840 | |
841 +-----------------+
842 | AT_NULL |
843 - -
844 | auxv |
845 +-----------------+
846 | NULL |
847 - -
848 | envp |
849 +-----------------+
850 | NULL |
851 - -
852 | argv |
853 +-----------------+
854 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000855 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000856 | undefined |
857 : :
858 */
nethercotec25c4492004-10-18 11:52:17 +0000859static Addr setup_client_stack(void* init_sp,
860 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000861 const struct exeinfo *info,
862 UInt** client_auxv)
863{
nethercotee567e702004-07-10 17:49:17 +0000864 void* res;
nethercote71980f02004-01-24 18:18:54 +0000865 char **cpp;
866 char *strtab; /* string table */
867 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000868 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000869 struct ume_auxv *auxv;
870 const struct ume_auxv *orig_auxv;
871 const struct ume_auxv *cauxv;
872 unsigned stringsize; /* total size of strings in bytes */
873 unsigned auxsize; /* total size of auxv in bytes */
874 int argc; /* total argc */
875 int envc; /* total number of env vars */
876 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000877 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000878
879 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000880 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000881
882 /* ==================== compute sizes ==================== */
883
884 /* first of all, work out how big the client stack will be */
885 stringsize = 0;
886
887 /* paste on the extra args if the loader needs them (ie, the #!
888 interpreter and its argument) */
889 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000890 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000891 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000892 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000893 }
nethercoted6a56872004-07-26 15:32:47 +0000894 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000895 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000896 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000897 }
898
899 /* now scan the args we're given... */
900 for (cpp = orig_argv; *cpp; cpp++) {
901 argc++;
902 stringsize += strlen(*cpp) + 1;
903 }
904
905 /* ...and the environment */
906 envc = 0;
907 for (cpp = orig_envp; cpp && *cpp; cpp++) {
908 envc++;
909 stringsize += strlen(*cpp) + 1;
910 }
911
912 /* now, how big is the auxv? */
913 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
914 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
915 if (cauxv->a_type == AT_PLATFORM)
916 stringsize += strlen(cauxv->u.a_ptr) + 1;
917 auxsize += sizeof(*cauxv);
918 }
919
920 /* OK, now we know how big the client stack is */
921 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000922 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000923 sizeof(char **)*argc + /* argv */
924 sizeof(char **) + /* terminal NULL */
925 sizeof(char **)*envc + /* envp */
926 sizeof(char **) + /* terminal NULL */
927 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000928 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000929 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000930
sewardj79048ce2005-02-18 08:28:32 +0000931 if (0) VG_(printf)("stacksize = %d\n", stacksize);
932
nethercotef84f6952004-07-15 14:58:33 +0000933 // decide where stack goes!
934 VG_(clstk_end) = VG_(client_end);
935
nethercote73b526f2004-10-31 18:48:21 +0000936 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000937
nethercote71980f02004-01-24 18:18:54 +0000938 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000939 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000940 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
941
nethercote71980f02004-01-24 18:18:54 +0000942 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000943 stringbase = strtab = (char *)(VG_(client_trampoline_code)
944 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000945
946 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000947
sewardj79048ce2005-02-18 08:28:32 +0000948 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000949 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000950 "clstk_base %p\n"
951 "clstk_end %p\n",
952 stringsize, auxsize, stacksize,
953 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000954
nethercote71980f02004-01-24 18:18:54 +0000955 /* ==================== allocate space ==================== */
956
957 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000958 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000959 PROT_READ | PROT_WRITE | PROT_EXEC,
960 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
961 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000962
963 /* ==================== copy client stack ==================== */
964
nethercotea3c3cf22004-11-01 18:38:00 +0000965 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000966
967 /* --- argc --- */
968 *ptr++ = argc; /* client argc */
969
970 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000971 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000972 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000973 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000974 }
nethercoted6a56872004-07-26 15:32:47 +0000975 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000976 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000977 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000978 }
979 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000980 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000981 }
982 *ptr++ = 0;
983
984 /* --- envp --- */
985 VG_(client_envp) = (Char **)ptr;
986 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000987 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000988 *ptr++ = 0;
989
990 /* --- auxv --- */
991 auxv = (struct ume_auxv *)ptr;
992 *client_auxv = (UInt *)auxv;
993
994 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
995 /* copy the entry... */
996 *auxv = *orig_auxv;
997
998 /* ...and fix up the copy */
999 switch(auxv->a_type) {
1000 case AT_PHDR:
1001 if (info->phdr == 0)
1002 auxv->a_type = AT_IGNORE;
1003 else
1004 auxv->u.a_val = info->phdr;
1005 break;
1006
1007 case AT_PHNUM:
1008 if (info->phdr == 0)
1009 auxv->a_type = AT_IGNORE;
1010 else
1011 auxv->u.a_val = info->phnum;
1012 break;
1013
1014 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001015 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001016 break;
1017
1018 case AT_PLATFORM: /* points to a platform description string */
1019 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1020 break;
1021
1022 case AT_ENTRY:
1023 auxv->u.a_val = info->entry;
1024 break;
1025
1026 case AT_IGNORE:
1027 case AT_EXECFD:
1028 case AT_PHENT:
1029 case AT_PAGESZ:
1030 case AT_FLAGS:
1031 case AT_NOTELF:
1032 case AT_UID:
1033 case AT_EUID:
1034 case AT_GID:
1035 case AT_EGID:
1036 case AT_CLKTCK:
1037 case AT_HWCAP:
1038 case AT_FPUCW:
1039 case AT_DCACHEBSIZE:
1040 case AT_ICACHEBSIZE:
1041 case AT_UCACHEBSIZE:
1042 /* All these are pointerless, so we don't need to do anything
1043 about them. */
1044 break;
1045
1046 case AT_SECURE:
1047 /* If this is 1, then it means that this program is running
1048 suid, and therefore the dynamic linker should be careful
1049 about LD_PRELOAD, etc. However, since stage1 (the thing
1050 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001051 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001052 set AT_SECURE to 0. */
1053 auxv->u.a_val = 0;
1054 break;
1055
1056 case AT_SYSINFO:
1057 /* Leave this unmolested for now, but we'll update it later
1058 when we set up the client trampoline code page */
1059 break;
1060
1061 case AT_SYSINFO_EHDR:
1062 /* Trash this, because we don't reproduce it */
1063 auxv->a_type = AT_IGNORE;
1064 break;
1065
1066 default:
1067 /* stomp out anything we don't know about */
1068 if (0)
nethercote545fe672004-11-01 16:52:43 +00001069 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001070 auxv->a_type = AT_IGNORE;
1071 break;
1072
1073 }
1074 }
1075 *auxv = *orig_auxv;
1076 vg_assert(auxv->a_type == AT_NULL);
1077
njnc6168192004-11-29 13:54:10 +00001078// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1079// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001080#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001081 /* --- trampoline page --- */
1082 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1083 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001084#endif
nethercotef84f6952004-07-15 14:58:33 +00001085
nethercote71980f02004-01-24 18:18:54 +00001086 vg_assert((strtab-stringbase) == stringsize);
1087
nethercote5ee67ca2004-06-22 14:00:09 +00001088 /* We know the initial ESP is pointing at argc/argv */
1089 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001090 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001091
sewardj79048ce2005-02-18 08:28:32 +00001092 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001093 return cl_esp;
1094}
1095
1096/*====================================================================*/
1097/*=== Find executable ===*/
1098/*====================================================================*/
1099
thughes4ad52d02004-06-27 17:37:21 +00001100static const char* executable_name;
1101
1102static Bool match_executable(const char *entry) {
1103 char buf[strlen(entry) + strlen(executable_name) + 2];
1104
1105 /* empty PATH element means . */
1106 if (*entry == '\0')
1107 entry = ".";
1108
1109 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1110
1111 if (access(buf, R_OK|X_OK) == 0) {
1112 executable_name = strdup(buf);
1113 vg_assert(NULL != executable_name);
1114 return True;
1115 }
1116 return False;
1117}
1118
nethercote71980f02004-01-24 18:18:54 +00001119static const char* find_executable(const char* exec)
1120{
1121 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001122 executable_name = exec;
1123 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001124 /* no '/' - we need to search the path */
1125 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001126 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001127 }
thughes4ad52d02004-06-27 17:37:21 +00001128 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001129}
1130
1131
1132/*====================================================================*/
1133/*=== Loading tools ===*/
1134/*====================================================================*/
1135
1136static void list_tools(void)
1137{
1138 DIR *dir = opendir(VG_(libdir));
1139 struct dirent *de;
1140 int first = 1;
1141
1142 if (dir == NULL) {
1143 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001144 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001145 return;
1146 }
1147
nethercotef4928da2004-06-15 10:54:40 +00001148 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001149 int len = strlen(de->d_name);
1150
njn063c5402004-11-22 16:58:05 +00001151 /* look for vgtool_TOOL.so names */
1152 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1153 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001154 VG_STREQ(de->d_name + len - 3, ".so")) {
1155 if (first) {
1156 fprintf(stderr, "Available tools:\n");
1157 first = 0;
1158 }
1159 de->d_name[len-3] = '\0';
1160 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001161 }
1162 }
1163
1164 closedir(dir);
1165
1166 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001167 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1168 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001169}
1170
1171
1172/* Find and load a tool, and check it looks ok. Also looks to see if there's
1173 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001174static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001175 ToolInfo** toolinfo_out, char **preloadpath_out )
1176{
1177 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001178 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001179 char buf[len];
1180 void* handle;
1181 ToolInfo* toolinfo;
1182 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001183
1184 // XXX: allowing full paths for --tool option -- does it make sense?
1185 // Doesn't allow for vgpreload_<tool>.so.
1186
1187 if (strchr(toolname, '/') != 0) {
1188 /* toolname contains '/', and so must be a pathname */
1189 handle = dlopen(toolname, RTLD_NOW);
1190 } else {
1191 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001192 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001193 handle = dlopen(buf, RTLD_NOW);
1194
1195 if (handle != NULL) {
1196 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1197 if (access(buf, R_OK) == 0) {
1198 preloadpath = strdup(buf);
1199 vg_assert(NULL != preloadpath);
1200 }
1201 }
1202 }
1203
1204 ok = (NULL != handle);
1205 if (!ok) {
1206 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1207 goto bad_load;
1208 }
1209
njn51d827b2005-05-09 01:02:08 +00001210 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001211 ok = (NULL != toolinfo);
1212 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001213 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001214 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1215 goto bad_load;
1216 }
1217
1218 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001219 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1220 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001221 if (!ok) {
1222 fprintf(stderr, "Error:\n"
1223 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001224 " Interface version used by core is: %d (size %d)\n"
1225 " Interface version used by tool is: %d (size %d)\n"
1226 " The version numbers must match.\n",
1227 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001228 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001229 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001230 toolinfo->sizeof_ToolInfo);
1231 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001232 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001233 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001234 else
nethercote996901a2004-08-03 13:29:09 +00001235 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001236 goto bad_load;
1237 }
1238
njn8a97c6d2005-03-31 04:37:24 +00001239 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001240 *toolinfo_out = toolinfo;
1241 *preloadpath_out = preloadpath;
1242 return;
1243
1244
1245 bad_load:
1246 if (handle != NULL)
1247 dlclose(handle);
1248
nethercotef4928da2004-06-15 10:54:40 +00001249 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001250 list_tools();
1251 exit(127);
1252}
1253
nethercotef4928da2004-06-15 10:54:40 +00001254
1255/*====================================================================*/
1256/*=== Command line errors ===*/
1257/*====================================================================*/
1258
njnbe9b47b2005-05-15 16:22:58 +00001259static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001260{
njnbe9b47b2005-05-15 16:22:58 +00001261 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001262 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001263}
1264
1265void VG_(bad_option) ( Char* opt )
1266{
njnbe9b47b2005-05-15 16:22:58 +00001267 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001268 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1269 VG_(printf)("valgrind: Use --help for more information.\n");
1270 VG_(exit)(1);
1271}
1272
nethercotef4928da2004-06-15 10:54:40 +00001273static void missing_prog ( void )
1274{
njnbe9b47b2005-05-15 16:22:58 +00001275 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001276 VG_(printf)("valgrind: no program specified\n");
1277 VG_(printf)("valgrind: Use --help for more information.\n");
1278 VG_(exit)(1);
1279}
1280
1281static void config_error ( Char* msg )
1282{
njnbe9b47b2005-05-15 16:22:58 +00001283 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001284 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1285 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1286 VG_(exit)(1);
1287}
1288
1289
nethercote71980f02004-01-24 18:18:54 +00001290/*====================================================================*/
1291/*=== Loading the client ===*/
1292/*====================================================================*/
1293
nethercotef4928da2004-06-15 10:54:40 +00001294static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001295 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1296{
1297 // If they didn't specify an executable with --exec, and didn't specify
1298 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001299 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001300 if (cl_argv[0] == NULL ||
1301 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1302 {
nethercotef4928da2004-06-15 10:54:40 +00001303 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001304 }
1305 }
1306
1307 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001308 info->exe_base = VG_(client_base);
1309 info->exe_end = VG_(client_end);
1310 info->argv = cl_argv;
1311
nethercotef4928da2004-06-15 10:54:40 +00001312 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001313 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001314 // Totally zero 'info' before continuing.
1315 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001316 } else {
1317 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001318 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001319 ret = do_exec(exec, info);
1320 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001321 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1322 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001323 exit(127);
1324 }
1325 }
1326
1327 /* Copy necessary bits of 'info' that were filled in */
1328 *client_eip = info->init_eip;
1329 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1330}
1331
nethercote969ecf12004-10-13 17:29:01 +00001332/*====================================================================*/
1333/*=== Address space unpadding ===*/
1334/*====================================================================*/
1335
1336typedef struct {
1337 char* killpad_start;
1338 char* killpad_end;
1339 struct stat* killpad_padstat;
1340} killpad_extra;
1341
1342static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1343 int maj, int min, int ino, void* ex)
1344{
1345 killpad_extra* extra = ex;
1346 void *b, *e;
1347 int res;
1348
1349 vg_assert(NULL != extra->killpad_padstat);
1350
1351 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1352 extra->killpad_padstat->st_ino != ino)
1353 return 1;
1354
1355 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1356 return 1;
1357
1358 if (segstart <= extra->killpad_start)
1359 b = extra->killpad_start;
1360 else
1361 b = segstart;
1362
1363 if (segend >= extra->killpad_end)
1364 e = extra->killpad_end;
1365 else
1366 e = segend;
1367
1368 res = munmap(b, (char *)e-(char *)b);
1369 vg_assert(0 == res);
1370
1371 return 1;
1372}
1373
1374// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001375static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001376{
1377 static struct stat padstat;
1378 killpad_extra extra;
1379 int res;
1380
sewardjb5f6f512005-03-10 23:59:00 +00001381 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001382
1383 res = fstat(padfile, &padstat);
1384 vg_assert(0 == res);
1385 extra.killpad_padstat = &padstat;
1386 extra.killpad_start = start;
1387 extra.killpad_end = end;
1388 foreach_map(killpad, &extra);
1389}
1390
sewardj2c5ffbe2005-03-12 13:32:06 +00001391static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001392{
1393 int res = close(padfile);
1394 vg_assert(0 == res);
1395}
1396
nethercote71980f02004-01-24 18:18:54 +00001397
1398/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001399/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001400/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001401
njn25e49d8e72002-09-23 09:36:25 +00001402/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001403VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001404Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001405Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001406Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001407Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001408Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001409Int VG_(clo_verbosity) = 1;
1410Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001411Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001412
njnbe9b47b2005-05-15 16:22:58 +00001413/* See big comment in core.h for meaning of these two. */
1414Int VG_(clo_log_fd) = 2;
nethercotef8548672004-06-21 12:42:35 +00001415Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001416
thughes6233a382004-08-21 11:10:44 +00001417Bool VG_(clo_time_stamp) = False;
1418
sewardj6024b212003-07-13 10:54:33 +00001419Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001420Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001421Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001422Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001423UChar VG_(clo_trace_flags) = 0; // 00000000b
1424UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001425Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001426Bool VG_(clo_trace_syscalls) = False;
1427Bool VG_(clo_trace_signals) = False;
1428Bool VG_(clo_trace_symtab) = False;
sewardjce058b02005-05-01 08:55:38 +00001429Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001430Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001431Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001432Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001433Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001434Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001435Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001436Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001437Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001438Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001439Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001440Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001441Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001442Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001443Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001444Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001445
jsgf855d93d2003-10-13 22:26:55 +00001446static Bool VG_(clo_wait_for_gdb) = False;
1447
sewardjde4a1d02002-03-22 01:27:54 +00001448
sewardj2c5ffbe2005-03-12 13:32:06 +00001449static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001450{
njn25e49d8e72002-09-23 09:36:25 +00001451 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001452"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001453"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001454" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001455" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001456" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001457" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001458" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001459" -q --quiet run silently; only print error msgs\n"
1460" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001461" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001462" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001463" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001464"\n"
1465" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001466" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001467" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001468" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001469" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001470" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001471"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001472" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001473" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1474" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001475" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001476" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001478" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001479" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1480" --show-below-main=no|yes continue stack traces below main() [no]\n"
1481" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001482" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001483" --db-attach=no|yes start debugger when errors detected? [no]\n"
1484" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1485" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001486" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1487" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001488"\n";
njn7cf0bd32002-06-08 13:36:03 +00001489
njn25e49d8e72002-09-23 09:36:25 +00001490 Char* usage2 =
1491"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001492" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001493" --sanity-level=<number> level of sanity checking to do [1]\n"
1494" --single-step=no|yes translate each instr separately? [no]\n"
1495" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001496" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001497" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001498" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1499" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001500" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001501" --trace-syscalls=no|yes show all system calls? [no]\n"
1502" --trace-signals=no|yes show signal handling details? [no]\n"
1503" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001504" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001505" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001506" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001507#if 0
1508" --model-pthreads=yes|no model the pthreads library [no]\n"
1509#endif
1510" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001511"\n"
1512" --vex-iropt-verbosity 0 .. 9 [0]\n"
1513" --vex-iropt-level 0 .. 2 [2]\n"
1514" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001515" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1516" --vex-guest-max-insns 1 .. 100 [50]\n"
1517" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1518"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001519" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001520" 1000 0000 show conversion into IR\n"
1521" 0100 0000 show after initial opt\n"
1522" 0010 0000 show after instrumentation\n"
1523" 0001 0000 show after second opt\n"
1524" 0000 1000 show after tree building\n"
1525" 0000 0100 show selecting insns\n"
1526" 0000 0010 show after reg-alloc\n"
1527" 0000 0001 show final assembly\n"
1528"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001529" debugging options for Valgrind tools that report errors\n"
1530" --dump-error=<number> show translation for basic block associated\n"
1531" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001532"\n";
njn3e884182003-04-15 13:03:23 +00001533
1534 Char* usage3 =
1535"\n"
nethercote71980f02004-01-24 18:18:54 +00001536" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001537"\n"
njn53612422005-03-12 16:22:54 +00001538" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001539" and licensed under the GNU General Public License, version 2.\n"
1540" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001541"\n"
nethercote137bc552003-11-14 17:47:54 +00001542" Tools are copyright and licensed by their authors. See each\n"
1543" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001544"\n";
njn7cf0bd32002-06-08 13:36:03 +00001545
njnbe9b47b2005-05-15 16:22:58 +00001546 // Ensure the message goes to stdout
1547 VG_(clo_log_fd) = 1;
1548 vg_assert( !VG_(logging_to_socket) );
1549
fitzhardinge98abfc72003-12-16 02:05:15 +00001550 VG_(printf)(usage1);
1551 if (VG_(details).name) {
1552 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001553 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001554 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001555 else
1556 VG_(printf)(" (none)\n");
1557 }
nethercote6c999f22004-01-31 22:55:15 +00001558 if (debug_help) {
1559 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001560
nethercote6c999f22004-01-31 22:55:15 +00001561 if (VG_(details).name) {
1562 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1563
1564 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001565 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001566 else
1567 VG_(printf)(" (none)\n");
1568 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001569 }
nethercote421281e2003-11-20 16:20:55 +00001570 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001571 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001572}
sewardjde4a1d02002-03-22 01:27:54 +00001573
nethercote71980f02004-01-24 18:18:54 +00001574static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001575 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001576{
nethercote71980f02004-01-24 18:18:54 +00001577 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001578
sewardj8b635a42004-11-22 19:01:47 +00001579 LibVEX_default_VexControl(& VG_(clo_vex_control));
1580
nethercote71980f02004-01-24 18:18:54 +00001581 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001582 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001583
nethercotef6a1d502004-08-09 12:21:57 +00001584 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001585 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001586 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1589 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001590 *need_help = 1;
1591
nethercotef6a1d502004-08-09 12:21:57 +00001592 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001593 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001594
nethercotef6c99d72004-11-09 14:35:43 +00001595 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001596 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001597
nethercotef6a1d502004-08-09 12:21:57 +00001598 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1599 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001600 }
1601 }
nethercote71980f02004-01-24 18:18:54 +00001602}
1603
nethercote5ee67ca2004-06-22 14:00:09 +00001604static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001605{
nethercotef8548672004-06-21 12:42:35 +00001606 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001607 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001608 enum {
1609 VgLogTo_Fd,
1610 VgLogTo_File,
1611 VgLogTo_FileExactly,
1612 VgLogTo_Socket
1613 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001614
nethercotee1730692003-11-20 10:38:07 +00001615 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001616 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001617
sewardj19d81412002-06-03 01:10:40 +00001618 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001619 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001620 config_error("Please use absolute paths in "
1621 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001622
njnc6168192004-11-29 13:54:10 +00001623// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001624#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001625 {
sewardjb5f6f512005-03-10 23:59:00 +00001626 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001627 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1628 switch(auxp[0]) {
1629 case AT_SYSINFO:
1630 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1631 break;
1632 }
1633 }
1634 }
1635#endif
sewardjde4a1d02002-03-22 01:27:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001640 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001641
thughes3bfd5a02004-07-18 08:05:44 +00001642 /* Look for a colon in the switch name */
1643 while (*colon && *colon != ':' && *colon != '=')
1644 colon++;
nethercote71980f02004-01-24 18:18:54 +00001645
1646 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001647 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001648 if (VG_CLO_STREQN(2, arg, "--") &&
1649 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1650 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1651 {
1652 // prefix matches, convert "--toolname:foo" to "--foo"
1653 if (0)
1654 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001655 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001656 arg[0] = '-';
1657 arg[1] = '-';
1658
1659 } else {
1660 // prefix doesn't match, skip to next arg
1661 continue;
1662 }
1663 }
1664
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001666 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1667 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1668 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001669
njn45270a22005-03-27 01:00:11 +00001670 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001671
nethercote71980f02004-01-24 18:18:54 +00001672 else if (VG_CLO_STREQ(arg, "-v") ||
1673 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001674 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001675
nethercote71980f02004-01-24 18:18:54 +00001676 else if (VG_CLO_STREQ(arg, "-q") ||
1677 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001678 VG_(clo_verbosity)--;
1679
sewardj1cf558c2005-04-25 01:36:56 +00001680 else if (VG_CLO_STREQ(arg, "-d")) {
1681 /* do nothing */
1682 }
1683
njn45270a22005-03-27 01:00:11 +00001684 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1685 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1686 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1687 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1688 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1689 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1690 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001691 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001692 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1693 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1694 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1695 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1696 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1697 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1698 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1699 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1700 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001701 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001702 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1703 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1704 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1705 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1706 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001707
njn45270a22005-03-27 01:00:11 +00001708 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1709 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001710
njn45270a22005-03-27 01:00:11 +00001711 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1712 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1713 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1714 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1715 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001716
njn45270a22005-03-27 01:00:11 +00001717 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001718 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001719 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001720 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001721 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001722 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001723 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001724 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001725 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001726 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001727 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001728 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1729
nethercotef8548672004-06-21 12:42:35 +00001730 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001731 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001732 VG_(clo_log_name) = NULL;
1733 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001734 }
1735
nethercotef8548672004-06-21 12:42:35 +00001736 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001737 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001738 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001739 }
njnd6bc3c32005-03-27 00:44:31 +00001740
sewardj603d4102005-01-11 14:01:02 +00001741 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001742 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001743 VG_(clo_log_name) = &arg[19];
1744 }
sewardjde4a1d02002-03-22 01:27:54 +00001745
nethercotef8548672004-06-21 12:42:35 +00001746 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001747 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001748 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001749 }
1750
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001752 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001753 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001754 VG_(message)(Vg_UserMsg,
1755 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001756 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001757 }
nethercote71980f02004-01-24 18:18:54 +00001758 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001759 VG_(clo_n_suppressions)++;
1760 }
sewardjde4a1d02002-03-22 01:27:54 +00001761
sewardjfa8ec112005-01-19 11:55:34 +00001762 /* "stuvwxyz" --> stuvwxyz (binary) */
1763 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1764 Int j;
1765 char* opt = & arg[14];
1766
1767 if (8 != VG_(strlen)(opt)) {
1768 VG_(message)(Vg_UserMsg,
1769 "--trace-flags argument must have 8 digits");
1770 VG_(bad_option)(arg);
1771 }
1772 for (j = 0; j < 8; j++) {
1773 if ('0' == opt[j]) { /* do nothing */ }
1774 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1775 else {
1776 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1777 "contain 0s and 1s");
1778 VG_(bad_option)(arg);
1779 }
1780 }
1781 }
1782
1783 /* "stuvwxyz" --> stuvwxyz (binary) */
1784 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001785 Int j;
nethercote71980f02004-01-24 18:18:54 +00001786 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001787
sewardj2a99cf62004-11-24 10:44:19 +00001788 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001789 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001790 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001791 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001792 }
sewardj8b635a42004-11-22 19:01:47 +00001793 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001794 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001795 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001796 else {
sewardjfa8ec112005-01-19 11:55:34 +00001797 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001798 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001799 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001800 }
1801 }
1802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
njn45270a22005-03-27 01:00:11 +00001804 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001805
sewardjd153fae2005-01-10 17:24:47 +00001806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1807 VG_(clo_gen_suppressions) = 0;
1808 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1809 VG_(clo_gen_suppressions) = 1;
1810 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1811 VG_(clo_gen_suppressions) = 2;
1812
nethercote71980f02004-01-24 18:18:54 +00001813 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001814 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
njn8c0b3bb2005-03-12 21:20:39 +00001817 skip_arg:
1818 if (arg != vg_argv[i])
1819 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
1821
sewardj998d40d2004-12-06 14:24:52 +00001822 /* Make VEX control parameters sane */
1823
1824 if (VG_(clo_vex_control).guest_chase_thresh
1825 >= VG_(clo_vex_control).guest_max_insns)
1826 VG_(clo_vex_control).guest_chase_thresh
1827 = VG_(clo_vex_control).guest_max_insns - 1;
1828
1829 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1830 VG_(clo_vex_control).guest_chase_thresh = 0;
1831
1832 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001833
njnf9ebf672003-05-12 21:41:30 +00001834 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001835 VG_(clo_verbosity) = 0;
1836
nethercote04d0fbc2004-01-26 16:48:06 +00001837 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001838 VG_(message)(Vg_UserMsg, "");
1839 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001840 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(message)(Vg_UserMsg,
1842 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001843 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001844 }
1845
njnbe9b47b2005-05-15 16:22:58 +00001846 if (VG_(clo_gen_suppressions) > 0 &&
1847 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1848 VG_(message)(Vg_UserMsg,
1849 "Can't use --gen-suppressions= with this tool,");
1850 VG_(message)(Vg_UserMsg,
1851 "as it doesn't generate errors.");
1852 VG_(bad_option)("--gen-suppressions=");
1853 }
1854
1855 /* All non-logging-related options have been checked. If the logging
1856 option specified is ok, we can switch to it, as we know we won't
1857 have to generate any other command-line-related error messages.
1858 (So far we should be still attached to stderr, so we can show on
1859 the terminal any problems to do with processing command line
1860 opts.)
1861
1862 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001863 should be connected to whatever sink has been selected, and we
1864 indiscriminately chuck stuff into it without worrying what the
1865 nature of it is. Oh the wonder of Unix streams. */
1866
njnbe9b47b2005-05-15 16:22:58 +00001867 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1868 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001869
njnbe9b47b2005-05-15 16:22:58 +00001870 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001871
sewardj4cf05692002-10-27 20:28:29 +00001872 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001873 vg_assert(VG_(clo_log_name) == NULL);
1874 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001875 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001876
sewardj4cf05692002-10-27 20:28:29 +00001877 case VgLogTo_File: {
1878 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001879 Int seq = 0;
1880 Int pid = VG_(getpid)();
1881
nethercotef8548672004-06-21 12:42:35 +00001882 vg_assert(VG_(clo_log_name) != NULL);
1883 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001884
nethercote71980f02004-01-24 18:18:54 +00001885 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001886 if (seq == 0)
1887 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001888 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001889 else
1890 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001891 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001892 seq++;
1893
njnbe9b47b2005-05-15 16:22:58 +00001894 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001895 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001896 = VG_(open)(logfilename,
1897 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1898 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001899 if (eventually_log_fd >= 0) {
1900 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001901 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001902 } else {
njnbe9b47b2005-05-15 16:22:58 +00001903 // If the file already existed, we try the next name. If it
1904 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001905 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001906 VG_(message)(Vg_UserMsg,
1907 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001908 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001909 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001910 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001911 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001912 }
1913 }
1914 }
sewardj603d4102005-01-11 14:01:02 +00001915 break; /* switch (VG_(clo_log_to)) */
1916 }
1917
1918 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001919 vg_assert(VG_(clo_log_name) != NULL);
1920 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001921
1922 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001923 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001924 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1925 VKI_S_IRUSR|VKI_S_IWUSR);
1926 if (eventually_log_fd >= 0) {
1927 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001928 } else {
sewardj603d4102005-01-11 14:01:02 +00001929 VG_(message)(Vg_UserMsg,
1930 "Can't create/open log file `%s'; giving up!",
1931 VG_(clo_log_name));
1932 VG_(bad_option)(
1933 "--log-file-exactly=<file> (didn't work out for some reason.)");
1934 /*NOTREACHED*/
1935 }
1936 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001937 }
1938
1939 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001940 vg_assert(VG_(clo_log_name) != NULL);
1941 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1942 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1943 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001944 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001945 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001946 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001947 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001948 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001949 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001950 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001951 }
nethercotef8548672004-06-21 12:42:35 +00001952 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001953 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001954 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001955 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001956 VG_(message)(Vg_UserMsg,
1957 "Log messages will sent to stderr instead." );
1958 VG_(message)(Vg_UserMsg,
1959 "" );
1960 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001961 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001962 } else {
nethercotef8548672004-06-21 12:42:35 +00001963 vg_assert(eventually_log_fd > 0);
1964 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001965 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001966 }
sewardj73cf3bc2002-11-03 03:20:15 +00001967 break;
1968 }
sewardj4cf05692002-10-27 20:28:29 +00001969 }
1970
njnbe9b47b2005-05-15 16:22:58 +00001971 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1972 // XXX: this is more or less duplicating the behaviour of the calls to
1973 // VG_(safe_fd)() above, although this does not close the original fd.
1974 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1975 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001976 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001977 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001978 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1979 else {
nethercotef8548672004-06-21 12:42:35 +00001980 VG_(clo_log_fd) = eventually_log_fd;
1981 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001982 }
1983
sewardj4cf05692002-10-27 20:28:29 +00001984 /* Ok, the logging sink is running now. Print a suitable preamble.
1985 If logging to file or a socket, write details of parent PID and
1986 command line args, to help people trying to interpret the
1987 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001988
sewardj83adf412002-05-01 01:25:45 +00001989 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001990 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001991 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001992 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001993 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001994 NULL == VG_(details).version
1995 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001996 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001997 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001998
njnd04b7c62002-10-03 14:05:52 +00001999 /* Core details */
2000 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00002001 "Using LibVEX rev %s, a library for dynamic binary translation.",
2002 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00002003 VG_(message)(Vg_UserMsg,
2004 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2005 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002006 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002007 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002008 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002009 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002010 }
2011
njnbe9b47b2005-05-15 16:22:58 +00002012 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002013 VG_(message)(Vg_UserMsg, "");
2014 VG_(message)(Vg_UserMsg,
2015 "My PID = %d, parent PID = %d. Prog and args are:",
2016 VG_(getpid)(), VG_(getppid)() );
2017 for (i = 0; i < VG_(client_argc); i++)
2018 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2019 }
2020
sewardjde4a1d02002-03-22 01:27:54 +00002021 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002022 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00002023 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002024 VG_(message)(Vg_DebugMsg, "");
2025 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2026 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002027 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002028 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002029
njn1fd5eb22005-03-13 05:43:23 +00002030 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002031 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002032 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002033 }
nethercotea70f7352004-04-18 12:08:46 +00002034
njn1fd5eb22005-03-13 05:43:23 +00002035 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002036 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2037 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002038 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002039 } else {
2040 #define BUF_LEN 256
2041 Char version_buf[BUF_LEN];
2042 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002043 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002044 if (n > 0) {
2045 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002046 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002047 } else {
njn1fd5eb22005-03-13 05:43:23 +00002048 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002049 }
2050 VG_(close)(fd);
2051 #undef BUF_LEN
2052 }
sewardjde4a1d02002-03-22 01:27:54 +00002053 }
2054
fitzhardinge98abfc72003-12-16 02:05:15 +00002055 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002056 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002057 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002058 needs one, load the default */
2059 static const Char default_supp[] = "default.supp";
2060 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2061 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2062 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2063 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2064 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002065 }
2066}
2067
nethercotef6a1d502004-08-09 12:21:57 +00002068// Build the string for VALGRINDCLO.
2069Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2070{
2071 /* If we're tracing the children, then we need to start it
2072 with our starter+arguments, which are copied into VALGRINDCLO,
2073 except the --exec= option is changed if present.
2074 */
2075 Int i;
2076 Char *exec;
2077 Char *cp;
2078 Char *optvar;
2079 Int optlen, execlen;
2080
2081 // All these allocated blocks are not free - because we're either
2082 // going to exec, or panic when we fail.
2083
2084 // Create --exec= option: "--exec=<exename>"
2085 exec = VG_(arena_malloc)(VG_AR_CORE,
2086 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2087 vg_assert(NULL != exec);
2088 VG_(sprintf)(exec, "--exec=%s", exename);
2089
2090 // Allocate space for optvar (may overestimate by counting --exec twice,
2091 // no matter)
2092 optlen = 1;
2093 for (i = 0; i < vg_argc; i++)
2094 optlen += VG_(strlen)(vg_argv[i]) + 1;
2095 optlen += VG_(strlen)(exec)+1;
2096 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2097
2098 // Copy all valgrind args except the old --exec (if present)
2099 // VG_CLO_SEP is the separator.
2100 cp = optvar;
2101 for (i = 1; i < vg_argc; i++) {
2102 Char *arg = vg_argv[i];
2103
2104 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2105 // don't copy existing --exec= arg
2106 } else if (VG_(strcmp)(arg, "--") == 0) {
2107 // stop at "--"
2108 break;
2109 } else {
2110 // copy non "--exec" arg
2111 Int len = VG_(strlen)(arg);
2112 VG_(memcpy)(cp, arg, len);
2113 cp += len;
2114 *cp++ = VG_CLO_SEP;
2115 }
2116 }
2117 // Add the new --exec= option
2118 execlen = VG_(strlen)(exec);
2119 VG_(memcpy)(cp, exec, execlen);
2120 cp += execlen;
2121 *cp++ = VG_CLO_SEP;
2122
2123 *cp = '\0';
2124
2125 return optvar;
2126}
2127
2128// Build "/proc/self/fd/<execfd>".
2129Char* VG_(build_child_exename)( void )
2130{
2131 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2132 vg_assert(NULL != exename);
2133 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2134 return exename;
2135}
2136
sewardjde4a1d02002-03-22 01:27:54 +00002137
nethercote71980f02004-01-24 18:18:54 +00002138/*====================================================================*/
2139/*=== File descriptor setup ===*/
2140/*====================================================================*/
2141
2142static void setup_file_descriptors(void)
2143{
2144 struct vki_rlimit rl;
2145
2146 /* Get the current file descriptor limits. */
2147 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2148 rl.rlim_cur = 1024;
2149 rl.rlim_max = 1024;
2150 }
2151
2152 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002153 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2154 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002155 } else {
2156 rl.rlim_cur = rl.rlim_max;
2157 }
2158
2159 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002160 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2161 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002162
2163 /* Update the soft limit. */
2164 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2165
nethercotef6a1d502004-08-09 12:21:57 +00002166 if (vgexecfd != -1)
2167 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002168 if (VG_(clexecfd) != -1)
2169 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2170}
2171
nethercote71980f02004-01-24 18:18:54 +00002172/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002173/*=== Initialise program data/text, etc. ===*/
2174/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002175
sewardjb5f6f512005-03-10 23:59:00 +00002176static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2177 UInt dev, UInt ino, ULong foffset,
2178 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002179{
nethercote71980f02004-01-24 18:18:54 +00002180 /* Only record valgrind mappings for now, without loading any
2181 symbols. This is so we know where the free space is before we
2182 start allocating more memory (note: heap is OK, it's just mmap
2183 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002184 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002185 VG_(debugLog)(2, "main",
2186 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002187 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002188 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002189 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2190 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002191 /* update VG_(valgrind_last) if it looks wrong */
2192 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002193 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002194 }
sewardjde4a1d02002-03-22 01:27:54 +00002195}
2196
nethercote71980f02004-01-24 18:18:54 +00002197// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002198Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002199
sewardjb5f6f512005-03-10 23:59:00 +00002200/*
2201 This second pass adds in client mappings, and loads symbol tables
2202 for all interesting mappings. The trouble is that things can
2203 change as we go, because we're calling the Tool to track memory as
2204 we find it.
2205
2206 So for Valgrind mappings, we don't replace any mappings which
2207 aren't still identical (which will include the .so mappings, so we
2208 will load their symtabs)>
2209 */
2210static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2211 UInt dev, UInt ino, ULong foffset,
2212 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002213{
nethercote71980f02004-01-24 18:18:54 +00002214 UInt flags;
2215 Bool is_stack_segment;
2216 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002217
nethercote71980f02004-01-24 18:18:54 +00002218 is_stack_segment
2219 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002220
sewardj8c615892005-04-25 02:38:28 +00002221 VG_(debugLog)(2, "main",
2222 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002223 (void*)start, (void*)(start+size), prot, is_stack_segment,
2224 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002225
nethercote71980f02004-01-24 18:18:54 +00002226 if (is_stack_segment)
2227 flags = SF_STACK | SF_GROWDOWN;
2228 else
2229 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002230
nethercote71980f02004-01-24 18:18:54 +00002231 if (filename != NULL)
2232 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002233
sewardjb5f6f512005-03-10 23:59:00 +00002234#if 0
2235 // This needs to be fixed properly. jrs 20050307
2236 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2237 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002238
sewardjb5f6f512005-03-10 23:59:00 +00002239 /* We have to be a bit careful about inserting new mappings into
2240 the Valgrind part of the address space. We're actively
2241 changing things as we parse these mappings, particularly in
2242 shadow memory, and so we don't want to overwrite those
2243 changes. Therefore, we only insert/update a mapping if it is
2244 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002245
sewardjb5f6f512005-03-10 23:59:00 +00002246 NOTE: we're only talking about the Segment list mapping
2247 metadata; this doesn't actually mmap anything more. */
2248 if (filename || (s && s->addr == start && s->len == size)) {
2249 flags |= SF_VALGRIND;
2250 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2251 } else {
2252 /* assert range is already mapped */
2253 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2254 }
2255 } else
2256#endif
2257 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2258
2259 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2260 VG_TRACK( new_mem_startup, start, size,
2261 !!(prot & VKI_PROT_READ),
2262 !!(prot & VKI_PROT_WRITE),
2263 !!(prot & VKI_PROT_EXEC));
2264 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002265
nethercote71980f02004-01-24 18:18:54 +00002266 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002267 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002268 vg_assert(0 != r_esp);
2269 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002270 if (0) {
2271 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002272 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002273 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2274 r_esp, start+size);
2275 }
nethercote71980f02004-01-24 18:18:54 +00002276 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002277 // what's this for?
2278 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002279 }
sewardjde4a1d02002-03-22 01:27:54 +00002280}
2281
2282
nethercote71980f02004-01-24 18:18:54 +00002283/*====================================================================*/
2284/*=== Sanity check machinery (permanently engaged) ===*/
2285/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002286
2287/* A fast sanity check -- suitable for calling circa once per
2288 millisecond. */
2289
nethercote885dd912004-08-03 23:14:00 +00002290void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002291{
sewardjb5f6f512005-03-10 23:59:00 +00002292 ThreadId tid;
2293
njn37cea302002-09-30 11:24:00 +00002294 VGP_PUSHCC(VgpCoreCheapSanity);
2295
nethercote27fec902004-06-16 21:26:32 +00002296 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002297
2298 /* --- First do all the tests that we can do quickly. ---*/
2299
nethercote297effd2004-08-02 15:07:57 +00002300 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002301
njn25e49d8e72002-09-23 09:36:25 +00002302 /* Check stuff pertaining to the memory check system. */
2303
2304 /* Check that nobody has spuriously claimed that the first or
2305 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002306 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002307 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002308 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002309 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002310 }
njn25e49d8e72002-09-23 09:36:25 +00002311
2312 /* --- Now some more expensive checks. ---*/
2313
2314 /* Once every 25 times, check some more expensive stuff. */
2315 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002316 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002317 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002318
njn37cea302002-09-30 11:24:00 +00002319 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002320 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002321
2322# if 0
2323 { void zzzmemscan(void); zzzmemscan(); }
2324# endif
2325
nethercote297effd2004-08-02 15:07:57 +00002326 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002327 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002328
2329 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002330 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002331 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002332 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002333 }
sewardjb5f6f512005-03-10 23:59:00 +00002334
2335 /* Check that Segments and /proc/self/maps match up */
2336 //vg_assert(VG_(sanity_check_memory)());
2337
2338 /* Look for stack overruns. Visit all threads. */
2339 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002340 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002341
2342 if (VG_(threads)[tid].status == VgTs_Empty ||
2343 VG_(threads)[tid].status == VgTs_Zombie)
2344 continue;
2345
2346 remains = VGA_(stack_unused)(tid);
2347 if (remains < VKI_PAGE_SIZE)
2348 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2349 tid, remains);
2350 }
2351
njn25e49d8e72002-09-23 09:36:25 +00002352 /*
nethercote297effd2004-08-02 15:07:57 +00002353 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002354 */
njn37cea302002-09-30 11:24:00 +00002355 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002356 }
2357
nethercote27fec902004-06-16 21:26:32 +00002358 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002359 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002360 /* Check sanity of the low-level memory manager. Note that bugs
2361 in the client's code can cause this to fail, so we don't do
2362 this check unless specially asked for. And because it's
2363 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002364 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002365 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002366 }
njn37cea302002-09-30 11:24:00 +00002367 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002368}
nethercote71980f02004-01-24 18:18:54 +00002369
2370
2371/*====================================================================*/
2372/*=== main() ===*/
2373/*====================================================================*/
2374
nethercotec314eba2004-07-15 12:59:41 +00002375/*
2376 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002377 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002378 loads the client executable (and the dynamic linker, if necessary)
2379 into the client part, and calls into Valgrind proper.
2380
2381 The code is careful not to allow spurious mappings to appear in the
2382 wrong parts of the address space. In particular, to make sure
2383 dlopen puts things in the right place, it will pad out the forbidden
2384 chunks of address space so that dlopen is forced to put things where
2385 we want them.
2386
2387 The memory map it creates is:
2388
njn80950732005-03-26 00:18:45 +00002389 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002390 | client address space |
2391 : :
2392 : :
2393 | client stack |
2394 client_end +-------------------------+
2395 | redzone |
2396 shadow_base +-------------------------+
2397 | |
nethercote996901a2004-08-03 13:29:09 +00002398 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002399 | (may be 0 sized) |
2400 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002401 valgrind_base +-------------------------+
2402 | kickstart executable |
2403 | valgrind heap vvvvvvvvv| (barely used)
2404 - -
2405 | valgrind .so files |
2406 | and mappings |
2407 - -
2408 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002409 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002410 : kernel :
2411
2412 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2413 VG_(mmap)(), we need to build the segment skip-list, so we know where
2414 we can put things. However, building that structure requires
2415 allocating memory. So we need to a bootstrapping process. It's done
2416 by making VG_(arena_malloc)() have a special static superblock that's
2417 used for the first 1MB's worth of allocations. This is enough to
2418 build the segment skip-list.
2419*/
2420
thughes4ad52d02004-06-27 17:37:21 +00002421
sewardj1cf558c2005-04-25 01:36:56 +00002422/* This may be needed before m_mylibc is OK to run. */
2423static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2424{
2425 while (True) {
2426 if (*s1 == 0 && *s2 == 0) return 0;
2427 if (*s1 == 0) return -1;
2428 if (*s2 == 0) return 1;
2429
2430 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2431 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2432
2433 s1++; s2++;
2434 }
2435}
2436
2437
sewardjb5f6f512005-03-10 23:59:00 +00002438int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002439{
2440 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002441 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002442 const char *exec = NULL;
2443 char *preload; /* tool-specific LD_PRELOAD .so */
2444 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002445 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002446 struct exeinfo info;
2447 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002448 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002449 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002450 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002451 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002452 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002453
2454 //============================================================
2455 // Nb: startup is complex. Prerequisites are shown at every step.
2456 //
2457 // *** Be very careful when messing with the order ***
2458 //============================================================
2459
sewardj1cf558c2005-04-25 01:36:56 +00002460 //--------------------------------------------------------------
2461 // Start up the logging mechanism
2462 // p: none
2463 //--------------------------------------------------------------
2464 /* Start the debugging-log system ASAP. First find out how many
2465 "-d"s were specified. This is a pre-scan of the command line. */
2466 loglevel = 0;
2467 for (i = 1; i < argc; i++) {
2468 if (argv[i][0] != '-')
2469 break;
2470 if (0 == local_strcmp(argv[i], "--"))
2471 break;
2472 if (0 == local_strcmp(argv[i], "-d"))
2473 loglevel++;
2474 }
2475
2476 /* ... and start the debug logger. Now we can safely emit logging
2477 messages all through startup. */
2478 VG_(debugLog_startup)(loglevel, "Stage 2");
2479
nethercotef4928da2004-06-15 10:54:40 +00002480 //============================================================
2481 // Command line argument handling order:
2482 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002483 // (including the tool-specific usage)
2484 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002485 // * Then, if client is missing, abort with error msg
2486 // * Then, if any cmdline args are bad, abort with error msg
2487 //============================================================
2488
fitzhardingeb50068f2004-02-24 23:42:55 +00002489 // Get the current process datasize rlimit, and set it to zero.
2490 // This prevents any internal uses of brk() from having any effect.
2491 // We remember the old value so we can restore it on exec, so that
2492 // child processes will have a reasonable brk value.
2493 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2494 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2495 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002496
2497 // Get the current process stack rlimit.
2498 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2499
nethercote71980f02004-01-24 18:18:54 +00002500 //--------------------------------------------------------------
2501 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002502 // p: none
nethercote71980f02004-01-24 18:18:54 +00002503 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002504 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002505 {
sewardj1fbc1a52005-04-25 02:05:54 +00002506 void* init_sp = argv - 1;
2507 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002508 }
2509
2510 //--------------------------------------------------------------
2511 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002512 // p: none
nethercote71980f02004-01-24 18:18:54 +00002513 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002514 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002515 if (cp != NULL)
2516 VG_(libdir) = cp;
2517 }
2518
2519 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002520 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2521 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002522 // p: none
nethercote71980f02004-01-24 18:18:54 +00002523 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002524 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002525 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002526 pre_process_cmd_line_options(&need_help, &tool, &exec);
2527
2528 //==============================================================
2529 // Nb: once a tool is specified, the tool.so must be loaded even if
2530 // they specified --help or didn't specify a client program.
2531 //==============================================================
2532
2533 //--------------------------------------------------------------
2534 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002535 // p: set-libdir [for VG_(libdir)]
2536 // p: pre_process_cmd_line_options() [for 'tool']
2537 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002539 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002540
2541 //==============================================================
2542 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002543 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002544 //==============================================================
2545
2546 //--------------------------------------------------------------
2547 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002548 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002549 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002550 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002551 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002552
2553 //--------------------------------------------------------------
2554 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002555 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2556 // p: layout_remaining_space [so there's space]
2557 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002558 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002559 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002560
2561 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002562 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002563 // p: layout_remaining_space() [everything must be mapped in before now]
2564 // p: load_client() [ditto]
2565 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002566 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2567 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002568
2569 //--------------------------------------------------------------
2570 // Set up client's environment
2571 // p: set-libdir [for VG_(libdir)]
2572 // p: load_tool() [for 'preload']
2573 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002574 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002575 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002576
2577 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002578 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002579 // p: load_client() [for 'info']
2580 // p: fix_environment() [for 'env']
2581 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002582 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002583 {
sewardj1fbc1a52005-04-25 02:05:54 +00002584 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002585
sewardj1fbc1a52005-04-25 02:05:54 +00002586 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2587 &client_auxv);
2588 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002589 }
nethercote71980f02004-01-24 18:18:54 +00002590
sewardj1fbc1a52005-04-25 02:05:54 +00002591 VG_(debugLog)(2, "main",
2592 "Client info: "
2593 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2594 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2595 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002596
2597 //==============================================================
2598 // Finished setting up operating environment. Now initialise
2599 // Valgrind. (This is where the old VG_(main)() started.)
2600 //==============================================================
2601
2602 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002603 // setup file descriptors
2604 // p: n/a
2605 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002606 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002607 setup_file_descriptors();
2608
2609 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002610 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002611 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002612 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002613 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002614 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2615
2616 //==============================================================
2617 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2618 //==============================================================
2619
2620 //--------------------------------------------------------------
2621 // Init tool: pre_clo_init, process cmd line, post_clo_init
2622 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002623 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002624 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2625 // p: parse_procselfmaps [so VG segments are setup so tool can
2626 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002628 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002629 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002630 VG_(sanity_check_needs)();
2631
nethercotef4928da2004-06-15 10:54:40 +00002632 // If --tool and --help/--help-debug was given, now give the core+tool
2633 // help message
nethercotef4928da2004-06-15 10:54:40 +00002634 if (need_help) {
2635 usage(/*--help-debug?*/2 == need_help);
2636 }
nethercotec314eba2004-07-15 12:59:41 +00002637 process_cmd_line_options(client_auxv, tool);
2638
njn51d827b2005-05-09 01:02:08 +00002639 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002640
2641 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002642 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002643 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002644 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002645 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002646 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002647 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002648 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002649 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002650 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002651
sewardj21c6d0f2005-05-02 10:33:44 +00002652#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002653 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002654 // Protect client trampoline page (which is also sysinfo stuff)
2655 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002656 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002657 {
2658 Segment *seg;
2659 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2660 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002661
sewardjb5f6f512005-03-10 23:59:00 +00002662 /* Make sure this segment isn't treated as stack */
2663 seg = VG_(find_segment)(VG_(client_trampoline_code));
2664 if (seg)
2665 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2666 }
sewardj21c6d0f2005-05-02 10:33:44 +00002667#endif
sewardjb5f6f512005-03-10 23:59:00 +00002668
nethercotec314eba2004-07-15 12:59:41 +00002669 //==============================================================
2670 // Can use VG_(map)() after segments set up
2671 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002672
2673 //--------------------------------------------------------------
2674 // Allow GDB attach
2675 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2676 //--------------------------------------------------------------
2677 /* Hook to delay things long enough so we can get the pid and
2678 attach GDB in another shell. */
2679 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002680 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002681 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2682 /* jrs 20050206: I don't understand why this works on x86. On
2683 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2684 work. */
2685 /* do "jump *$eip" to skip this in gdb (x86) */
2686 //VG_(do_syscall0)(__NR_pause);
2687 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002688 }
2689
sewardjb5d320c2005-03-13 18:57:15 +00002690 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002691 // Search for file descriptors that are inherited from our parent
2692 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2693 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002694 if (VG_(clo_track_fds)) {
2695 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002696 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002697 }
nethercote71980f02004-01-24 18:18:54 +00002698
2699 //--------------------------------------------------------------
2700 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002701 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2702 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002703 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002704 VG_(scheduler_init)();
2705
2706 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002707 // Initialise the pthread model
2708 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002709 // load_client() [for 'client_eip']
2710 // setup_client_stack() [for 'sp_at_startup']
2711 // setup_scheduler() [for the rest of state 1 stuff]
2712 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002713 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002714 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002715
2716 // Tell the tool that we just wrote to the registers.
2717 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2718 sizeof(VexGuestArchState));
2719
sewardj2a99cf62004-11-24 10:44:19 +00002720 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002721 // Initialise the pthread model
2722 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002723 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002724 //if (VG_(clo_model_pthreads))
2725 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002726
2727 //--------------------------------------------------------------
2728 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002729 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002730 //--------------------------------------------------------------
2731 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002732 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002733 VG_(sigstartup_actions)();
2734
2735 //--------------------------------------------------------------
2736 // Perhaps we're profiling Valgrind?
2737 // p: process_cmd_line_options() [for VG_(clo_profile)]
2738 // p: others?
2739 //
2740 // XXX: this seems to be broken? It always says the tool wasn't built
2741 // for profiling; vg_profile.c's functions don't seem to be overriding
2742 // vg_dummy_profile.c's?
2743 //
2744 // XXX: want this as early as possible. Looking for --profile
2745 // in pre_process_cmd_line_options() could get it earlier.
2746 //--------------------------------------------------------------
2747 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002748 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002749
2750 VGP_PUSHCC(VgpStartup);
2751
2752 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002753 // Read suppression file
2754 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2755 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002756 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2757 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002758 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002759 }
nethercote71980f02004-01-24 18:18:54 +00002760
2761 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002762 // Initialise translation table and translation cache
2763 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2764 // aren't identified as part of the client, which would waste
2765 // > 20M of virtual address space.]
2766 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002767 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002768 VG_(init_tt_tc)();
2769
2770 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002771 // Read debug info to find glibc entry points to intercept
2772 // p: parse_procselfmaps? [XXX for debug info?]
2773 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2774 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002775 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002776 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002777 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002778
2779 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002780 // Verbosity message
2781 // p: end_rdtsc_calibration [so startup message is printed first]
2782 //--------------------------------------------------------------
2783 if (VG_(clo_verbosity) == 1)
2784 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2785 if (VG_(clo_verbosity) > 0)
2786 VG_(message)(Vg_UserMsg, "");
2787
2788 //--------------------------------------------------------------
2789 // Setup pointercheck
2790 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2791 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002792 if (VG_(clo_pointercheck))
2793 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002794
nethercote71980f02004-01-24 18:18:54 +00002795 //--------------------------------------------------------------
2796 // Run!
2797 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002798 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002799
sewardjb5f6f512005-03-10 23:59:00 +00002800 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002801
sewardj1fbc1a52005-04-25 02:05:54 +00002802 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002803 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002804
sewardjb5f6f512005-03-10 23:59:00 +00002805 abort();
2806}
2807
2808
2809/* Do everything which needs doing when the last thread exits */
2810void VG_(shutdown_actions)(ThreadId tid)
2811{
2812 vg_assert(tid == VG_(master_tid));
2813 vg_assert(VG_(is_running_thread)(tid));
2814
2815 // Wait for all other threads to exit.
2816 VGA_(reap_threads)(tid);
2817
2818 VG_(clo_model_pthreads) = False;
2819
2820 // Clean the client up before the final report
2821 VGA_(final_tidyup)(tid);
2822
2823 // OK, done
2824 VG_(exit_thread)(tid);
2825
2826 /* should be no threads left */
2827 vg_assert(VG_(count_living_threads)() == 0);
2828
2829 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002830 //--------------------------------------------------------------
2831 // Finalisation: cleanup, messages, etc. Order no so important, only
2832 // affects what order the messages come.
2833 //--------------------------------------------------------------
2834 if (VG_(clo_verbosity) > 0)
2835 VG_(message)(Vg_UserMsg, "");
2836
nethercote71980f02004-01-24 18:18:54 +00002837 /* Print out file descriptor summary and stats. */
2838 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002839 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002840
njn95ec8702004-11-22 16:46:13 +00002841 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002842 VG_(show_all_errors)();
2843
njn51d827b2005-05-09 01:02:08 +00002844 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002845
nethercote885dd912004-08-03 23:14:00 +00002846 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002847
2848 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002849 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002850
nethercote71980f02004-01-24 18:18:54 +00002851 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002852 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002853 if (VG_(clo_profile_flags) > 0)
2854 VG_(show_BB_profile)();
2855
sewardj8b635a42004-11-22 19:01:47 +00002856 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002857 if (0)
2858 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002859}
sewardj8b635a42004-11-22 19:01:47 +00002860
sewardjde4a1d02002-03-22 01:27:54 +00002861/*--------------------------------------------------------------------*/
2862/*--- end vg_main.c ---*/
2863/*--------------------------------------------------------------------*/