blob: 0924c84859ad427b3fc55e6e3daab6dad3399e53 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njn2521d322005-05-08 14:45:13 +000040#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000041#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000042#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000043
44#include <dirent.h>
45#include <dlfcn.h>
46#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000047#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000048#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000049#include <string.h>
50#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000051#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000052#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <sys/wait.h>
54#include <unistd.h>
55
sewardjb5f6f512005-03-10 23:59:00 +000056#include "memcheck/memcheck.h"
57
thughes74b8de22004-04-22 18:12:31 +000058#ifndef AT_DCACHEBSIZE
59#define AT_DCACHEBSIZE 19
60#endif /* AT_DCACHEBSIZE */
61
62#ifndef AT_ICACHEBSIZE
63#define AT_ICACHEBSIZE 20
64#endif /* AT_ICACHEBSIZE */
65
66#ifndef AT_UCACHEBSIZE
67#define AT_UCACHEBSIZE 21
68#endif /* AT_UCACHEBSIZE */
69
nethercote71980f02004-01-24 18:18:54 +000070#ifndef AT_SYSINFO
71#define AT_SYSINFO 32
72#endif /* AT_SYSINFO */
73
74#ifndef AT_SYSINFO_EHDR
75#define AT_SYSINFO_EHDR 33
76#endif /* AT_SYSINFO_EHDR */
77
78#ifndef AT_SECURE
79#define AT_SECURE 23 /* secure mode boolean */
80#endif /* AT_SECURE */
81
nethercote71980f02004-01-24 18:18:54 +000082/* redzone gap between client address space and shadow */
83#define REDZONE_SIZE (1 * 1024*1024)
84
85/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000086#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000087
nethercotee2097312004-06-27 12:29:56 +000088/* Proportion of client space for its heap (rest is for mmaps + stack) */
89#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000090
njn14319cc2005-03-13 06:26:22 +000091/* Number of file descriptors that Valgrind tries to reserve for
92 it's own use - just a small constant. */
93#define N_RESERVED_FDS (10)
94
95/* Default debugger command. */
96#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
97
nethercote71980f02004-01-24 18:18:54 +000098/*====================================================================*/
99/*=== Global entities not referenced from generated code ===*/
100/*====================================================================*/
101
sewardjde4a1d02002-03-22 01:27:54 +0000102/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000103 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000104 ------------------------------------------------------------------ */
105
nethercote71980f02004-01-24 18:18:54 +0000106/* Client address space, lowest to highest (see top of ume.c) */
107Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(client_end);
109Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000110Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(clstk_base);
112Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000113
114Addr VG_(brk_base); /* start of brk */
115Addr VG_(brk_limit); /* current brk */
116
nethercote996901a2004-08-03 13:29:09 +0000117Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000118Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000119
120Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000121
nethercote820bd8c2004-09-07 23:04:49 +0000122// Note that VG_(valgrind_last) names the last byte of the section, whereas
123// the VG_(*_end) vars name the byte one past the end of the section.
124Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000125
nethercote73b526f2004-10-31 18:48:21 +0000126struct vki_rlimit VG_(client_rlimit_data);
127struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000128
fitzhardinge98abfc72003-12-16 02:05:15 +0000129/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000130static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000131
132/* client executable */
133Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000134
135/* Path to library directory */
136const Char *VG_(libdir) = VG_LIBDIR;
137
138/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000139static Int vg_argc;
140static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000141
sewardjb5f6f512005-03-10 23:59:00 +0000142/* The master thread the one which will be responsible for mopping
143 everything up at exit. Normally it is tid 1, since that's the
144 first thread created, but it may be something else after a
145 fork(). */
146ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000147
thughesad1c9562004-06-26 11:27:52 +0000148/* Application-visible file descriptor limits */
149Int VG_(fd_soft_limit) = -1;
150Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000151
nethercote4ad74312004-10-26 09:59:49 +0000152/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000153 envp[] as extracted from the client's stack at startup-time. */
154Int VG_(client_argc);
155Char** VG_(client_argv);
156Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000157
sewardj51ac0872004-12-21 01:20:49 +0000158
sewardjde4a1d02002-03-22 01:27:54 +0000159/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000160 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000161 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000162
sewardjde4a1d02002-03-22 01:27:54 +0000163/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000164ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000165
nethercote71980f02004-01-24 18:18:54 +0000166/* Tell the logging mechanism whether we are logging to a file
167 descriptor or a socket descriptor. */
njnbe9b47b2005-05-15 16:22:58 +0000168Bool VG_(logging_to_socket) = False;
nethercote71980f02004-01-24 18:18:54 +0000169
sewardj73cf3bc2002-11-03 03:20:15 +0000170
nethercote71980f02004-01-24 18:18:54 +0000171/*====================================================================*/
172/*=== Counters, for profiling purposes only ===*/
173/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000174
sewardjde4a1d02002-03-22 01:27:54 +0000175/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000176static UInt sanity_fast_count = 0;
177static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000178
nethercote3a42fb82004-08-03 18:08:50 +0000179static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000180{
nethercote3a42fb82004-08-03 18:08:50 +0000181 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000182 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000183 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000184 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000185
nethercote3a42fb82004-08-03 18:08:50 +0000186 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000187 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000188
nethercote71980f02004-01-24 18:18:54 +0000189 VG_(message)(Vg_DebugMsg,
190 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000191 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000192
njn9271cbc2005-03-13 05:38:25 +0000193 VG_(print_ExeContext_stats)();
194
nethercote3a42fb82004-08-03 18:08:50 +0000195 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000196 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000197 VG_(message)(Vg_DebugMsg, "");
198 VG_(message)(Vg_DebugMsg,
199 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000200 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000201 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000202 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000203 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000204 }
nethercote71980f02004-01-24 18:18:54 +0000205}
206
207
208/*====================================================================*/
209/*=== Miscellaneous global functions ===*/
210/*====================================================================*/
211
nethercotecf97ffb2004-09-09 13:40:31 +0000212static Int ptrace_setregs(Int pid, ThreadId tid)
213{
sewardj2a99cf62004-11-24 10:44:19 +0000214 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000215}
216
nethercote04d0fbc2004-01-26 16:48:06 +0000217/* Start debugger and get it to attach to this process. Called if the
218 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000219 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000220 meaningfully get the debugger to continue the program, though; to
221 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000222void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000223{
224 Int pid;
225
226 if ((pid = fork()) == 0) {
227 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000228 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000229
230 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000231 Int status;
232 Int res;
233
nethercote71980f02004-01-24 18:18:54 +0000234 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
235 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000236 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000237 kill(pid, SIGSTOP) == 0 &&
238 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000239 Char pidbuf[15];
240 Char file[30];
241 Char buf[100];
242 Char *bufptr;
243 Char *cmdptr;
244
245 VG_(sprintf)(pidbuf, "%d", pid);
246 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
247
248 bufptr = buf;
249 cmdptr = VG_(clo_db_command);
250
251 while (*cmdptr) {
252 switch (*cmdptr) {
253 case '%':
254 switch (*++cmdptr) {
255 case 'f':
256 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
257 bufptr += VG_(strlen)(file);
258 cmdptr++;
259 break;
260 case 'p':
261 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
262 bufptr += VG_(strlen)(pidbuf);
263 cmdptr++;
264 break;
265 default:
266 *bufptr++ = *cmdptr++;
267 break;
268 }
269 break;
270 default:
271 *bufptr++ = *cmdptr++;
272 break;
273 }
274 }
275
276 *bufptr++ = '\0';
277
278 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000279 res = VG_(system)(buf);
280 if (res == 0) {
281 VG_(message)(Vg_UserMsg, "");
282 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000283 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000284 } else {
285 VG_(message)(Vg_UserMsg, "Apparently failed!");
286 VG_(message)(Vg_UserMsg, "");
287 }
288 }
289
nethercote73b526f2004-10-31 18:48:21 +0000290 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000291 VG_(waitpid)(pid, &status, 0);
292 }
293}
294
295
296/* Print some helpful-ish text about unimplemented things, and give
297 up. */
298void VG_(unimplemented) ( Char* msg )
299{
300 VG_(message)(Vg_UserMsg, "");
301 VG_(message)(Vg_UserMsg,
302 "Valgrind detected that your program requires");
303 VG_(message)(Vg_UserMsg,
304 "the following unimplemented functionality:");
305 VG_(message)(Vg_UserMsg, " %s", msg);
306 VG_(message)(Vg_UserMsg,
307 "This may be because the functionality is hard to implement,");
308 VG_(message)(Vg_UserMsg,
309 "or because no reasonable program would behave this way,");
310 VG_(message)(Vg_UserMsg,
311 "or because nobody has yet needed it. In any case, let us know at");
312 VG_(message)(Vg_UserMsg,
313 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
314 VG_(message)(Vg_UserMsg,
315 "");
316 VG_(message)(Vg_UserMsg,
317 "Valgrind has to exit now. Sorry. Bye!");
318 VG_(message)(Vg_UserMsg,
319 "");
320 VG_(pp_sched_status)();
321 VG_(exit)(1);
322}
323
sewardj2a99cf62004-11-24 10:44:19 +0000324/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000325Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000326{
njncf45fd42004-11-24 16:30:22 +0000327 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000328}
329
njn67516132005-03-22 04:02:43 +0000330Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000331{
332 return INSTR_PTR( VG_(threads)[tid].arch );
333}
334
njnea4b28c2004-11-30 16:04:58 +0000335
nethercote71980f02004-01-24 18:18:54 +0000336/*====================================================================*/
337/*=== Check we were launched by stage 1 ===*/
338/*====================================================================*/
339
340/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000341static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000342{
nethercoteebf1d862004-11-01 18:22:05 +0000343 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000344 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000345
346 for (; auxv->a_type != AT_NULL; auxv++)
347 switch(auxv->a_type) {
348 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000349 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000350 found |= 1;
351 break;
352
353 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000354 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000355 found |= 2;
356 break;
nethercote7f390022004-10-25 17:18:24 +0000357
358 case AT_PHDR:
359 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
360 break;
nethercote71980f02004-01-24 18:18:54 +0000361 }
362
nethercote361a14e2004-07-26 11:11:56 +0000363 if ( found != (1|2) ) {
364 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000365 exit(127);
366 }
nethercote31779c72004-07-30 21:50:15 +0000367 vg_assert(padfile >= 0);
368 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000369}
370
371
372/*====================================================================*/
373/*=== Address space determination ===*/
374/*====================================================================*/
375
nethercote7f390022004-10-25 17:18:24 +0000376extern char _start[];
377
nethercote31779c72004-07-30 21:50:15 +0000378static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000379{
nethercotea3c3cf22004-11-01 18:38:00 +0000380 Int ires;
381 void* vres;
382 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000383
nethercote7f390022004-10-25 17:18:24 +0000384 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
385 // this is a workable approximation
386 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000387 VG_(valgrind_base) = PGROUNDDN(&_start);
388 }
389
nethercote820bd8c2004-09-07 23:04:49 +0000390 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000391
nethercote31779c72004-07-30 21:50:15 +0000392 // This gives the client the largest possible address space while
393 // taking into account the tool's shadow needs.
394 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000395 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000396 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000397 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000398 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000399 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000400 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000401
nethercote31779c72004-07-30 21:50:15 +0000402 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000403 VG_(shadow_end) = VG_(valgrind_base);
404 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000405
nethercotee2097312004-06-27 12:29:56 +0000406#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
407
nethercote71980f02004-01-24 18:18:54 +0000408 if (0)
nethercotee2097312004-06-27 12:29:56 +0000409 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000410 "client_base %p (%dMB)\n"
411 "client_mapbase %p (%dMB)\n"
412 "client_end %p (%dMB)\n"
413 "shadow_base %p (%dMB)\n"
414 "shadow_end %p\n"
415 "valgrind_base %p (%dMB)\n"
416 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000417 VG_(client_base), SEGSIZE(client_base, client_mapbase),
418 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
419 VG_(client_end), SEGSIZE(client_end, shadow_base),
420 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000421 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000422 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
423 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000424 );
425
426#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000427
428 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000429 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000430 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000431 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000432
433 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000434 ires = munmap((void*)VG_(client_base), client_size);
435 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000436
437 // Map shadow memory.
438 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000439 if (shadow_size != 0) {
440 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000441 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000442 if ((void*)-1 == vres) {
443 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000444 "valgrind: Could not allocate address space (%p bytes)\n"
445 "valgrind: for shadow memory\n"
446 "valgrind: Possible causes:\n"
447 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
448 "valgrind: needs at least 1.5GB swap space.\n"
449 "valgrind: - Or, your virtual memory size may be limited (check\n"
450 "valgrind: with 'ulimit -v').\n"
451 "valgrind: - Or, your system may use a kernel that provides only a\n"
452 "valgrind: too-small (eg. 2GB) user address space.\n"
453 , (void*)shadow_size
454 );
nethercoted4722622004-08-30 19:36:42 +0000455 exit(1);
456 }
nethercotee567e702004-07-10 17:49:17 +0000457 }
nethercote71980f02004-01-24 18:18:54 +0000458}
459
460/*====================================================================*/
461/*=== Command line setup ===*/
462/*====================================================================*/
463
464/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
465static char* get_file_clo(char* dir)
466{
467# define FLEN 512
468 Int fd, n;
469 struct stat s1;
470 char* f_clo = NULL;
471 char filename[FLEN];
472
473 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
474 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
475 if ( fd > 0 ) {
476 if ( 0 == fstat(fd, &s1) ) {
477 f_clo = malloc(s1.st_size+1);
478 vg_assert(f_clo);
479 n = read(fd, f_clo, s1.st_size);
480 if (n == -1) n = 0;
481 f_clo[n] = '\0';
482 }
483 close(fd);
484 }
485 return f_clo;
486# undef FLEN
487}
488
489static Int count_args(char* s)
490{
491 Int n = 0;
492 if (s) {
493 char* cp = s;
494 while (True) {
495 // We have alternating sequences: blanks, non-blanks, blanks...
496 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000497 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000498 if ( !*cp ) break;
499 n++;
njn0c0f32a2005-03-26 04:14:01 +0000500 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000501 }
502 }
503 return n;
504}
505
506/* add args out of environment, skipping multiple spaces and -- args */
507static char** copy_args( char* s, char** to )
508{
509 if (s) {
510 char* cp = s;
511 while (True) {
512 // We have alternating sequences: blanks, non-blanks, blanks...
513 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000514 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000515 if ( !*cp ) break;
516 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000517 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000518 if ( *cp ) *cp++ = '\0'; // terminate if necessary
519 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
520 }
521 }
522 return to;
523}
524
525// Augment command line with arguments from environment and .valgrindrc
526// files.
527static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
528{
nethercotef6a1d502004-08-09 12:21:57 +0000529 int vg_argc0 = *vg_argc_inout;
530 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000531
532 char* env_clo = getenv(VALGRINDOPTS);
533 char* f1_clo = get_file_clo( getenv("HOME") );
534 char* f2_clo = get_file_clo(".");
535
536 /* copy any extra args from file or environment, if present */
537 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
538 /* ' ' separated extra options */
539 char **from;
540 char **to;
thughescaca0022004-09-13 10:20:34 +0000541 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
542
543 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
544
nethercote71980f02004-01-24 18:18:54 +0000545 env_arg_count = count_args(env_clo);
546 f1_arg_count = count_args(f1_clo);
547 f2_arg_count = count_args(f2_clo);
548
549 if (0)
550 printf("extra-argc=%d %d %d\n",
551 env_arg_count, f1_arg_count, f2_arg_count);
552
553 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000554 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000555 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000556 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000557 vg_assert(vg_argv0);
558 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000559
560 /* copy argv[0] */
561 *to++ = *from++;
562
563 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
564 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
565 * to override less local ones. */
566 to = copy_args(f1_clo, to);
567 to = copy_args(env_clo, to);
568 to = copy_args(f2_clo, to);
569
570 /* copy original arguments, stopping at command or -- */
571 while (*from) {
572 if (**from != '-')
573 break;
574 if (VG_STREQ(*from, "--")) {
575 from++; /* skip -- */
576 break;
577 }
578 *to++ = *from++;
579 }
580
581 /* add -- */
582 *to++ = "--";
583
nethercotef6a1d502004-08-09 12:21:57 +0000584 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000585
586 /* copy rest of original command line, then NULL */
587 while (*from) *to++ = *from++;
588 *to = NULL;
589 }
590
nethercotef6a1d502004-08-09 12:21:57 +0000591 *vg_argc_inout = vg_argc0;
592 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000593}
594
nethercotef6a1d502004-08-09 12:21:57 +0000595#define VG_CLO_SEP '\01'
596
nethercote71980f02004-01-24 18:18:54 +0000597static void get_command_line( int argc, char** argv,
598 Int* vg_argc_out, Char*** vg_argv_out,
599 char*** cl_argv_out )
600{
nethercotef6a1d502004-08-09 12:21:57 +0000601 int vg_argc0;
602 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000603 char** cl_argv;
604 char* env_clo = getenv(VALGRINDCLO);
605
606 if (env_clo != NULL && *env_clo != '\0') {
607 char *cp;
608 char **cpp;
609
nethercotef6a1d502004-08-09 12:21:57 +0000610 /* OK, VALGRINDCLO is set, which means we must be a child of another
611 Valgrind process using --trace-children, so we're getting all our
612 arguments from VALGRINDCLO, and the entire command line belongs to
613 the client (including argv[0]) */
614 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000615 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000616 if (*cp == VG_CLO_SEP)
617 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000618
nethercotef6a1d502004-08-09 12:21:57 +0000619 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
620 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000621
nethercotef6a1d502004-08-09 12:21:57 +0000622 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000623
624 *cpp++ = "valgrind"; /* nominal argv[0] */
625 *cpp++ = env_clo;
626
nethercotef6a1d502004-08-09 12:21:57 +0000627 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000628 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000629 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000630 *cp++ = '\0'; /* chop it up in place */
631 *cpp++ = cp;
632 }
633 }
634 *cpp = NULL;
635 cl_argv = argv;
636
637 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000638 Bool noaugment = False;
639
nethercote71980f02004-01-24 18:18:54 +0000640 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000641 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000642
nethercotef6a1d502004-08-09 12:21:57 +0000643 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000644 Char* arg = argv[vg_argc0];
645 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000646 break;
sewardjb5f6f512005-03-10 23:59:00 +0000647 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000648 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000649 break;
650 }
njn45270a22005-03-27 01:00:11 +0000651 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000652 }
nethercotef6a1d502004-08-09 12:21:57 +0000653 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000654
655 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000656 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000657 those extra args will already be present in VALGRINDCLO.
658 (We also don't do it when --command-line-only=yes.) */
659 if (!noaugment)
660 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000661 }
662
663 if (0) {
664 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000665 for (i = 0; i < vg_argc0; i++)
666 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000667 }
668
nethercotef6a1d502004-08-09 12:21:57 +0000669 *vg_argc_out = vg_argc0;
670 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000671 *cl_argv_out = cl_argv;
672}
673
674
675/*====================================================================*/
676/*=== Environment and stack setup ===*/
677/*====================================================================*/
678
679/* Scan a colon-separated list, and call a function on each element.
680 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000681 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000682 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000683
684 This routine will return True if (*func) returns True and False if
685 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000686*/
thughes4ad52d02004-06-27 17:37:21 +0000687static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000688{
689 char *cp, *entry;
690 int end;
691
692 if (colsep == NULL ||
693 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000694 return False;
nethercote71980f02004-01-24 18:18:54 +0000695
696 entry = cp = colsep;
697
698 do {
699 end = (*cp == '\0');
700
701 if (*cp == ':' || *cp == '\0') {
702 char save = *cp;
703
704 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000705 if ((*func)(entry)) {
706 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000707 return True;
thughes21942d92004-07-12 09:35:37 +0000708 }
nethercote71980f02004-01-24 18:18:54 +0000709 *cp = save;
710 entry = cp+1;
711 }
712 cp++;
713 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000714
715 return False;
716}
717
nethercote71980f02004-01-24 18:18:54 +0000718/* Prepare the client's environment. This is basically a copy of our
719 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000720 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000721
sewardjb5f6f512005-03-10 23:59:00 +0000722 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000723
724 Yummy. String hacking in C.
725
726 If this needs to handle any more variables it should be hacked
727 into something table driven.
728 */
729static char **fix_environment(char **origenv, const char *preload)
730{
731 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000732 static const char ld_preload[] = "LD_PRELOAD=";
733 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000734 static const int ld_preload_len = sizeof(ld_preload)-1;
735 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
736 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000737 char *inject_path;
738 int inject_path_len;
739 int vgliblen = strlen(VG_(libdir));
740 char **cpp;
741 char **ret;
742 int envc;
743 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
744
745 /* Find the vg_inject.so; also make room for the tool preload
746 library */
747 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
748 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000749 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000750
751 if (preload)
752 snprintf(inject_path, inject_path_len, "%s/%s:%s",
753 VG_(libdir), inject_so, preload);
754 else
755 snprintf(inject_path, inject_path_len, "%s/%s",
756 VG_(libdir), inject_so);
757
758 /* Count the original size of the env */
759 envc = 0; /* trailing NULL */
760 for (cpp = origenv; cpp && *cpp; cpp++)
761 envc++;
762
763 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000764 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000765 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000766
767 /* copy it over */
768 for (cpp = ret; *origenv; )
769 *cpp++ = *origenv++;
770 *cpp = NULL;
771
772 vg_assert(envc == (cpp - ret));
773
774 /* Walk over the new environment, mashing as we go */
775 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000776 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000777 int len = strlen(*cpp) + inject_path_len;
778 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000779 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000780
781 snprintf(cp, len, "%s%s:%s",
782 ld_preload, inject_path, (*cpp)+ld_preload_len);
783
784 *cpp = cp;
785
786 ld_preload_done = 1;
787 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
788 *cpp = "";
789 }
790 }
791
792 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000793 if (!ld_preload_done) {
794 int len = ld_preload_len + inject_path_len;
795 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000796 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000797
798 snprintf(cp, len, "%s%s",
799 ld_preload, inject_path);
800
801 ret[envc++] = cp;
802 }
803
sewardjb5f6f512005-03-10 23:59:00 +0000804 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000805 ret[envc] = NULL;
806
807 return ret;
808}
809
810extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000811
812/* Add a string onto the string table, and return its address */
813static char *copy_str(char **tab, const char *str)
814{
815 char *cp = *tab;
816 char *orig = cp;
817
818 while(*str)
819 *cp++ = *str++;
820 *cp++ = '\0';
821
822 if (0)
nethercote545fe672004-11-01 16:52:43 +0000823 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000824
825 *tab = cp;
826
827 return orig;
828}
829
830/*
831 This sets up the client's initial stack, containing the args,
832 environment and aux vector.
833
834 The format of the stack is:
835
836 higher address +-----------------+
837 | Trampoline code |
838 +-----------------+
839 | |
840 : string table :
841 | |
842 +-----------------+
843 | AT_NULL |
844 - -
845 | auxv |
846 +-----------------+
847 | NULL |
848 - -
849 | envp |
850 +-----------------+
851 | NULL |
852 - -
853 | argv |
854 +-----------------+
855 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000856 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000857 | undefined |
858 : :
859 */
nethercotec25c4492004-10-18 11:52:17 +0000860static Addr setup_client_stack(void* init_sp,
861 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000862 const struct exeinfo *info,
863 UInt** client_auxv)
864{
nethercotee567e702004-07-10 17:49:17 +0000865 void* res;
nethercote71980f02004-01-24 18:18:54 +0000866 char **cpp;
867 char *strtab; /* string table */
868 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000869 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000870 struct ume_auxv *auxv;
871 const struct ume_auxv *orig_auxv;
872 const struct ume_auxv *cauxv;
873 unsigned stringsize; /* total size of strings in bytes */
874 unsigned auxsize; /* total size of auxv in bytes */
875 int argc; /* total argc */
876 int envc; /* total number of env vars */
877 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000878 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000879
880 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000881 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000882
883 /* ==================== compute sizes ==================== */
884
885 /* first of all, work out how big the client stack will be */
886 stringsize = 0;
887
888 /* paste on the extra args if the loader needs them (ie, the #!
889 interpreter and its argument) */
890 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000891 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000892 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000893 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000894 }
nethercoted6a56872004-07-26 15:32:47 +0000895 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000896 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000897 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000898 }
899
900 /* now scan the args we're given... */
901 for (cpp = orig_argv; *cpp; cpp++) {
902 argc++;
903 stringsize += strlen(*cpp) + 1;
904 }
905
906 /* ...and the environment */
907 envc = 0;
908 for (cpp = orig_envp; cpp && *cpp; cpp++) {
909 envc++;
910 stringsize += strlen(*cpp) + 1;
911 }
912
913 /* now, how big is the auxv? */
914 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
915 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
916 if (cauxv->a_type == AT_PLATFORM)
917 stringsize += strlen(cauxv->u.a_ptr) + 1;
918 auxsize += sizeof(*cauxv);
919 }
920
921 /* OK, now we know how big the client stack is */
922 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000923 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000924 sizeof(char **)*argc + /* argv */
925 sizeof(char **) + /* terminal NULL */
926 sizeof(char **)*envc + /* envp */
927 sizeof(char **) + /* terminal NULL */
928 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000929 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000930 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000931
sewardj79048ce2005-02-18 08:28:32 +0000932 if (0) VG_(printf)("stacksize = %d\n", stacksize);
933
nethercotef84f6952004-07-15 14:58:33 +0000934 // decide where stack goes!
935 VG_(clstk_end) = VG_(client_end);
936
nethercote73b526f2004-10-31 18:48:21 +0000937 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000938
nethercote71980f02004-01-24 18:18:54 +0000939 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000940 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000941 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
942
nethercote71980f02004-01-24 18:18:54 +0000943 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000944 stringbase = strtab = (char *)(VG_(client_trampoline_code)
945 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000946
947 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000948
sewardj79048ce2005-02-18 08:28:32 +0000949 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000950 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000951 "clstk_base %p\n"
952 "clstk_end %p\n",
953 stringsize, auxsize, stacksize,
954 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000955
nethercote71980f02004-01-24 18:18:54 +0000956 /* ==================== allocate space ==================== */
957
958 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000959 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000960 PROT_READ | PROT_WRITE | PROT_EXEC,
961 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
962 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000963
964 /* ==================== copy client stack ==================== */
965
nethercotea3c3cf22004-11-01 18:38:00 +0000966 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000967
968 /* --- argc --- */
969 *ptr++ = argc; /* client argc */
970
971 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000972 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000973 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000974 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000975 }
nethercoted6a56872004-07-26 15:32:47 +0000976 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000977 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000978 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000979 }
980 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000981 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000982 }
983 *ptr++ = 0;
984
985 /* --- envp --- */
986 VG_(client_envp) = (Char **)ptr;
987 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000988 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000989 *ptr++ = 0;
990
991 /* --- auxv --- */
992 auxv = (struct ume_auxv *)ptr;
993 *client_auxv = (UInt *)auxv;
994
995 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
996 /* copy the entry... */
997 *auxv = *orig_auxv;
998
999 /* ...and fix up the copy */
1000 switch(auxv->a_type) {
1001 case AT_PHDR:
1002 if (info->phdr == 0)
1003 auxv->a_type = AT_IGNORE;
1004 else
1005 auxv->u.a_val = info->phdr;
1006 break;
1007
1008 case AT_PHNUM:
1009 if (info->phdr == 0)
1010 auxv->a_type = AT_IGNORE;
1011 else
1012 auxv->u.a_val = info->phnum;
1013 break;
1014
1015 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001016 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001017 break;
1018
1019 case AT_PLATFORM: /* points to a platform description string */
1020 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1021 break;
1022
1023 case AT_ENTRY:
1024 auxv->u.a_val = info->entry;
1025 break;
1026
1027 case AT_IGNORE:
1028 case AT_EXECFD:
1029 case AT_PHENT:
1030 case AT_PAGESZ:
1031 case AT_FLAGS:
1032 case AT_NOTELF:
1033 case AT_UID:
1034 case AT_EUID:
1035 case AT_GID:
1036 case AT_EGID:
1037 case AT_CLKTCK:
1038 case AT_HWCAP:
1039 case AT_FPUCW:
1040 case AT_DCACHEBSIZE:
1041 case AT_ICACHEBSIZE:
1042 case AT_UCACHEBSIZE:
1043 /* All these are pointerless, so we don't need to do anything
1044 about them. */
1045 break;
1046
1047 case AT_SECURE:
1048 /* If this is 1, then it means that this program is running
1049 suid, and therefore the dynamic linker should be careful
1050 about LD_PRELOAD, etc. However, since stage1 (the thing
1051 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001052 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001053 set AT_SECURE to 0. */
1054 auxv->u.a_val = 0;
1055 break;
1056
1057 case AT_SYSINFO:
1058 /* Leave this unmolested for now, but we'll update it later
1059 when we set up the client trampoline code page */
1060 break;
1061
1062 case AT_SYSINFO_EHDR:
1063 /* Trash this, because we don't reproduce it */
1064 auxv->a_type = AT_IGNORE;
1065 break;
1066
1067 default:
1068 /* stomp out anything we don't know about */
1069 if (0)
nethercote545fe672004-11-01 16:52:43 +00001070 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001071 auxv->a_type = AT_IGNORE;
1072 break;
1073
1074 }
1075 }
1076 *auxv = *orig_auxv;
1077 vg_assert(auxv->a_type == AT_NULL);
1078
njnc6168192004-11-29 13:54:10 +00001079// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1080// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001081#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001082 /* --- trampoline page --- */
1083 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1084 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001085#endif
nethercotef84f6952004-07-15 14:58:33 +00001086
nethercote71980f02004-01-24 18:18:54 +00001087 vg_assert((strtab-stringbase) == stringsize);
1088
nethercote5ee67ca2004-06-22 14:00:09 +00001089 /* We know the initial ESP is pointing at argc/argv */
1090 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001091 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001092
sewardj79048ce2005-02-18 08:28:32 +00001093 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001094 return cl_esp;
1095}
1096
1097/*====================================================================*/
1098/*=== Find executable ===*/
1099/*====================================================================*/
1100
thughes4ad52d02004-06-27 17:37:21 +00001101static const char* executable_name;
1102
1103static Bool match_executable(const char *entry) {
1104 char buf[strlen(entry) + strlen(executable_name) + 2];
1105
1106 /* empty PATH element means . */
1107 if (*entry == '\0')
1108 entry = ".";
1109
1110 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1111
1112 if (access(buf, R_OK|X_OK) == 0) {
1113 executable_name = strdup(buf);
1114 vg_assert(NULL != executable_name);
1115 return True;
1116 }
1117 return False;
1118}
1119
nethercote71980f02004-01-24 18:18:54 +00001120static const char* find_executable(const char* exec)
1121{
1122 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001123 executable_name = exec;
1124 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001125 /* no '/' - we need to search the path */
1126 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001127 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001128 }
thughes4ad52d02004-06-27 17:37:21 +00001129 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001130}
1131
1132
1133/*====================================================================*/
1134/*=== Loading tools ===*/
1135/*====================================================================*/
1136
1137static void list_tools(void)
1138{
1139 DIR *dir = opendir(VG_(libdir));
1140 struct dirent *de;
1141 int first = 1;
1142
1143 if (dir == NULL) {
1144 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001145 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001146 return;
1147 }
1148
nethercotef4928da2004-06-15 10:54:40 +00001149 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001150 int len = strlen(de->d_name);
1151
njn063c5402004-11-22 16:58:05 +00001152 /* look for vgtool_TOOL.so names */
1153 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1154 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001155 VG_STREQ(de->d_name + len - 3, ".so")) {
1156 if (first) {
1157 fprintf(stderr, "Available tools:\n");
1158 first = 0;
1159 }
1160 de->d_name[len-3] = '\0';
1161 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001162 }
1163 }
1164
1165 closedir(dir);
1166
1167 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001168 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1169 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001170}
1171
1172
1173/* Find and load a tool, and check it looks ok. Also looks to see if there's
1174 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001175static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001176 ToolInfo** toolinfo_out, char **preloadpath_out )
1177{
1178 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001179 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001180 char buf[len];
1181 void* handle;
1182 ToolInfo* toolinfo;
1183 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001184
1185 // XXX: allowing full paths for --tool option -- does it make sense?
1186 // Doesn't allow for vgpreload_<tool>.so.
1187
1188 if (strchr(toolname, '/') != 0) {
1189 /* toolname contains '/', and so must be a pathname */
1190 handle = dlopen(toolname, RTLD_NOW);
1191 } else {
1192 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001193 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001194 handle = dlopen(buf, RTLD_NOW);
1195
1196 if (handle != NULL) {
1197 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1198 if (access(buf, R_OK) == 0) {
1199 preloadpath = strdup(buf);
1200 vg_assert(NULL != preloadpath);
1201 }
1202 }
1203 }
1204
1205 ok = (NULL != handle);
1206 if (!ok) {
1207 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1208 goto bad_load;
1209 }
1210
njn51d827b2005-05-09 01:02:08 +00001211 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001212 ok = (NULL != toolinfo);
1213 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001214 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001215 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1216 goto bad_load;
1217 }
1218
1219 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001220 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1221 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001222 if (!ok) {
1223 fprintf(stderr, "Error:\n"
1224 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001225 " Interface version used by core is: %d (size %d)\n"
1226 " Interface version used by tool is: %d (size %d)\n"
1227 " The version numbers must match.\n",
1228 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001229 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001230 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001231 toolinfo->sizeof_ToolInfo);
1232 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001233 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001234 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001235 else
nethercote996901a2004-08-03 13:29:09 +00001236 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001237 goto bad_load;
1238 }
1239
njn8a97c6d2005-03-31 04:37:24 +00001240 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001241 *toolinfo_out = toolinfo;
1242 *preloadpath_out = preloadpath;
1243 return;
1244
1245
1246 bad_load:
1247 if (handle != NULL)
1248 dlclose(handle);
1249
nethercotef4928da2004-06-15 10:54:40 +00001250 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001251 list_tools();
1252 exit(127);
1253}
1254
nethercotef4928da2004-06-15 10:54:40 +00001255
1256/*====================================================================*/
1257/*=== Command line errors ===*/
1258/*====================================================================*/
1259
njnbe9b47b2005-05-15 16:22:58 +00001260static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001261{
njnbe9b47b2005-05-15 16:22:58 +00001262 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001263 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001264}
1265
1266void VG_(bad_option) ( Char* opt )
1267{
njnbe9b47b2005-05-15 16:22:58 +00001268 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001269 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001270 VG_(printf)("valgrind: Use --help for more information.\n");
1271 VG_(exit)(1);
1272}
1273
nethercotef4928da2004-06-15 10:54:40 +00001274static void missing_prog ( void )
1275{
njnbe9b47b2005-05-15 16:22:58 +00001276 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001277 VG_(printf)("valgrind: no program specified\n");
1278 VG_(printf)("valgrind: Use --help for more information.\n");
1279 VG_(exit)(1);
1280}
1281
1282static void config_error ( Char* msg )
1283{
njnbe9b47b2005-05-15 16:22:58 +00001284 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001285 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1286 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1287 VG_(exit)(1);
1288}
1289
1290
nethercote71980f02004-01-24 18:18:54 +00001291/*====================================================================*/
1292/*=== Loading the client ===*/
1293/*====================================================================*/
1294
nethercotef4928da2004-06-15 10:54:40 +00001295static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001296 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1297{
1298 // If they didn't specify an executable with --exec, and didn't specify
1299 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001300 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001301 if (cl_argv[0] == NULL ||
1302 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1303 {
nethercotef4928da2004-06-15 10:54:40 +00001304 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001305 }
1306 }
1307
1308 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001309 info->exe_base = VG_(client_base);
1310 info->exe_end = VG_(client_end);
1311 info->argv = cl_argv;
1312
nethercotef4928da2004-06-15 10:54:40 +00001313 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001314 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001315 // Totally zero 'info' before continuing.
1316 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001317 } else {
1318 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001319 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001320 ret = do_exec(exec, info);
1321 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001322 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1323 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001324 exit(127);
1325 }
1326 }
1327
1328 /* Copy necessary bits of 'info' that were filled in */
1329 *client_eip = info->init_eip;
1330 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1331}
1332
nethercote969ecf12004-10-13 17:29:01 +00001333/*====================================================================*/
1334/*=== Address space unpadding ===*/
1335/*====================================================================*/
1336
1337typedef struct {
1338 char* killpad_start;
1339 char* killpad_end;
1340 struct stat* killpad_padstat;
1341} killpad_extra;
1342
1343static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1344 int maj, int min, int ino, void* ex)
1345{
1346 killpad_extra* extra = ex;
1347 void *b, *e;
1348 int res;
1349
1350 vg_assert(NULL != extra->killpad_padstat);
1351
1352 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1353 extra->killpad_padstat->st_ino != ino)
1354 return 1;
1355
1356 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1357 return 1;
1358
1359 if (segstart <= extra->killpad_start)
1360 b = extra->killpad_start;
1361 else
1362 b = segstart;
1363
1364 if (segend >= extra->killpad_end)
1365 e = extra->killpad_end;
1366 else
1367 e = segend;
1368
1369 res = munmap(b, (char *)e-(char *)b);
1370 vg_assert(0 == res);
1371
1372 return 1;
1373}
1374
1375// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001376static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001377{
1378 static struct stat padstat;
1379 killpad_extra extra;
1380 int res;
1381
sewardjb5f6f512005-03-10 23:59:00 +00001382 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001383
1384 res = fstat(padfile, &padstat);
1385 vg_assert(0 == res);
1386 extra.killpad_padstat = &padstat;
1387 extra.killpad_start = start;
1388 extra.killpad_end = end;
1389 foreach_map(killpad, &extra);
1390}
1391
sewardj2c5ffbe2005-03-12 13:32:06 +00001392static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001393{
1394 int res = close(padfile);
1395 vg_assert(0 == res);
1396}
1397
nethercote71980f02004-01-24 18:18:54 +00001398
1399/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001400/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001401/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001402
njn20242342005-05-16 23:31:24 +00001403// See pub_{core,tool}_options.h for explanations of all these.
1404
njn25e49d8e72002-09-23 09:36:25 +00001405/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001406VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001407Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001408Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001409Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001410Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001411Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001412Int VG_(clo_verbosity) = 1;
1413Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001414Bool VG_(clo_trace_children) = False;
njn20242342005-05-16 23:31:24 +00001415Int VG_(clo_log_fd) = 2;
1416Char* VG_(clo_log_name) = NULL;
thughes6233a382004-08-21 11:10:44 +00001417Bool VG_(clo_time_stamp) = False;
sewardj6024b212003-07-13 10:54:33 +00001418Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001419Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001420Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001421Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001422UChar VG_(clo_trace_flags) = 0; // 00000000b
1423UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001424Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001425Bool VG_(clo_trace_syscalls) = False;
1426Bool VG_(clo_trace_signals) = False;
1427Bool VG_(clo_trace_symtab) = False;
sewardjce058b02005-05-01 08:55:38 +00001428Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001429Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001430Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001431Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001432Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001433Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001434Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001435Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001436Bool VG_(clo_track_fds) = False;
njn20242342005-05-16 23:31:24 +00001437Bool VG_(clo_show_below_main)= False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001438Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001439Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001440Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001441Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001442Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001443Int VG_(clo_max_stackframe) = 2000000;
njn20242342005-05-16 23:31:24 +00001444Bool VG_(clo_wait_for_gdb) = False;
jsgf855d93d2003-10-13 22:26:55 +00001445
sewardjde4a1d02002-03-22 01:27:54 +00001446
sewardj2c5ffbe2005-03-12 13:32:06 +00001447static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001448{
njn25e49d8e72002-09-23 09:36:25 +00001449 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001450"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001451"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001452" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001453" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001454" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001455" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001456" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001457" -q --quiet run silently; only print error msgs\n"
1458" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001459" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001460" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001461" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001462"\n"
1463" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001464" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001465" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001466" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001467" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001468" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001469"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001470" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001471" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1472" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001473" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001474" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001475" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001476" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1478" --show-below-main=no|yes continue stack traces below main() [no]\n"
1479" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001480" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001481" --db-attach=no|yes start debugger when errors detected? [no]\n"
1482" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1483" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001484" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1485" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001486"\n";
njn7cf0bd32002-06-08 13:36:03 +00001487
njn25e49d8e72002-09-23 09:36:25 +00001488 Char* usage2 =
1489"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001490" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001491" --sanity-level=<number> level of sanity checking to do [1]\n"
1492" --single-step=no|yes translate each instr separately? [no]\n"
1493" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001494" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001495" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001496" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1497" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001498" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001499" --trace-syscalls=no|yes show all system calls? [no]\n"
1500" --trace-signals=no|yes show signal handling details? [no]\n"
1501" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001502" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001504" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001505#if 0
1506" --model-pthreads=yes|no model the pthreads library [no]\n"
1507#endif
1508" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001509"\n"
1510" --vex-iropt-verbosity 0 .. 9 [0]\n"
1511" --vex-iropt-level 0 .. 2 [2]\n"
1512" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001513" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1514" --vex-guest-max-insns 1 .. 100 [50]\n"
1515" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1516"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001517" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001518" 1000 0000 show conversion into IR\n"
1519" 0100 0000 show after initial opt\n"
1520" 0010 0000 show after instrumentation\n"
1521" 0001 0000 show after second opt\n"
1522" 0000 1000 show after tree building\n"
1523" 0000 0100 show selecting insns\n"
1524" 0000 0010 show after reg-alloc\n"
1525" 0000 0001 show final assembly\n"
1526"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001527" debugging options for Valgrind tools that report errors\n"
1528" --dump-error=<number> show translation for basic block associated\n"
1529" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001530"\n";
njn3e884182003-04-15 13:03:23 +00001531
1532 Char* usage3 =
1533"\n"
nethercote71980f02004-01-24 18:18:54 +00001534" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001535"\n"
njn53612422005-03-12 16:22:54 +00001536" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001537" and licensed under the GNU General Public License, version 2.\n"
1538" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001539"\n"
nethercote137bc552003-11-14 17:47:54 +00001540" Tools are copyright and licensed by their authors. See each\n"
1541" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001542"\n";
njn7cf0bd32002-06-08 13:36:03 +00001543
njnbe9b47b2005-05-15 16:22:58 +00001544 // Ensure the message goes to stdout
1545 VG_(clo_log_fd) = 1;
1546 vg_assert( !VG_(logging_to_socket) );
1547
fitzhardinge98abfc72003-12-16 02:05:15 +00001548 VG_(printf)(usage1);
1549 if (VG_(details).name) {
1550 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001551 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001552 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001553 else
1554 VG_(printf)(" (none)\n");
1555 }
nethercote6c999f22004-01-31 22:55:15 +00001556 if (debug_help) {
1557 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001558
nethercote6c999f22004-01-31 22:55:15 +00001559 if (VG_(details).name) {
1560 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1561
1562 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001563 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001564 else
1565 VG_(printf)(" (none)\n");
1566 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001567 }
nethercote421281e2003-11-20 16:20:55 +00001568 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001569 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001570}
sewardjde4a1d02002-03-22 01:27:54 +00001571
nethercote71980f02004-01-24 18:18:54 +00001572static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001573 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001574{
nethercote71980f02004-01-24 18:18:54 +00001575 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001576
sewardj8b635a42004-11-22 19:01:47 +00001577 LibVEX_default_VexControl(& VG_(clo_vex_control));
1578
nethercote71980f02004-01-24 18:18:54 +00001579 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001580 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001581
nethercotef6a1d502004-08-09 12:21:57 +00001582 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001583 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001584 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001585
nethercotef6a1d502004-08-09 12:21:57 +00001586 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1587 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001588 *need_help = 1;
1589
nethercotef6a1d502004-08-09 12:21:57 +00001590 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001591 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001592
nethercotef6c99d72004-11-09 14:35:43 +00001593 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001594 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001595
nethercotef6a1d502004-08-09 12:21:57 +00001596 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1597 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001598 }
1599 }
nethercote71980f02004-01-24 18:18:54 +00001600}
1601
nethercote5ee67ca2004-06-22 14:00:09 +00001602static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001603{
nethercotef8548672004-06-21 12:42:35 +00001604 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001605 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001606 enum {
1607 VgLogTo_Fd,
1608 VgLogTo_File,
1609 VgLogTo_FileExactly,
1610 VgLogTo_Socket
1611 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001612
nethercotee1730692003-11-20 10:38:07 +00001613 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001614 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001615
sewardj19d81412002-06-03 01:10:40 +00001616 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001618 config_error("Please use absolute paths in "
1619 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001620
njnc6168192004-11-29 13:54:10 +00001621// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001622#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001623 {
sewardjb5f6f512005-03-10 23:59:00 +00001624 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001625 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1626 switch(auxp[0]) {
1627 case AT_SYSINFO:
1628 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1629 break;
1630 }
1631 }
1632 }
1633#endif
sewardjde4a1d02002-03-22 01:27:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001638 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001639
thughes3bfd5a02004-07-18 08:05:44 +00001640 /* Look for a colon in the switch name */
1641 while (*colon && *colon != ':' && *colon != '=')
1642 colon++;
nethercote71980f02004-01-24 18:18:54 +00001643
1644 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001645 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001646 if (VG_CLO_STREQN(2, arg, "--") &&
1647 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1648 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1649 {
1650 // prefix matches, convert "--toolname:foo" to "--foo"
1651 if (0)
1652 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001653 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001654 arg[0] = '-';
1655 arg[1] = '-';
1656
1657 } else {
1658 // prefix doesn't match, skip to next arg
1659 continue;
1660 }
1661 }
1662
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001664 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1665 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1666 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001667
njn45270a22005-03-27 01:00:11 +00001668 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 else if (VG_CLO_STREQ(arg, "-v") ||
1671 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001672 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001673
nethercote71980f02004-01-24 18:18:54 +00001674 else if (VG_CLO_STREQ(arg, "-q") ||
1675 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001676 VG_(clo_verbosity)--;
1677
sewardj1cf558c2005-04-25 01:36:56 +00001678 else if (VG_CLO_STREQ(arg, "-d")) {
1679 /* do nothing */
1680 }
1681
njn45270a22005-03-27 01:00:11 +00001682 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1683 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1684 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1685 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1686 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1687 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1688 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001689 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001690 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1691 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1692 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1693 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1694 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1695 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1696 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1697 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1698 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001699 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001700 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1701 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1702 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1703 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1704 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001705
njn45270a22005-03-27 01:00:11 +00001706 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1707 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001708
njn45270a22005-03-27 01:00:11 +00001709 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1710 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1711 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1712 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1713 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001714
njn45270a22005-03-27 01:00:11 +00001715 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001716 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001717 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001718 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001719 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001720 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001721 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001722 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001723 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001724 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001725 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001726 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1727
nethercotef8548672004-06-21 12:42:35 +00001728 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001729 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001730 VG_(clo_log_name) = NULL;
1731 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001732 }
1733
nethercotef8548672004-06-21 12:42:35 +00001734 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001735 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001736 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001737 }
njnd6bc3c32005-03-27 00:44:31 +00001738
sewardj603d4102005-01-11 14:01:02 +00001739 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001740 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001741 VG_(clo_log_name) = &arg[19];
1742 }
sewardjde4a1d02002-03-22 01:27:54 +00001743
nethercotef8548672004-06-21 12:42:35 +00001744 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001745 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001746 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001747 }
1748
nethercote71980f02004-01-24 18:18:54 +00001749 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001750 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001751 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001752 VG_(message)(Vg_UserMsg,
1753 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001754 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001755 }
nethercote71980f02004-01-24 18:18:54 +00001756 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001757 VG_(clo_n_suppressions)++;
1758 }
sewardjde4a1d02002-03-22 01:27:54 +00001759
sewardjfa8ec112005-01-19 11:55:34 +00001760 /* "stuvwxyz" --> stuvwxyz (binary) */
1761 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1762 Int j;
1763 char* opt = & arg[14];
1764
1765 if (8 != VG_(strlen)(opt)) {
1766 VG_(message)(Vg_UserMsg,
1767 "--trace-flags argument must have 8 digits");
1768 VG_(bad_option)(arg);
1769 }
1770 for (j = 0; j < 8; j++) {
1771 if ('0' == opt[j]) { /* do nothing */ }
1772 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1773 else {
1774 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1775 "contain 0s and 1s");
1776 VG_(bad_option)(arg);
1777 }
1778 }
1779 }
1780
1781 /* "stuvwxyz" --> stuvwxyz (binary) */
1782 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001783 Int j;
nethercote71980f02004-01-24 18:18:54 +00001784 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001785
sewardj2a99cf62004-11-24 10:44:19 +00001786 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001787 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001788 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001789 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001790 }
sewardj8b635a42004-11-22 19:01:47 +00001791 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001792 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001793 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001794 else {
sewardjfa8ec112005-01-19 11:55:34 +00001795 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001796 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001797 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001798 }
1799 }
1800 }
sewardjde4a1d02002-03-22 01:27:54 +00001801
njn45270a22005-03-27 01:00:11 +00001802 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001803
sewardjd153fae2005-01-10 17:24:47 +00001804 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1805 VG_(clo_gen_suppressions) = 0;
1806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1807 VG_(clo_gen_suppressions) = 1;
1808 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1809 VG_(clo_gen_suppressions) = 2;
1810
nethercote71980f02004-01-24 18:18:54 +00001811 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001812 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001813 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001814 }
njn8c0b3bb2005-03-12 21:20:39 +00001815 skip_arg:
1816 if (arg != vg_argv[i])
1817 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001818 }
1819
sewardj998d40d2004-12-06 14:24:52 +00001820 /* Make VEX control parameters sane */
1821
1822 if (VG_(clo_vex_control).guest_chase_thresh
1823 >= VG_(clo_vex_control).guest_max_insns)
1824 VG_(clo_vex_control).guest_chase_thresh
1825 = VG_(clo_vex_control).guest_max_insns - 1;
1826
1827 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1828 VG_(clo_vex_control).guest_chase_thresh = 0;
1829
1830 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001831
njnf9ebf672003-05-12 21:41:30 +00001832 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001833 VG_(clo_verbosity) = 0;
1834
nethercote04d0fbc2004-01-26 16:48:06 +00001835 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(message)(Vg_UserMsg, "");
1837 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001838 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001839 VG_(message)(Vg_UserMsg,
1840 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001841 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001842 }
1843
njnbe9b47b2005-05-15 16:22:58 +00001844 if (VG_(clo_gen_suppressions) > 0 &&
1845 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1846 VG_(message)(Vg_UserMsg,
1847 "Can't use --gen-suppressions= with this tool,");
1848 VG_(message)(Vg_UserMsg,
1849 "as it doesn't generate errors.");
1850 VG_(bad_option)("--gen-suppressions=");
1851 }
1852
1853 /* All non-logging-related options have been checked. If the logging
1854 option specified is ok, we can switch to it, as we know we won't
1855 have to generate any other command-line-related error messages.
1856 (So far we should be still attached to stderr, so we can show on
1857 the terminal any problems to do with processing command line
1858 opts.)
1859
1860 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001861 should be connected to whatever sink has been selected, and we
1862 indiscriminately chuck stuff into it without worrying what the
1863 nature of it is. Oh the wonder of Unix streams. */
1864
njnbe9b47b2005-05-15 16:22:58 +00001865 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1866 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001867
njnbe9b47b2005-05-15 16:22:58 +00001868 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001869
sewardj4cf05692002-10-27 20:28:29 +00001870 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001871 vg_assert(VG_(clo_log_name) == NULL);
1872 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001873 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001874
sewardj4cf05692002-10-27 20:28:29 +00001875 case VgLogTo_File: {
1876 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001877 Int seq = 0;
1878 Int pid = VG_(getpid)();
1879
nethercotef8548672004-06-21 12:42:35 +00001880 vg_assert(VG_(clo_log_name) != NULL);
1881 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001882
nethercote71980f02004-01-24 18:18:54 +00001883 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001884 if (seq == 0)
1885 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001886 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001887 else
1888 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001889 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001890 seq++;
1891
njnbe9b47b2005-05-15 16:22:58 +00001892 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001893 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001894 = VG_(open)(logfilename,
1895 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1896 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001897 if (eventually_log_fd >= 0) {
1898 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001899 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001900 } else {
njnbe9b47b2005-05-15 16:22:58 +00001901 // If the file already existed, we try the next name. If it
1902 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001903 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001904 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001905 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001906 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001907 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001908 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001909 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001910 }
1911 }
1912 }
sewardj603d4102005-01-11 14:01:02 +00001913 break; /* switch (VG_(clo_log_to)) */
1914 }
1915
1916 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001917 vg_assert(VG_(clo_log_name) != NULL);
1918 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001919
1920 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001921 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001922 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1923 VKI_S_IRUSR|VKI_S_IWUSR);
1924 if (eventually_log_fd >= 0) {
1925 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001926 } else {
sewardj603d4102005-01-11 14:01:02 +00001927 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001928 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001929 VG_(clo_log_name));
1930 VG_(bad_option)(
1931 "--log-file-exactly=<file> (didn't work out for some reason.)");
1932 /*NOTREACHED*/
1933 }
1934 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001935 }
1936
1937 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001938 vg_assert(VG_(clo_log_name) != NULL);
1939 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1940 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1941 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001942 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001943 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001944 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001945 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001946 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001947 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001948 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001949 }
nethercotef8548672004-06-21 12:42:35 +00001950 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001951 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001952 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001953 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001954 VG_(message)(Vg_UserMsg,
1955 "Log messages will sent to stderr instead." );
1956 VG_(message)(Vg_UserMsg,
1957 "" );
1958 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001959 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001960 } else {
nethercotef8548672004-06-21 12:42:35 +00001961 vg_assert(eventually_log_fd > 0);
1962 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001963 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001964 }
sewardj73cf3bc2002-11-03 03:20:15 +00001965 break;
1966 }
sewardj4cf05692002-10-27 20:28:29 +00001967 }
1968
njnbe9b47b2005-05-15 16:22:58 +00001969 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1970 // XXX: this is more or less duplicating the behaviour of the calls to
1971 // VG_(safe_fd)() above, although this does not close the original fd.
1972 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1973 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001974 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001975 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001976 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1977 else {
nethercotef8548672004-06-21 12:42:35 +00001978 VG_(clo_log_fd) = eventually_log_fd;
1979 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001980 }
1981
sewardj4cf05692002-10-27 20:28:29 +00001982 /* Ok, the logging sink is running now. Print a suitable preamble.
1983 If logging to file or a socket, write details of parent PID and
1984 command line args, to help people trying to interpret the
1985 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001986
sewardj83adf412002-05-01 01:25:45 +00001987 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001988 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001989 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001990 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001991 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001992 NULL == VG_(details).version
1993 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001994 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001995 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001996
njnd04b7c62002-10-03 14:05:52 +00001997 /* Core details */
1998 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001999 "Using LibVEX rev %s, a library for dynamic binary translation.",
2000 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00002001 VG_(message)(Vg_UserMsg,
sewardj15f7dc02005-05-16 18:30:40 +00002002 "Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.");
sewardjc7025332004-12-13 18:30:39 +00002003 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002004 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002005 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002006 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002007 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002008 }
2009
njnbe9b47b2005-05-15 16:22:58 +00002010 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002011 VG_(message)(Vg_UserMsg, "");
2012 VG_(message)(Vg_UserMsg,
2013 "My PID = %d, parent PID = %d. Prog and args are:",
2014 VG_(getpid)(), VG_(getppid)() );
2015 for (i = 0; i < VG_(client_argc); i++)
2016 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2017 }
2018
sewardjde4a1d02002-03-22 01:27:54 +00002019 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002020 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00002021 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002022 VG_(message)(Vg_DebugMsg, "");
2023 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2024 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002025 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002026 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002027
njn1fd5eb22005-03-13 05:43:23 +00002028 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002029 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002030 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002031 }
nethercotea70f7352004-04-18 12:08:46 +00002032
njn1fd5eb22005-03-13 05:43:23 +00002033 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002034 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2035 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002036 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002037 } else {
2038 #define BUF_LEN 256
2039 Char version_buf[BUF_LEN];
2040 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002041 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002042 if (n > 0) {
2043 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002044 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002045 } else {
njn1fd5eb22005-03-13 05:43:23 +00002046 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002047 }
2048 VG_(close)(fd);
2049 #undef BUF_LEN
2050 }
sewardjde4a1d02002-03-22 01:27:54 +00002051 }
2052
fitzhardinge98abfc72003-12-16 02:05:15 +00002053 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002054 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002055 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002056 needs one, load the default */
2057 static const Char default_supp[] = "default.supp";
2058 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2059 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2060 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2061 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2062 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002063 }
2064}
2065
nethercotef6a1d502004-08-09 12:21:57 +00002066// Build the string for VALGRINDCLO.
2067Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2068{
2069 /* If we're tracing the children, then we need to start it
2070 with our starter+arguments, which are copied into VALGRINDCLO,
2071 except the --exec= option is changed if present.
2072 */
2073 Int i;
2074 Char *exec;
2075 Char *cp;
2076 Char *optvar;
2077 Int optlen, execlen;
2078
2079 // All these allocated blocks are not free - because we're either
2080 // going to exec, or panic when we fail.
2081
2082 // Create --exec= option: "--exec=<exename>"
2083 exec = VG_(arena_malloc)(VG_AR_CORE,
2084 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2085 vg_assert(NULL != exec);
2086 VG_(sprintf)(exec, "--exec=%s", exename);
2087
2088 // Allocate space for optvar (may overestimate by counting --exec twice,
2089 // no matter)
2090 optlen = 1;
2091 for (i = 0; i < vg_argc; i++)
2092 optlen += VG_(strlen)(vg_argv[i]) + 1;
2093 optlen += VG_(strlen)(exec)+1;
2094 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2095
2096 // Copy all valgrind args except the old --exec (if present)
2097 // VG_CLO_SEP is the separator.
2098 cp = optvar;
2099 for (i = 1; i < vg_argc; i++) {
2100 Char *arg = vg_argv[i];
2101
2102 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2103 // don't copy existing --exec= arg
2104 } else if (VG_(strcmp)(arg, "--") == 0) {
2105 // stop at "--"
2106 break;
2107 } else {
2108 // copy non "--exec" arg
2109 Int len = VG_(strlen)(arg);
2110 VG_(memcpy)(cp, arg, len);
2111 cp += len;
2112 *cp++ = VG_CLO_SEP;
2113 }
2114 }
2115 // Add the new --exec= option
2116 execlen = VG_(strlen)(exec);
2117 VG_(memcpy)(cp, exec, execlen);
2118 cp += execlen;
2119 *cp++ = VG_CLO_SEP;
2120
2121 *cp = '\0';
2122
2123 return optvar;
2124}
2125
2126// Build "/proc/self/fd/<execfd>".
2127Char* VG_(build_child_exename)( void )
2128{
2129 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2130 vg_assert(NULL != exename);
2131 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2132 return exename;
2133}
2134
sewardjde4a1d02002-03-22 01:27:54 +00002135
nethercote71980f02004-01-24 18:18:54 +00002136/*====================================================================*/
2137/*=== File descriptor setup ===*/
2138/*====================================================================*/
2139
2140static void setup_file_descriptors(void)
2141{
2142 struct vki_rlimit rl;
2143
2144 /* Get the current file descriptor limits. */
2145 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2146 rl.rlim_cur = 1024;
2147 rl.rlim_max = 1024;
2148 }
2149
2150 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002151 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2152 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002153 } else {
2154 rl.rlim_cur = rl.rlim_max;
2155 }
2156
2157 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002158 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2159 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002160
2161 /* Update the soft limit. */
2162 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2163
nethercotef6a1d502004-08-09 12:21:57 +00002164 if (vgexecfd != -1)
2165 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002166 if (VG_(clexecfd) != -1)
2167 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2168}
2169
nethercote71980f02004-01-24 18:18:54 +00002170/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002171/*=== Initialise program data/text, etc. ===*/
2172/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002173
sewardjb5f6f512005-03-10 23:59:00 +00002174static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2175 UInt dev, UInt ino, ULong foffset,
2176 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002177{
nethercote71980f02004-01-24 18:18:54 +00002178 /* Only record valgrind mappings for now, without loading any
2179 symbols. This is so we know where the free space is before we
2180 start allocating more memory (note: heap is OK, it's just mmap
2181 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002182 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002183 VG_(debugLog)(2, "main",
2184 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002185 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002186 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002187 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2188 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002189 /* update VG_(valgrind_last) if it looks wrong */
2190 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002191 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002192 }
sewardjde4a1d02002-03-22 01:27:54 +00002193}
2194
nethercote71980f02004-01-24 18:18:54 +00002195// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002196Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002197
sewardjb5f6f512005-03-10 23:59:00 +00002198/*
2199 This second pass adds in client mappings, and loads symbol tables
2200 for all interesting mappings. The trouble is that things can
2201 change as we go, because we're calling the Tool to track memory as
2202 we find it.
2203
2204 So for Valgrind mappings, we don't replace any mappings which
2205 aren't still identical (which will include the .so mappings, so we
2206 will load their symtabs)>
2207 */
2208static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2209 UInt dev, UInt ino, ULong foffset,
2210 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002211{
nethercote71980f02004-01-24 18:18:54 +00002212 UInt flags;
2213 Bool is_stack_segment;
2214 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002215
nethercote71980f02004-01-24 18:18:54 +00002216 is_stack_segment
2217 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002218
sewardj8c615892005-04-25 02:38:28 +00002219 VG_(debugLog)(2, "main",
2220 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002221 (void*)start, (void*)(start+size), prot, is_stack_segment,
2222 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 if (is_stack_segment)
2225 flags = SF_STACK | SF_GROWDOWN;
2226 else
2227 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002228
nethercote71980f02004-01-24 18:18:54 +00002229 if (filename != NULL)
2230 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
sewardjb5f6f512005-03-10 23:59:00 +00002232#if 0
2233 // This needs to be fixed properly. jrs 20050307
2234 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2235 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002236
sewardjb5f6f512005-03-10 23:59:00 +00002237 /* We have to be a bit careful about inserting new mappings into
2238 the Valgrind part of the address space. We're actively
2239 changing things as we parse these mappings, particularly in
2240 shadow memory, and so we don't want to overwrite those
2241 changes. Therefore, we only insert/update a mapping if it is
2242 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002243
sewardjb5f6f512005-03-10 23:59:00 +00002244 NOTE: we're only talking about the Segment list mapping
2245 metadata; this doesn't actually mmap anything more. */
2246 if (filename || (s && s->addr == start && s->len == size)) {
2247 flags |= SF_VALGRIND;
2248 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2249 } else {
2250 /* assert range is already mapped */
2251 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2252 }
2253 } else
2254#endif
2255 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2256
2257 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2258 VG_TRACK( new_mem_startup, start, size,
2259 !!(prot & VKI_PROT_READ),
2260 !!(prot & VKI_PROT_WRITE),
2261 !!(prot & VKI_PROT_EXEC));
2262 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002263
nethercote71980f02004-01-24 18:18:54 +00002264 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002265 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002266 vg_assert(0 != r_esp);
2267 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002268 if (0) {
2269 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002270 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002271 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2272 r_esp, start+size);
2273 }
nethercote71980f02004-01-24 18:18:54 +00002274 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002275 // what's this for?
2276 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002277 }
sewardjde4a1d02002-03-22 01:27:54 +00002278}
2279
2280
nethercote71980f02004-01-24 18:18:54 +00002281/*====================================================================*/
2282/*=== Sanity check machinery (permanently engaged) ===*/
2283/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002284
2285/* A fast sanity check -- suitable for calling circa once per
2286 millisecond. */
2287
nethercote885dd912004-08-03 23:14:00 +00002288void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002289{
sewardjb5f6f512005-03-10 23:59:00 +00002290 ThreadId tid;
2291
njn37cea302002-09-30 11:24:00 +00002292 VGP_PUSHCC(VgpCoreCheapSanity);
2293
nethercote27fec902004-06-16 21:26:32 +00002294 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002295
2296 /* --- First do all the tests that we can do quickly. ---*/
2297
nethercote297effd2004-08-02 15:07:57 +00002298 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002299
njn25e49d8e72002-09-23 09:36:25 +00002300 /* Check stuff pertaining to the memory check system. */
2301
2302 /* Check that nobody has spuriously claimed that the first or
2303 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002304 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002305 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002306 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002307 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002308 }
njn25e49d8e72002-09-23 09:36:25 +00002309
2310 /* --- Now some more expensive checks. ---*/
2311
2312 /* Once every 25 times, check some more expensive stuff. */
2313 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002314 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002315 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002316
njn37cea302002-09-30 11:24:00 +00002317 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002318 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002319
2320# if 0
2321 { void zzzmemscan(void); zzzmemscan(); }
2322# endif
2323
nethercote297effd2004-08-02 15:07:57 +00002324 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002325 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002326
2327 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002328 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002329 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002330 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002331 }
sewardjb5f6f512005-03-10 23:59:00 +00002332
2333 /* Check that Segments and /proc/self/maps match up */
2334 //vg_assert(VG_(sanity_check_memory)());
2335
2336 /* Look for stack overruns. Visit all threads. */
2337 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002338 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002339
2340 if (VG_(threads)[tid].status == VgTs_Empty ||
2341 VG_(threads)[tid].status == VgTs_Zombie)
2342 continue;
2343
2344 remains = VGA_(stack_unused)(tid);
2345 if (remains < VKI_PAGE_SIZE)
2346 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2347 tid, remains);
2348 }
2349
njn25e49d8e72002-09-23 09:36:25 +00002350 /*
nethercote297effd2004-08-02 15:07:57 +00002351 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002352 */
njn37cea302002-09-30 11:24:00 +00002353 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002354 }
2355
nethercote27fec902004-06-16 21:26:32 +00002356 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002357 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002358 /* Check sanity of the low-level memory manager. Note that bugs
2359 in the client's code can cause this to fail, so we don't do
2360 this check unless specially asked for. And because it's
2361 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002362 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002363 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002364 }
njn37cea302002-09-30 11:24:00 +00002365 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002366}
nethercote71980f02004-01-24 18:18:54 +00002367
2368
2369/*====================================================================*/
2370/*=== main() ===*/
2371/*====================================================================*/
2372
nethercotec314eba2004-07-15 12:59:41 +00002373/*
2374 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002375 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002376 loads the client executable (and the dynamic linker, if necessary)
2377 into the client part, and calls into Valgrind proper.
2378
2379 The code is careful not to allow spurious mappings to appear in the
2380 wrong parts of the address space. In particular, to make sure
2381 dlopen puts things in the right place, it will pad out the forbidden
2382 chunks of address space so that dlopen is forced to put things where
2383 we want them.
2384
2385 The memory map it creates is:
2386
njn311c5d82005-05-15 21:03:42 +00002387 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002388 | client address space |
2389 : :
2390 : :
2391 | client stack |
2392 client_end +-------------------------+
2393 | redzone |
2394 shadow_base +-------------------------+
2395 | |
nethercote996901a2004-08-03 13:29:09 +00002396 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002397 | (may be 0 sized) |
2398 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002399 valgrind_base +-------------------------+
2400 | kickstart executable |
2401 | valgrind heap vvvvvvvvv| (barely used)
2402 - -
2403 | valgrind .so files |
2404 | and mappings |
2405 - -
2406 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002407 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002408 : kernel :
2409
2410 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2411 VG_(mmap)(), we need to build the segment skip-list, so we know where
2412 we can put things. However, building that structure requires
2413 allocating memory. So we need to a bootstrapping process. It's done
2414 by making VG_(arena_malloc)() have a special static superblock that's
2415 used for the first 1MB's worth of allocations. This is enough to
2416 build the segment skip-list.
2417*/
2418
thughes4ad52d02004-06-27 17:37:21 +00002419
sewardj1cf558c2005-04-25 01:36:56 +00002420/* This may be needed before m_mylibc is OK to run. */
2421static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2422{
2423 while (True) {
2424 if (*s1 == 0 && *s2 == 0) return 0;
2425 if (*s1 == 0) return -1;
2426 if (*s2 == 0) return 1;
2427
2428 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2429 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2430
2431 s1++; s2++;
2432 }
2433}
2434
2435
sewardjb5f6f512005-03-10 23:59:00 +00002436int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002437{
2438 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002439 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002440 const char *exec = NULL;
2441 char *preload; /* tool-specific LD_PRELOAD .so */
2442 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002443 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002444 struct exeinfo info;
2445 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002446 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002447 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002448 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002449 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002450 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002451
2452 //============================================================
2453 // Nb: startup is complex. Prerequisites are shown at every step.
2454 //
2455 // *** Be very careful when messing with the order ***
2456 //============================================================
2457
sewardj1cf558c2005-04-25 01:36:56 +00002458 //--------------------------------------------------------------
2459 // Start up the logging mechanism
2460 // p: none
2461 //--------------------------------------------------------------
2462 /* Start the debugging-log system ASAP. First find out how many
2463 "-d"s were specified. This is a pre-scan of the command line. */
2464 loglevel = 0;
2465 for (i = 1; i < argc; i++) {
2466 if (argv[i][0] != '-')
2467 break;
2468 if (0 == local_strcmp(argv[i], "--"))
2469 break;
2470 if (0 == local_strcmp(argv[i], "-d"))
2471 loglevel++;
2472 }
2473
2474 /* ... and start the debug logger. Now we can safely emit logging
2475 messages all through startup. */
2476 VG_(debugLog_startup)(loglevel, "Stage 2");
2477
nethercotef4928da2004-06-15 10:54:40 +00002478 //============================================================
2479 // Command line argument handling order:
2480 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002481 // (including the tool-specific usage)
2482 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002483 // * Then, if client is missing, abort with error msg
2484 // * Then, if any cmdline args are bad, abort with error msg
2485 //============================================================
2486
fitzhardingeb50068f2004-02-24 23:42:55 +00002487 // Get the current process datasize rlimit, and set it to zero.
2488 // This prevents any internal uses of brk() from having any effect.
2489 // We remember the old value so we can restore it on exec, so that
2490 // child processes will have a reasonable brk value.
2491 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2492 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2493 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002494
2495 // Get the current process stack rlimit.
2496 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2497
nethercote71980f02004-01-24 18:18:54 +00002498 //--------------------------------------------------------------
2499 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002500 // p: none
nethercote71980f02004-01-24 18:18:54 +00002501 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002502 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002503 {
sewardj1fbc1a52005-04-25 02:05:54 +00002504 void* init_sp = argv - 1;
2505 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002506 }
2507
2508 //--------------------------------------------------------------
2509 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002510 // p: none
nethercote71980f02004-01-24 18:18:54 +00002511 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002512 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002513 if (cp != NULL)
2514 VG_(libdir) = cp;
2515 }
2516
2517 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002518 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2519 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002520 // p: none
nethercote71980f02004-01-24 18:18:54 +00002521 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002522 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002523 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002524 pre_process_cmd_line_options(&need_help, &tool, &exec);
2525
2526 //==============================================================
2527 // Nb: once a tool is specified, the tool.so must be loaded even if
2528 // they specified --help or didn't specify a client program.
2529 //==============================================================
2530
2531 //--------------------------------------------------------------
2532 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002533 // p: set-libdir [for VG_(libdir)]
2534 // p: pre_process_cmd_line_options() [for 'tool']
2535 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002536 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002537 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002538
2539 //==============================================================
2540 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002541 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002542 //==============================================================
2543
2544 //--------------------------------------------------------------
2545 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002546 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002547 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002548 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002549 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002550
2551 //--------------------------------------------------------------
2552 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002553 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2554 // p: layout_remaining_space [so there's space]
2555 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002556 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002557 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002558
2559 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002560 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002561 // p: layout_remaining_space() [everything must be mapped in before now]
2562 // p: load_client() [ditto]
2563 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002564 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2565 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002566
2567 //--------------------------------------------------------------
2568 // Set up client's environment
2569 // p: set-libdir [for VG_(libdir)]
2570 // p: load_tool() [for 'preload']
2571 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002572 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002573 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002574
2575 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002576 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002577 // p: load_client() [for 'info']
2578 // p: fix_environment() [for 'env']
2579 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002580 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002581 {
sewardj1fbc1a52005-04-25 02:05:54 +00002582 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002583
sewardj1fbc1a52005-04-25 02:05:54 +00002584 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2585 &client_auxv);
2586 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002587 }
nethercote71980f02004-01-24 18:18:54 +00002588
sewardj1fbc1a52005-04-25 02:05:54 +00002589 VG_(debugLog)(2, "main",
2590 "Client info: "
2591 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2592 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2593 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002594
2595 //==============================================================
2596 // Finished setting up operating environment. Now initialise
2597 // Valgrind. (This is where the old VG_(main)() started.)
2598 //==============================================================
2599
2600 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002601 // setup file descriptors
2602 // p: n/a
2603 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002604 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002605 setup_file_descriptors();
2606
2607 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002608 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002609 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002610 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002611 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002612 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2613
2614 //==============================================================
2615 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2616 //==============================================================
2617
2618 //--------------------------------------------------------------
2619 // Init tool: pre_clo_init, process cmd line, post_clo_init
2620 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002621 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002622 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2623 // p: parse_procselfmaps [so VG segments are setup so tool can
2624 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002625 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002626 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002627 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002628 VG_(sanity_check_needs)();
2629
nethercotef4928da2004-06-15 10:54:40 +00002630 // If --tool and --help/--help-debug was given, now give the core+tool
2631 // help message
nethercotef4928da2004-06-15 10:54:40 +00002632 if (need_help) {
2633 usage(/*--help-debug?*/2 == need_help);
2634 }
nethercotec314eba2004-07-15 12:59:41 +00002635 process_cmd_line_options(client_auxv, tool);
2636
njn51d827b2005-05-09 01:02:08 +00002637 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002638
2639 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002640 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002641 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002642 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002643 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002644 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002645 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002646 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002647 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002648 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002649
sewardj21c6d0f2005-05-02 10:33:44 +00002650#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002651 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002652 // Protect client trampoline page (which is also sysinfo stuff)
2653 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002654 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002655 {
2656 Segment *seg;
2657 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2658 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002659
sewardjb5f6f512005-03-10 23:59:00 +00002660 /* Make sure this segment isn't treated as stack */
2661 seg = VG_(find_segment)(VG_(client_trampoline_code));
2662 if (seg)
2663 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2664 }
sewardj21c6d0f2005-05-02 10:33:44 +00002665#endif
sewardjb5f6f512005-03-10 23:59:00 +00002666
nethercotec314eba2004-07-15 12:59:41 +00002667 //==============================================================
2668 // Can use VG_(map)() after segments set up
2669 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002670
2671 //--------------------------------------------------------------
2672 // Allow GDB attach
2673 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2674 //--------------------------------------------------------------
2675 /* Hook to delay things long enough so we can get the pid and
2676 attach GDB in another shell. */
2677 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002678 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002679 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2680 /* jrs 20050206: I don't understand why this works on x86. On
2681 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2682 work. */
2683 /* do "jump *$eip" to skip this in gdb (x86) */
2684 //VG_(do_syscall0)(__NR_pause);
2685 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002686 }
2687
sewardjb5d320c2005-03-13 18:57:15 +00002688 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002689 // Search for file descriptors that are inherited from our parent
2690 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2691 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002692 if (VG_(clo_track_fds)) {
2693 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002694 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002695 }
nethercote71980f02004-01-24 18:18:54 +00002696
2697 //--------------------------------------------------------------
2698 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002699 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2700 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002701 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002702 VG_(scheduler_init)();
2703
2704 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002705 // Initialise the pthread model
2706 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002707 // load_client() [for 'client_eip']
2708 // setup_client_stack() [for 'sp_at_startup']
2709 // setup_scheduler() [for the rest of state 1 stuff]
2710 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002711 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002712 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002713
2714 // Tell the tool that we just wrote to the registers.
2715 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2716 sizeof(VexGuestArchState));
2717
sewardj2a99cf62004-11-24 10:44:19 +00002718 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002719 // Initialise the pthread model
2720 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002721 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002722 //if (VG_(clo_model_pthreads))
2723 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002724
2725 //--------------------------------------------------------------
2726 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002727 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002728 //--------------------------------------------------------------
2729 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002730 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002731 VG_(sigstartup_actions)();
2732
2733 //--------------------------------------------------------------
2734 // Perhaps we're profiling Valgrind?
2735 // p: process_cmd_line_options() [for VG_(clo_profile)]
2736 // p: others?
2737 //
2738 // XXX: this seems to be broken? It always says the tool wasn't built
2739 // for profiling; vg_profile.c's functions don't seem to be overriding
2740 // vg_dummy_profile.c's?
2741 //
2742 // XXX: want this as early as possible. Looking for --profile
2743 // in pre_process_cmd_line_options() could get it earlier.
2744 //--------------------------------------------------------------
2745 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002746 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002747
2748 VGP_PUSHCC(VgpStartup);
2749
2750 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002751 // Read suppression file
2752 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2753 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002754 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2755 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002756 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002757 }
nethercote71980f02004-01-24 18:18:54 +00002758
2759 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002760 // Initialise translation table and translation cache
2761 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2762 // aren't identified as part of the client, which would waste
2763 // > 20M of virtual address space.]
2764 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002765 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002766 VG_(init_tt_tc)();
2767
2768 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002769 // Read debug info to find glibc entry points to intercept
2770 // p: parse_procselfmaps? [XXX for debug info?]
2771 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2772 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002773 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002774 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002775 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002776
2777 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002778 // Verbosity message
2779 // p: end_rdtsc_calibration [so startup message is printed first]
2780 //--------------------------------------------------------------
2781 if (VG_(clo_verbosity) == 1)
2782 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2783 if (VG_(clo_verbosity) > 0)
2784 VG_(message)(Vg_UserMsg, "");
2785
2786 //--------------------------------------------------------------
2787 // Setup pointercheck
2788 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2789 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002790 if (VG_(clo_pointercheck))
2791 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002792
nethercote71980f02004-01-24 18:18:54 +00002793 //--------------------------------------------------------------
2794 // Run!
2795 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002796 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002797
sewardjb5f6f512005-03-10 23:59:00 +00002798 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002799
sewardj1fbc1a52005-04-25 02:05:54 +00002800 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002801 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002802
sewardjb5f6f512005-03-10 23:59:00 +00002803 abort();
2804}
2805
2806
2807/* Do everything which needs doing when the last thread exits */
2808void VG_(shutdown_actions)(ThreadId tid)
2809{
2810 vg_assert(tid == VG_(master_tid));
2811 vg_assert(VG_(is_running_thread)(tid));
2812
2813 // Wait for all other threads to exit.
2814 VGA_(reap_threads)(tid);
2815
2816 VG_(clo_model_pthreads) = False;
2817
2818 // Clean the client up before the final report
2819 VGA_(final_tidyup)(tid);
2820
2821 // OK, done
2822 VG_(exit_thread)(tid);
2823
2824 /* should be no threads left */
2825 vg_assert(VG_(count_living_threads)() == 0);
2826
2827 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002828 //--------------------------------------------------------------
2829 // Finalisation: cleanup, messages, etc. Order no so important, only
2830 // affects what order the messages come.
2831 //--------------------------------------------------------------
2832 if (VG_(clo_verbosity) > 0)
2833 VG_(message)(Vg_UserMsg, "");
2834
nethercote71980f02004-01-24 18:18:54 +00002835 /* Print out file descriptor summary and stats. */
2836 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002837 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002838
njn95ec8702004-11-22 16:46:13 +00002839 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002840 VG_(show_all_errors)();
2841
njn51d827b2005-05-09 01:02:08 +00002842 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002843
nethercote885dd912004-08-03 23:14:00 +00002844 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002845
2846 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002847 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002848
nethercote71980f02004-01-24 18:18:54 +00002849 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002850 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002851 if (VG_(clo_profile_flags) > 0)
2852 VG_(show_BB_profile)();
2853
sewardj8b635a42004-11-22 19:01:47 +00002854 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002855 if (0)
2856 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002857}
sewardj8b635a42004-11-22 19:01:47 +00002858
sewardjde4a1d02002-03-22 01:27:54 +00002859/*--------------------------------------------------------------------*/
2860/*--- end vg_main.c ---*/
2861/*--------------------------------------------------------------------*/