blob: f026ed67a41d4979ca9e534850f985bfce1bc134 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn20242342005-05-16 23:31:24 +000039#include "pub_core_options.h"
njnd1af0032005-05-29 17:01:48 +000040#include "pub_core_redir.h"
njn2521d322005-05-08 14:45:13 +000041#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000042#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000043#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000044
45#include <dirent.h>
46#include <dlfcn.h>
47#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000048#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000049#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000050#include <string.h>
51#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000052#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000054#include <sys/wait.h>
55#include <unistd.h>
56
sewardjb5f6f512005-03-10 23:59:00 +000057#include "memcheck/memcheck.h"
58
thughes74b8de22004-04-22 18:12:31 +000059#ifndef AT_DCACHEBSIZE
60#define AT_DCACHEBSIZE 19
61#endif /* AT_DCACHEBSIZE */
62
63#ifndef AT_ICACHEBSIZE
64#define AT_ICACHEBSIZE 20
65#endif /* AT_ICACHEBSIZE */
66
67#ifndef AT_UCACHEBSIZE
68#define AT_UCACHEBSIZE 21
69#endif /* AT_UCACHEBSIZE */
70
nethercote71980f02004-01-24 18:18:54 +000071#ifndef AT_SYSINFO
72#define AT_SYSINFO 32
73#endif /* AT_SYSINFO */
74
75#ifndef AT_SYSINFO_EHDR
76#define AT_SYSINFO_EHDR 33
77#endif /* AT_SYSINFO_EHDR */
78
79#ifndef AT_SECURE
80#define AT_SECURE 23 /* secure mode boolean */
81#endif /* AT_SECURE */
82
nethercote71980f02004-01-24 18:18:54 +000083/* redzone gap between client address space and shadow */
84#define REDZONE_SIZE (1 * 1024*1024)
85
86/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000087#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000088
nethercotee2097312004-06-27 12:29:56 +000089/* Proportion of client space for its heap (rest is for mmaps + stack) */
90#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000091
njn14319cc2005-03-13 06:26:22 +000092/* Number of file descriptors that Valgrind tries to reserve for
93 it's own use - just a small constant. */
94#define N_RESERVED_FDS (10)
95
nethercote71980f02004-01-24 18:18:54 +000096/*====================================================================*/
97/*=== Global entities not referenced from generated code ===*/
98/*====================================================================*/
99
sewardjde4a1d02002-03-22 01:27:54 +0000100/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000101 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000102 ------------------------------------------------------------------ */
103
nethercote71980f02004-01-24 18:18:54 +0000104/* Client address space, lowest to highest (see top of ume.c) */
105Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000106Addr VG_(client_end);
107Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000108Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000109Addr VG_(clstk_base);
110Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000111
112Addr VG_(brk_base); /* start of brk */
113Addr VG_(brk_limit); /* current brk */
114
nethercote996901a2004-08-03 13:29:09 +0000115Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000116Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000117
118Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000119
nethercote820bd8c2004-09-07 23:04:49 +0000120// Note that VG_(valgrind_last) names the last byte of the section, whereas
121// the VG_(*_end) vars name the byte one past the end of the section.
122Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
nethercote73b526f2004-10-31 18:48:21 +0000124struct vki_rlimit VG_(client_rlimit_data);
125struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000126
fitzhardinge98abfc72003-12-16 02:05:15 +0000127/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000128static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000129
130/* client executable */
131Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000132
133/* Path to library directory */
134const Char *VG_(libdir) = VG_LIBDIR;
135
136/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000137static Int vg_argc;
138static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000139
thughesad1c9562004-06-26 11:27:52 +0000140/* Application-visible file descriptor limits */
141Int VG_(fd_soft_limit) = -1;
142Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000143
nethercote4ad74312004-10-26 09:59:49 +0000144/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000145 envp[] as extracted from the client's stack at startup-time. */
146Int VG_(client_argc);
147Char** VG_(client_argv);
148Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000149
sewardj51ac0872004-12-21 01:20:49 +0000150
sewardjde4a1d02002-03-22 01:27:54 +0000151/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000152 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000153 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
sewardjde4a1d02002-03-22 01:27:54 +0000155/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000156ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000157
nethercote71980f02004-01-24 18:18:54 +0000158/* Tell the logging mechanism whether we are logging to a file
159 descriptor or a socket descriptor. */
njnbe9b47b2005-05-15 16:22:58 +0000160Bool VG_(logging_to_socket) = False;
nethercote71980f02004-01-24 18:18:54 +0000161
sewardj73cf3bc2002-11-03 03:20:15 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/*====================================================================*/
164/*=== Counters, for profiling purposes only ===*/
165/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000166
sewardjde4a1d02002-03-22 01:27:54 +0000167/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000168static UInt sanity_fast_count = 0;
169static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000170
nethercote3a42fb82004-08-03 18:08:50 +0000171static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000172{
nethercote3a42fb82004-08-03 18:08:50 +0000173 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000174 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000175 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000176 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000177
nethercote3a42fb82004-08-03 18:08:50 +0000178 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000179 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000180
nethercote71980f02004-01-24 18:18:54 +0000181 VG_(message)(Vg_DebugMsg,
182 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000183 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000184
njn9271cbc2005-03-13 05:38:25 +0000185 VG_(print_ExeContext_stats)();
186
nethercote3a42fb82004-08-03 18:08:50 +0000187 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000188 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000189 VG_(message)(Vg_DebugMsg, "");
190 VG_(message)(Vg_DebugMsg,
191 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000192 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000193 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000194 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000195 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000196 }
nethercote71980f02004-01-24 18:18:54 +0000197}
198
199
200/*====================================================================*/
201/*=== Miscellaneous global functions ===*/
202/*====================================================================*/
203
nethercotecf97ffb2004-09-09 13:40:31 +0000204static Int ptrace_setregs(Int pid, ThreadId tid)
205{
sewardj2a99cf62004-11-24 10:44:19 +0000206 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000207}
208
nethercote04d0fbc2004-01-26 16:48:06 +0000209/* Start debugger and get it to attach to this process. Called if the
210 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000211 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000212 meaningfully get the debugger to continue the program, though; to
213 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000214void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000215{
216 Int pid;
217
218 if ((pid = fork()) == 0) {
219 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000220 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000221
222 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000223 Int status;
224 Int res;
225
nethercote71980f02004-01-24 18:18:54 +0000226 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
227 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000228 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000229 kill(pid, SIGSTOP) == 0 &&
230 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000231 Char pidbuf[15];
232 Char file[30];
233 Char buf[100];
234 Char *bufptr;
235 Char *cmdptr;
236
237 VG_(sprintf)(pidbuf, "%d", pid);
238 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
239
240 bufptr = buf;
241 cmdptr = VG_(clo_db_command);
242
243 while (*cmdptr) {
244 switch (*cmdptr) {
245 case '%':
246 switch (*++cmdptr) {
247 case 'f':
248 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
249 bufptr += VG_(strlen)(file);
250 cmdptr++;
251 break;
252 case 'p':
253 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
254 bufptr += VG_(strlen)(pidbuf);
255 cmdptr++;
256 break;
257 default:
258 *bufptr++ = *cmdptr++;
259 break;
260 }
261 break;
262 default:
263 *bufptr++ = *cmdptr++;
264 break;
265 }
266 }
267
268 *bufptr++ = '\0';
269
270 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000271 res = VG_(system)(buf);
272 if (res == 0) {
273 VG_(message)(Vg_UserMsg, "");
274 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000275 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000276 } else {
277 VG_(message)(Vg_UserMsg, "Apparently failed!");
278 VG_(message)(Vg_UserMsg, "");
279 }
280 }
281
nethercote73b526f2004-10-31 18:48:21 +0000282 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000283 VG_(waitpid)(pid, &status, 0);
284 }
285}
286
287
288/* Print some helpful-ish text about unimplemented things, and give
289 up. */
290void VG_(unimplemented) ( Char* msg )
291{
292 VG_(message)(Vg_UserMsg, "");
293 VG_(message)(Vg_UserMsg,
294 "Valgrind detected that your program requires");
295 VG_(message)(Vg_UserMsg,
296 "the following unimplemented functionality:");
297 VG_(message)(Vg_UserMsg, " %s", msg);
298 VG_(message)(Vg_UserMsg,
299 "This may be because the functionality is hard to implement,");
300 VG_(message)(Vg_UserMsg,
301 "or because no reasonable program would behave this way,");
302 VG_(message)(Vg_UserMsg,
303 "or because nobody has yet needed it. In any case, let us know at");
304 VG_(message)(Vg_UserMsg,
305 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
306 VG_(message)(Vg_UserMsg,
307 "");
308 VG_(message)(Vg_UserMsg,
309 "Valgrind has to exit now. Sorry. Bye!");
310 VG_(message)(Vg_UserMsg,
311 "");
312 VG_(pp_sched_status)();
313 VG_(exit)(1);
314}
315
sewardj2a99cf62004-11-24 10:44:19 +0000316/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000317Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000318{
njncf45fd42004-11-24 16:30:22 +0000319 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000320}
321
njn67516132005-03-22 04:02:43 +0000322Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000323{
324 return INSTR_PTR( VG_(threads)[tid].arch );
325}
326
njnea4b28c2004-11-30 16:04:58 +0000327
nethercote71980f02004-01-24 18:18:54 +0000328/*====================================================================*/
329/*=== Check we were launched by stage 1 ===*/
330/*====================================================================*/
331
332/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000333static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000334{
nethercoteebf1d862004-11-01 18:22:05 +0000335 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000336 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000337
338 for (; auxv->a_type != AT_NULL; auxv++)
339 switch(auxv->a_type) {
340 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000341 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000342 found |= 1;
343 break;
344
345 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000346 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000347 found |= 2;
348 break;
nethercote7f390022004-10-25 17:18:24 +0000349
350 case AT_PHDR:
351 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
352 break;
nethercote71980f02004-01-24 18:18:54 +0000353 }
354
nethercote361a14e2004-07-26 11:11:56 +0000355 if ( found != (1|2) ) {
356 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000357 exit(127);
358 }
nethercote31779c72004-07-30 21:50:15 +0000359 vg_assert(padfile >= 0);
360 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000361}
362
363
364/*====================================================================*/
365/*=== Address space determination ===*/
366/*====================================================================*/
367
nethercote7f390022004-10-25 17:18:24 +0000368extern char _start[];
369
nethercote31779c72004-07-30 21:50:15 +0000370static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000371{
nethercotea3c3cf22004-11-01 18:38:00 +0000372 Int ires;
373 void* vres;
374 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000375
nethercote7f390022004-10-25 17:18:24 +0000376 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
377 // this is a workable approximation
378 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000379 VG_(valgrind_base) = PGROUNDDN(&_start);
380 }
381
nethercote820bd8c2004-09-07 23:04:49 +0000382 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000383
nethercote31779c72004-07-30 21:50:15 +0000384 // This gives the client the largest possible address space while
385 // taking into account the tool's shadow needs.
386 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000387 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000388 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000389 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000390 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000391 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000392 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote31779c72004-07-30 21:50:15 +0000394 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000395 VG_(shadow_end) = VG_(valgrind_base);
396 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000397
nethercotee2097312004-06-27 12:29:56 +0000398#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
399
nethercote71980f02004-01-24 18:18:54 +0000400 if (0)
nethercotee2097312004-06-27 12:29:56 +0000401 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000402 "client_base %p (%dMB)\n"
403 "client_mapbase %p (%dMB)\n"
404 "client_end %p (%dMB)\n"
405 "shadow_base %p (%dMB)\n"
406 "shadow_end %p\n"
407 "valgrind_base %p (%dMB)\n"
408 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000409 VG_(client_base), SEGSIZE(client_base, client_mapbase),
410 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
411 VG_(client_end), SEGSIZE(client_end, shadow_base),
412 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000413 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000414 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
415 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000416 );
417
418#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000419
420 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000421 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000422 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000423 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000424
425 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000426 ires = munmap((void*)VG_(client_base), client_size);
427 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000428
429 // Map shadow memory.
430 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000431 if (shadow_size != 0) {
432 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000433 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000434 if ((void*)-1 == vres) {
435 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000436 "valgrind: Could not allocate address space (%p bytes)\n"
437 "valgrind: for shadow memory\n"
438 "valgrind: Possible causes:\n"
439 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
440 "valgrind: needs at least 1.5GB swap space.\n"
441 "valgrind: - Or, your virtual memory size may be limited (check\n"
442 "valgrind: with 'ulimit -v').\n"
443 "valgrind: - Or, your system may use a kernel that provides only a\n"
444 "valgrind: too-small (eg. 2GB) user address space.\n"
445 , (void*)shadow_size
446 );
nethercoted4722622004-08-30 19:36:42 +0000447 exit(1);
448 }
nethercotee567e702004-07-10 17:49:17 +0000449 }
nethercote71980f02004-01-24 18:18:54 +0000450}
451
452/*====================================================================*/
453/*=== Command line setup ===*/
454/*====================================================================*/
455
nethercote71980f02004-01-24 18:18:54 +0000456static char* get_file_clo(char* dir)
457{
458# define FLEN 512
459 Int fd, n;
460 struct stat s1;
461 char* f_clo = NULL;
462 char filename[FLEN];
463
464 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
465 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
466 if ( fd > 0 ) {
467 if ( 0 == fstat(fd, &s1) ) {
468 f_clo = malloc(s1.st_size+1);
469 vg_assert(f_clo);
470 n = read(fd, f_clo, s1.st_size);
471 if (n == -1) n = 0;
472 f_clo[n] = '\0';
473 }
474 close(fd);
475 }
476 return f_clo;
477# undef FLEN
478}
479
480static Int count_args(char* s)
481{
482 Int n = 0;
483 if (s) {
484 char* cp = s;
485 while (True) {
486 // We have alternating sequences: blanks, non-blanks, blanks...
487 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000488 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000489 if ( !*cp ) break;
490 n++;
njn0c0f32a2005-03-26 04:14:01 +0000491 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000492 }
493 }
494 return n;
495}
496
497/* add args out of environment, skipping multiple spaces and -- args */
498static char** copy_args( char* s, char** to )
499{
500 if (s) {
501 char* cp = s;
502 while (True) {
503 // We have alternating sequences: blanks, non-blanks, blanks...
504 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000505 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000506 if ( !*cp ) break;
507 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000508 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000509 if ( *cp ) *cp++ = '\0'; // terminate if necessary
510 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
511 }
512 }
513 return to;
514}
515
516// Augment command line with arguments from environment and .valgrindrc
517// files.
518static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
519{
nethercotef6a1d502004-08-09 12:21:57 +0000520 int vg_argc0 = *vg_argc_inout;
521 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000522
523 char* env_clo = getenv(VALGRINDOPTS);
524 char* f1_clo = get_file_clo( getenv("HOME") );
525 char* f2_clo = get_file_clo(".");
526
527 /* copy any extra args from file or environment, if present */
528 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
529 /* ' ' separated extra options */
530 char **from;
531 char **to;
thughescaca0022004-09-13 10:20:34 +0000532 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
533
534 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
535
nethercote71980f02004-01-24 18:18:54 +0000536 env_arg_count = count_args(env_clo);
537 f1_arg_count = count_args(f1_clo);
538 f2_arg_count = count_args(f2_clo);
539
540 if (0)
541 printf("extra-argc=%d %d %d\n",
542 env_arg_count, f1_arg_count, f2_arg_count);
543
544 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000545 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000546 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000547 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000548 vg_assert(vg_argv0);
549 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000550
551 /* copy argv[0] */
552 *to++ = *from++;
553
554 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
555 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
556 * to override less local ones. */
557 to = copy_args(f1_clo, to);
558 to = copy_args(env_clo, to);
559 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000560
561 // Free memory
562 free(f1_clo);
563 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000564
565 /* copy original arguments, stopping at command or -- */
566 while (*from) {
567 if (**from != '-')
568 break;
569 if (VG_STREQ(*from, "--")) {
570 from++; /* skip -- */
571 break;
572 }
573 *to++ = *from++;
574 }
575
576 /* add -- */
577 *to++ = "--";
578
nethercotef6a1d502004-08-09 12:21:57 +0000579 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000580
581 /* copy rest of original command line, then NULL */
582 while (*from) *to++ = *from++;
583 *to = NULL;
584 }
585
nethercotef6a1d502004-08-09 12:21:57 +0000586 *vg_argc_inout = vg_argc0;
587 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000588}
589
nethercotef6a1d502004-08-09 12:21:57 +0000590#define VG_CLO_SEP '\01'
591
nethercote71980f02004-01-24 18:18:54 +0000592static void get_command_line( int argc, char** argv,
593 Int* vg_argc_out, Char*** vg_argv_out,
594 char*** cl_argv_out )
595{
nethercotef6a1d502004-08-09 12:21:57 +0000596 int vg_argc0;
597 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000598 char** cl_argv;
599 char* env_clo = getenv(VALGRINDCLO);
600
601 if (env_clo != NULL && *env_clo != '\0') {
602 char *cp;
603 char **cpp;
604
nethercotef6a1d502004-08-09 12:21:57 +0000605 /* OK, VALGRINDCLO is set, which means we must be a child of another
606 Valgrind process using --trace-children, so we're getting all our
607 arguments from VALGRINDCLO, and the entire command line belongs to
608 the client (including argv[0]) */
609 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000610 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000611 if (*cp == VG_CLO_SEP)
612 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000613
nethercotef6a1d502004-08-09 12:21:57 +0000614 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
615 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000616
nethercotef6a1d502004-08-09 12:21:57 +0000617 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000618
619 *cpp++ = "valgrind"; /* nominal argv[0] */
620 *cpp++ = env_clo;
621
nethercotef6a1d502004-08-09 12:21:57 +0000622 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000623 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000624 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000625 *cp++ = '\0'; /* chop it up in place */
626 *cpp++ = cp;
627 }
628 }
629 *cpp = NULL;
630 cl_argv = argv;
631
632 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000633 Bool noaugment = False;
634
nethercote71980f02004-01-24 18:18:54 +0000635 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000636 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000637
nethercotef6a1d502004-08-09 12:21:57 +0000638 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000639 Char* arg = argv[vg_argc0];
640 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000641 break;
sewardjb5f6f512005-03-10 23:59:00 +0000642 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000643 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000644 break;
645 }
njn45270a22005-03-27 01:00:11 +0000646 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000647 }
nethercotef6a1d502004-08-09 12:21:57 +0000648 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000649
650 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000651 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000652 those extra args will already be present in VALGRINDCLO.
653 (We also don't do it when --command-line-only=yes.) */
654 if (!noaugment)
655 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000656 }
657
658 if (0) {
659 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000660 for (i = 0; i < vg_argc0; i++)
661 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000662 }
663
nethercotef6a1d502004-08-09 12:21:57 +0000664 *vg_argc_out = vg_argc0;
665 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000666 *cl_argv_out = cl_argv;
667}
668
669
670/*====================================================================*/
671/*=== Environment and stack setup ===*/
672/*====================================================================*/
673
674/* Scan a colon-separated list, and call a function on each element.
675 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000676 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000677 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000678
679 This routine will return True if (*func) returns True and False if
680 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000681*/
thughes4ad52d02004-06-27 17:37:21 +0000682static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000683{
684 char *cp, *entry;
685 int end;
686
687 if (colsep == NULL ||
688 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000689 return False;
nethercote71980f02004-01-24 18:18:54 +0000690
691 entry = cp = colsep;
692
693 do {
694 end = (*cp == '\0');
695
696 if (*cp == ':' || *cp == '\0') {
697 char save = *cp;
698
699 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000700 if ((*func)(entry)) {
701 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000702 return True;
thughes21942d92004-07-12 09:35:37 +0000703 }
nethercote71980f02004-01-24 18:18:54 +0000704 *cp = save;
705 entry = cp+1;
706 }
707 cp++;
708 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000709
710 return False;
711}
712
nethercote71980f02004-01-24 18:18:54 +0000713/* Prepare the client's environment. This is basically a copy of our
714 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000715 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000716
sewardjb5f6f512005-03-10 23:59:00 +0000717 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000718
719 Yummy. String hacking in C.
720
721 If this needs to handle any more variables it should be hacked
722 into something table driven.
723 */
724static char **fix_environment(char **origenv, const char *preload)
725{
726 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000727 static const char ld_preload[] = "LD_PRELOAD=";
728 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000729 static const int ld_preload_len = sizeof(ld_preload)-1;
730 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
731 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000732 char *inject_path;
733 int inject_path_len;
734 int vgliblen = strlen(VG_(libdir));
735 char **cpp;
736 char **ret;
737 int envc;
738 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
739
740 /* Find the vg_inject.so; also make room for the tool preload
741 library */
742 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
743 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000744 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000745
746 if (preload)
747 snprintf(inject_path, inject_path_len, "%s/%s:%s",
748 VG_(libdir), inject_so, preload);
749 else
750 snprintf(inject_path, inject_path_len, "%s/%s",
751 VG_(libdir), inject_so);
752
753 /* Count the original size of the env */
754 envc = 0; /* trailing NULL */
755 for (cpp = origenv; cpp && *cpp; cpp++)
756 envc++;
757
758 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000759 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000760 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000761
762 /* copy it over */
763 for (cpp = ret; *origenv; )
764 *cpp++ = *origenv++;
765 *cpp = NULL;
766
767 vg_assert(envc == (cpp - ret));
768
769 /* Walk over the new environment, mashing as we go */
770 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000771 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000772 int len = strlen(*cpp) + inject_path_len;
773 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000774 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000775
776 snprintf(cp, len, "%s%s:%s",
777 ld_preload, inject_path, (*cpp)+ld_preload_len);
778
779 *cpp = cp;
780
781 ld_preload_done = 1;
782 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
783 *cpp = "";
784 }
785 }
786
787 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000788 if (!ld_preload_done) {
789 int len = ld_preload_len + inject_path_len;
790 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000791 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000792
793 snprintf(cp, len, "%s%s",
794 ld_preload, inject_path);
795
796 ret[envc++] = cp;
797 }
798
sewardjb5f6f512005-03-10 23:59:00 +0000799 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000800 ret[envc] = NULL;
801
802 return ret;
803}
804
805extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000806
807/* Add a string onto the string table, and return its address */
808static char *copy_str(char **tab, const char *str)
809{
810 char *cp = *tab;
811 char *orig = cp;
812
813 while(*str)
814 *cp++ = *str++;
815 *cp++ = '\0';
816
817 if (0)
nethercote545fe672004-11-01 16:52:43 +0000818 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000819
820 *tab = cp;
821
822 return orig;
823}
824
825/*
826 This sets up the client's initial stack, containing the args,
827 environment and aux vector.
828
829 The format of the stack is:
830
831 higher address +-----------------+
832 | Trampoline code |
833 +-----------------+
834 | |
835 : string table :
836 | |
837 +-----------------+
838 | AT_NULL |
839 - -
840 | auxv |
841 +-----------------+
842 | NULL |
843 - -
844 | envp |
845 +-----------------+
846 | NULL |
847 - -
848 | argv |
849 +-----------------+
850 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000851 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000852 | undefined |
853 : :
854 */
nethercotec25c4492004-10-18 11:52:17 +0000855static Addr setup_client_stack(void* init_sp,
856 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000857 const struct exeinfo *info,
858 UInt** client_auxv)
859{
nethercotee567e702004-07-10 17:49:17 +0000860 void* res;
nethercote71980f02004-01-24 18:18:54 +0000861 char **cpp;
862 char *strtab; /* string table */
863 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000864 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000865 struct ume_auxv *auxv;
866 const struct ume_auxv *orig_auxv;
867 const struct ume_auxv *cauxv;
868 unsigned stringsize; /* total size of strings in bytes */
869 unsigned auxsize; /* total size of auxv in bytes */
870 int argc; /* total argc */
871 int envc; /* total number of env vars */
872 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000873 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000874
875 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000876 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000877
878 /* ==================== compute sizes ==================== */
879
880 /* first of all, work out how big the client stack will be */
881 stringsize = 0;
882
883 /* paste on the extra args if the loader needs them (ie, the #!
884 interpreter and its argument) */
885 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000886 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000887 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000888 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000889 }
nethercoted6a56872004-07-26 15:32:47 +0000890 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000891 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000892 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000893 }
894
895 /* now scan the args we're given... */
896 for (cpp = orig_argv; *cpp; cpp++) {
897 argc++;
898 stringsize += strlen(*cpp) + 1;
899 }
900
901 /* ...and the environment */
902 envc = 0;
903 for (cpp = orig_envp; cpp && *cpp; cpp++) {
904 envc++;
905 stringsize += strlen(*cpp) + 1;
906 }
907
908 /* now, how big is the auxv? */
909 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
910 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
911 if (cauxv->a_type == AT_PLATFORM)
912 stringsize += strlen(cauxv->u.a_ptr) + 1;
913 auxsize += sizeof(*cauxv);
914 }
915
916 /* OK, now we know how big the client stack is */
917 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000918 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000919 sizeof(char **)*argc + /* argv */
920 sizeof(char **) + /* terminal NULL */
921 sizeof(char **)*envc + /* envp */
922 sizeof(char **) + /* terminal NULL */
923 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000924 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000925 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000926
sewardj79048ce2005-02-18 08:28:32 +0000927 if (0) VG_(printf)("stacksize = %d\n", stacksize);
928
nethercotef84f6952004-07-15 14:58:33 +0000929 // decide where stack goes!
930 VG_(clstk_end) = VG_(client_end);
931
nethercote73b526f2004-10-31 18:48:21 +0000932 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000933
nethercote71980f02004-01-24 18:18:54 +0000934 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000935 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000936 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
937
nethercote71980f02004-01-24 18:18:54 +0000938 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000939 stringbase = strtab = (char *)(VG_(client_trampoline_code)
940 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000941
942 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000943
sewardj79048ce2005-02-18 08:28:32 +0000944 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000945 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000946 "clstk_base %p\n"
947 "clstk_end %p\n",
948 stringsize, auxsize, stacksize,
949 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000950
nethercote71980f02004-01-24 18:18:54 +0000951 /* ==================== allocate space ==================== */
952
953 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000954 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000955 PROT_READ | PROT_WRITE | PROT_EXEC,
956 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
957 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000958
959 /* ==================== copy client stack ==================== */
960
nethercotea3c3cf22004-11-01 18:38:00 +0000961 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000962
963 /* --- argc --- */
964 *ptr++ = argc; /* client argc */
965
966 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000967 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000968 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000969 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000970 }
nethercoted6a56872004-07-26 15:32:47 +0000971 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000972 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000973 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000974 }
975 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000976 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000977 }
978 *ptr++ = 0;
979
980 /* --- envp --- */
981 VG_(client_envp) = (Char **)ptr;
982 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000983 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000984 *ptr++ = 0;
985
986 /* --- auxv --- */
987 auxv = (struct ume_auxv *)ptr;
988 *client_auxv = (UInt *)auxv;
989
990 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
991 /* copy the entry... */
992 *auxv = *orig_auxv;
993
994 /* ...and fix up the copy */
995 switch(auxv->a_type) {
996 case AT_PHDR:
997 if (info->phdr == 0)
998 auxv->a_type = AT_IGNORE;
999 else
1000 auxv->u.a_val = info->phdr;
1001 break;
1002
1003 case AT_PHNUM:
1004 if (info->phdr == 0)
1005 auxv->a_type = AT_IGNORE;
1006 else
1007 auxv->u.a_val = info->phnum;
1008 break;
1009
1010 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001011 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001012 break;
1013
1014 case AT_PLATFORM: /* points to a platform description string */
1015 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1016 break;
1017
1018 case AT_ENTRY:
1019 auxv->u.a_val = info->entry;
1020 break;
1021
1022 case AT_IGNORE:
1023 case AT_EXECFD:
1024 case AT_PHENT:
1025 case AT_PAGESZ:
1026 case AT_FLAGS:
1027 case AT_NOTELF:
1028 case AT_UID:
1029 case AT_EUID:
1030 case AT_GID:
1031 case AT_EGID:
1032 case AT_CLKTCK:
1033 case AT_HWCAP:
1034 case AT_FPUCW:
1035 case AT_DCACHEBSIZE:
1036 case AT_ICACHEBSIZE:
1037 case AT_UCACHEBSIZE:
1038 /* All these are pointerless, so we don't need to do anything
1039 about them. */
1040 break;
1041
1042 case AT_SECURE:
1043 /* If this is 1, then it means that this program is running
1044 suid, and therefore the dynamic linker should be careful
1045 about LD_PRELOAD, etc. However, since stage1 (the thing
1046 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001047 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001048 set AT_SECURE to 0. */
1049 auxv->u.a_val = 0;
1050 break;
1051
1052 case AT_SYSINFO:
1053 /* Leave this unmolested for now, but we'll update it later
1054 when we set up the client trampoline code page */
1055 break;
1056
1057 case AT_SYSINFO_EHDR:
1058 /* Trash this, because we don't reproduce it */
1059 auxv->a_type = AT_IGNORE;
1060 break;
1061
1062 default:
1063 /* stomp out anything we don't know about */
1064 if (0)
nethercote545fe672004-11-01 16:52:43 +00001065 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001066 auxv->a_type = AT_IGNORE;
1067 break;
1068
1069 }
1070 }
1071 *auxv = *orig_auxv;
1072 vg_assert(auxv->a_type == AT_NULL);
1073
njnc6168192004-11-29 13:54:10 +00001074// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1075// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001076#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001077 /* --- trampoline page --- */
1078 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1079 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001080#endif
nethercotef84f6952004-07-15 14:58:33 +00001081
nethercote71980f02004-01-24 18:18:54 +00001082 vg_assert((strtab-stringbase) == stringsize);
1083
nethercote5ee67ca2004-06-22 14:00:09 +00001084 /* We know the initial ESP is pointing at argc/argv */
1085 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001086 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001087
sewardj79048ce2005-02-18 08:28:32 +00001088 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001089 return cl_esp;
1090}
1091
1092/*====================================================================*/
1093/*=== Find executable ===*/
1094/*====================================================================*/
1095
thughes4ad52d02004-06-27 17:37:21 +00001096static const char* executable_name;
1097
1098static Bool match_executable(const char *entry) {
1099 char buf[strlen(entry) + strlen(executable_name) + 2];
1100
1101 /* empty PATH element means . */
1102 if (*entry == '\0')
1103 entry = ".";
1104
1105 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1106
1107 if (access(buf, R_OK|X_OK) == 0) {
1108 executable_name = strdup(buf);
1109 vg_assert(NULL != executable_name);
1110 return True;
1111 }
1112 return False;
1113}
1114
nethercote71980f02004-01-24 18:18:54 +00001115static const char* find_executable(const char* exec)
1116{
1117 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001118 executable_name = exec;
1119 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001120 /* no '/' - we need to search the path */
1121 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001122 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001123 }
thughes4ad52d02004-06-27 17:37:21 +00001124 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001125}
1126
1127
1128/*====================================================================*/
1129/*=== Loading tools ===*/
1130/*====================================================================*/
1131
1132static void list_tools(void)
1133{
1134 DIR *dir = opendir(VG_(libdir));
1135 struct dirent *de;
1136 int first = 1;
1137
1138 if (dir == NULL) {
1139 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001140 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001141 return;
1142 }
1143
nethercotef4928da2004-06-15 10:54:40 +00001144 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001145 int len = strlen(de->d_name);
1146
njn063c5402004-11-22 16:58:05 +00001147 /* look for vgtool_TOOL.so names */
1148 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1149 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001150 VG_STREQ(de->d_name + len - 3, ".so")) {
1151 if (first) {
1152 fprintf(stderr, "Available tools:\n");
1153 first = 0;
1154 }
1155 de->d_name[len-3] = '\0';
1156 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001157 }
1158 }
1159
1160 closedir(dir);
1161
1162 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001163 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1164 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001165}
1166
1167
1168/* Find and load a tool, and check it looks ok. Also looks to see if there's
1169 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001170static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001171 ToolInfo** toolinfo_out, char **preloadpath_out )
1172{
1173 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001174 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001175 char buf[len];
1176 void* handle;
1177 ToolInfo* toolinfo;
1178 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001179
1180 // XXX: allowing full paths for --tool option -- does it make sense?
1181 // Doesn't allow for vgpreload_<tool>.so.
1182
1183 if (strchr(toolname, '/') != 0) {
1184 /* toolname contains '/', and so must be a pathname */
1185 handle = dlopen(toolname, RTLD_NOW);
1186 } else {
1187 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001188 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001189 handle = dlopen(buf, RTLD_NOW);
1190
1191 if (handle != NULL) {
1192 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1193 if (access(buf, R_OK) == 0) {
1194 preloadpath = strdup(buf);
1195 vg_assert(NULL != preloadpath);
1196 }
1197 }
1198 }
1199
1200 ok = (NULL != handle);
1201 if (!ok) {
1202 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1203 goto bad_load;
1204 }
1205
njn51d827b2005-05-09 01:02:08 +00001206 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001207 ok = (NULL != toolinfo);
1208 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001209 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001210 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1211 goto bad_load;
1212 }
1213
1214 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001215 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1216 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001217 if (!ok) {
1218 fprintf(stderr, "Error:\n"
1219 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001220 " Interface version used by core is: %d (size %d)\n"
1221 " Interface version used by tool is: %d (size %d)\n"
1222 " The version numbers must match.\n",
1223 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001224 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001225 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001226 toolinfo->sizeof_ToolInfo);
1227 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001228 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001229 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001230 else
nethercote996901a2004-08-03 13:29:09 +00001231 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001232 goto bad_load;
1233 }
1234
njn8a97c6d2005-03-31 04:37:24 +00001235 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001236 *toolinfo_out = toolinfo;
1237 *preloadpath_out = preloadpath;
1238 return;
1239
1240
1241 bad_load:
1242 if (handle != NULL)
1243 dlclose(handle);
1244
nethercotef4928da2004-06-15 10:54:40 +00001245 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001246 list_tools();
1247 exit(127);
1248}
1249
nethercotef4928da2004-06-15 10:54:40 +00001250
1251/*====================================================================*/
1252/*=== Command line errors ===*/
1253/*====================================================================*/
1254
njnbe9b47b2005-05-15 16:22:58 +00001255static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001256{
njnbe9b47b2005-05-15 16:22:58 +00001257 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001258 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001259}
1260
1261void VG_(bad_option) ( Char* opt )
1262{
njnbe9b47b2005-05-15 16:22:58 +00001263 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001264 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001265 VG_(printf)("valgrind: Use --help for more information.\n");
1266 VG_(exit)(1);
1267}
1268
nethercotef4928da2004-06-15 10:54:40 +00001269static void missing_prog ( void )
1270{
njnbe9b47b2005-05-15 16:22:58 +00001271 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001272 VG_(printf)("valgrind: no program specified\n");
1273 VG_(printf)("valgrind: Use --help for more information.\n");
1274 VG_(exit)(1);
1275}
1276
1277static void config_error ( Char* msg )
1278{
njnbe9b47b2005-05-15 16:22:58 +00001279 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001280 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1281 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1282 VG_(exit)(1);
1283}
1284
1285
nethercote71980f02004-01-24 18:18:54 +00001286/*====================================================================*/
1287/*=== Loading the client ===*/
1288/*====================================================================*/
1289
nethercotef4928da2004-06-15 10:54:40 +00001290static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001291 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1292{
1293 // If they didn't specify an executable with --exec, and didn't specify
1294 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001295 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001296 if (cl_argv[0] == NULL ||
1297 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1298 {
nethercotef4928da2004-06-15 10:54:40 +00001299 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001300 }
1301 }
1302
1303 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001304 info->exe_base = VG_(client_base);
1305 info->exe_end = VG_(client_end);
1306 info->argv = cl_argv;
1307
nethercotef4928da2004-06-15 10:54:40 +00001308 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001309 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001310 // Totally zero 'info' before continuing.
1311 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001312 } else {
1313 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001314 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001315 ret = do_exec(exec, info);
1316 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001317 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1318 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001319 exit(127);
1320 }
1321 }
1322
1323 /* Copy necessary bits of 'info' that were filled in */
1324 *client_eip = info->init_eip;
1325 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1326}
1327
nethercote969ecf12004-10-13 17:29:01 +00001328/*====================================================================*/
1329/*=== Address space unpadding ===*/
1330/*====================================================================*/
1331
1332typedef struct {
1333 char* killpad_start;
1334 char* killpad_end;
1335 struct stat* killpad_padstat;
1336} killpad_extra;
1337
1338static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1339 int maj, int min, int ino, void* ex)
1340{
1341 killpad_extra* extra = ex;
1342 void *b, *e;
1343 int res;
1344
1345 vg_assert(NULL != extra->killpad_padstat);
1346
1347 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1348 extra->killpad_padstat->st_ino != ino)
1349 return 1;
1350
1351 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1352 return 1;
1353
1354 if (segstart <= extra->killpad_start)
1355 b = extra->killpad_start;
1356 else
1357 b = segstart;
1358
1359 if (segend >= extra->killpad_end)
1360 e = extra->killpad_end;
1361 else
1362 e = segend;
1363
1364 res = munmap(b, (char *)e-(char *)b);
1365 vg_assert(0 == res);
1366
1367 return 1;
1368}
1369
1370// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001371static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001372{
1373 static struct stat padstat;
1374 killpad_extra extra;
1375 int res;
1376
sewardjb5f6f512005-03-10 23:59:00 +00001377 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001378
1379 res = fstat(padfile, &padstat);
1380 vg_assert(0 == res);
1381 extra.killpad_padstat = &padstat;
1382 extra.killpad_start = start;
1383 extra.killpad_end = end;
1384 foreach_map(killpad, &extra);
1385}
1386
sewardj2c5ffbe2005-03-12 13:32:06 +00001387static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001388{
1389 int res = close(padfile);
1390 vg_assert(0 == res);
1391}
1392
sewardj71bc3cb2005-05-19 00:25:45 +00001393/*====================================================================*/
1394/*=== Command-line: variables, processing, etc ===*/
1395/*====================================================================*/
1396
1397// See pub_{core,tool}_options.h for explanations of all these.
1398
sewardj2c5ffbe2005-03-12 13:32:06 +00001399static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001400{
njn25e49d8e72002-09-23 09:36:25 +00001401 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001402"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001403"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001404" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001405" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001406" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001407" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001408" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001409" -q --quiet run silently; only print error msgs\n"
1410" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001411" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001412" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001413" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001414" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001415"\n"
1416" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001417" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001418" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001419" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001420" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001421" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001422"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001423" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001424" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1425" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001426" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001427" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001428" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001429" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001430" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1431" --show-below-main=no|yes continue stack traces below main() [no]\n"
1432" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001433" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001434" --db-attach=no|yes start debugger when errors detected? [no]\n"
1435" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1436" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001437" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1438" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001439"\n";
njn7cf0bd32002-06-08 13:36:03 +00001440
njn25e49d8e72002-09-23 09:36:25 +00001441 Char* usage2 =
1442"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001443" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001444" --sanity-level=<number> level of sanity checking to do [1]\n"
1445" --single-step=no|yes translate each instr separately? [no]\n"
1446" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001447" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001448" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001449" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1450" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001451" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001452" --trace-syscalls=no|yes show all system calls? [no]\n"
1453" --trace-signals=no|yes show signal handling details? [no]\n"
1454" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001455" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001456" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001457" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001458#if 0
1459" --model-pthreads=yes|no model the pthreads library [no]\n"
1460#endif
1461" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001462"\n"
1463" --vex-iropt-verbosity 0 .. 9 [0]\n"
1464" --vex-iropt-level 0 .. 2 [2]\n"
1465" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001466" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1467" --vex-guest-max-insns 1 .. 100 [50]\n"
1468" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1469"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001470" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001471" 1000 0000 show conversion into IR\n"
1472" 0100 0000 show after initial opt\n"
1473" 0010 0000 show after instrumentation\n"
1474" 0001 0000 show after second opt\n"
1475" 0000 1000 show after tree building\n"
1476" 0000 0100 show selecting insns\n"
1477" 0000 0010 show after reg-alloc\n"
1478" 0000 0001 show final assembly\n"
1479"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001480" debugging options for Valgrind tools that report errors\n"
1481" --dump-error=<number> show translation for basic block associated\n"
1482" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001483"\n";
njn3e884182003-04-15 13:03:23 +00001484
1485 Char* usage3 =
1486"\n"
nethercote71980f02004-01-24 18:18:54 +00001487" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001488"\n"
njn53612422005-03-12 16:22:54 +00001489" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001490" and licensed under the GNU General Public License, version 2.\n"
1491" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001492"\n"
nethercote137bc552003-11-14 17:47:54 +00001493" Tools are copyright and licensed by their authors. See each\n"
1494" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001495"\n";
njn7cf0bd32002-06-08 13:36:03 +00001496
njnbe9b47b2005-05-15 16:22:58 +00001497 // Ensure the message goes to stdout
1498 VG_(clo_log_fd) = 1;
1499 vg_assert( !VG_(logging_to_socket) );
1500
fitzhardinge98abfc72003-12-16 02:05:15 +00001501 VG_(printf)(usage1);
1502 if (VG_(details).name) {
1503 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001504 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001505 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001506 else
1507 VG_(printf)(" (none)\n");
1508 }
nethercote6c999f22004-01-31 22:55:15 +00001509 if (debug_help) {
1510 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001511
nethercote6c999f22004-01-31 22:55:15 +00001512 if (VG_(details).name) {
1513 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1514
1515 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001516 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001517 else
1518 VG_(printf)(" (none)\n");
1519 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001520 }
nethercote421281e2003-11-20 16:20:55 +00001521 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001522 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001523}
sewardjde4a1d02002-03-22 01:27:54 +00001524
nethercote71980f02004-01-24 18:18:54 +00001525static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001526 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001527{
nethercote71980f02004-01-24 18:18:54 +00001528 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001529
sewardj8b635a42004-11-22 19:01:47 +00001530 LibVEX_default_VexControl(& VG_(clo_vex_control));
1531
nethercote71980f02004-01-24 18:18:54 +00001532 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001533 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001534
nethercotef6a1d502004-08-09 12:21:57 +00001535 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001536 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001537 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001538
nethercotef6a1d502004-08-09 12:21:57 +00001539 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1540 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001541 *need_help = 1;
1542
nethercotef6a1d502004-08-09 12:21:57 +00001543 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001544 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001545
nethercotef6c99d72004-11-09 14:35:43 +00001546 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001547 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001548
nethercotef6a1d502004-08-09 12:21:57 +00001549 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1550 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001551 }
1552 }
nethercote71980f02004-01-24 18:18:54 +00001553}
1554
nethercote5ee67ca2004-06-22 14:00:09 +00001555static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001556{
nethercotef8548672004-06-21 12:42:35 +00001557 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001558 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001559 enum {
1560 VgLogTo_Fd,
1561 VgLogTo_File,
1562 VgLogTo_FileExactly,
1563 VgLogTo_Socket
1564 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001565
nethercotee1730692003-11-20 10:38:07 +00001566 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001567 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001568
sewardj19d81412002-06-03 01:10:40 +00001569 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001570 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001571 config_error("Please use absolute paths in "
1572 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001573
njnc6168192004-11-29 13:54:10 +00001574// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001575#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001576 {
sewardjb5f6f512005-03-10 23:59:00 +00001577 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001578 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1579 switch(auxp[0]) {
1580 case AT_SYSINFO:
1581 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1582 break;
1583 }
1584 }
1585 }
1586#endif
sewardjde4a1d02002-03-22 01:27:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001589
nethercotef6a1d502004-08-09 12:21:57 +00001590 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001591 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001592
thughes3bfd5a02004-07-18 08:05:44 +00001593 /* Look for a colon in the switch name */
1594 while (*colon && *colon != ':' && *colon != '=')
1595 colon++;
nethercote71980f02004-01-24 18:18:54 +00001596
1597 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001598 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001599 if (VG_CLO_STREQN(2, arg, "--") &&
1600 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1601 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1602 {
1603 // prefix matches, convert "--toolname:foo" to "--foo"
1604 if (0)
1605 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001606 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001607 arg[0] = '-';
1608 arg[1] = '-';
1609
1610 } else {
1611 // prefix doesn't match, skip to next arg
1612 continue;
1613 }
1614 }
1615
fitzhardinge98abfc72003-12-16 02:05:15 +00001616 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001617 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1618 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1619 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001620
njn45270a22005-03-27 01:00:11 +00001621 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001622
nethercote71980f02004-01-24 18:18:54 +00001623 else if (VG_CLO_STREQ(arg, "-v") ||
1624 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001625 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001626
nethercote71980f02004-01-24 18:18:54 +00001627 else if (VG_CLO_STREQ(arg, "-q") ||
1628 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001629 VG_(clo_verbosity)--;
1630
sewardj1cf558c2005-04-25 01:36:56 +00001631 else if (VG_CLO_STREQ(arg, "-d")) {
1632 /* do nothing */
1633 }
1634
sewardj71bc3cb2005-05-19 00:25:45 +00001635 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001636 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1637 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1638 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1639 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1640 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1641 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1642 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001643 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001644 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1645 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1646 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1647 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1648 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1649 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1650 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1651 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1652 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001653 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001654 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1655 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1656 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1657 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1658 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001659
njn45270a22005-03-27 01:00:11 +00001660 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1661 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001662
njn45270a22005-03-27 01:00:11 +00001663 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1664 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1665 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1666 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1667 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001668
njn45270a22005-03-27 01:00:11 +00001669 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001670 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001671 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001672 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001673 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001674 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001675 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001676 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001677 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001678 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001679 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001680 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1681
nethercotef8548672004-06-21 12:42:35 +00001682 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001683 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001684 VG_(clo_log_name) = NULL;
1685 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001686 }
1687
nethercotef8548672004-06-21 12:42:35 +00001688 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001689 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001690 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001691 }
njnd6bc3c32005-03-27 00:44:31 +00001692
sewardj603d4102005-01-11 14:01:02 +00001693 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001694 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001695 VG_(clo_log_name) = &arg[19];
1696 }
sewardjde4a1d02002-03-22 01:27:54 +00001697
nethercotef8548672004-06-21 12:42:35 +00001698 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001699 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001700 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001701 }
1702
nethercote71980f02004-01-24 18:18:54 +00001703 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001704 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001705 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001706 VG_(message)(Vg_UserMsg,
1707 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001708 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001709 }
nethercote71980f02004-01-24 18:18:54 +00001710 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001711 VG_(clo_n_suppressions)++;
1712 }
sewardjde4a1d02002-03-22 01:27:54 +00001713
sewardjfa8ec112005-01-19 11:55:34 +00001714 /* "stuvwxyz" --> stuvwxyz (binary) */
1715 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1716 Int j;
1717 char* opt = & arg[14];
1718
1719 if (8 != VG_(strlen)(opt)) {
1720 VG_(message)(Vg_UserMsg,
1721 "--trace-flags argument must have 8 digits");
1722 VG_(bad_option)(arg);
1723 }
1724 for (j = 0; j < 8; j++) {
1725 if ('0' == opt[j]) { /* do nothing */ }
1726 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1727 else {
1728 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1729 "contain 0s and 1s");
1730 VG_(bad_option)(arg);
1731 }
1732 }
1733 }
1734
1735 /* "stuvwxyz" --> stuvwxyz (binary) */
1736 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001737 Int j;
nethercote71980f02004-01-24 18:18:54 +00001738 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001739
sewardj2a99cf62004-11-24 10:44:19 +00001740 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001741 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001742 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001743 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001744 }
sewardj8b635a42004-11-22 19:01:47 +00001745 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001746 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001747 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001748 else {
sewardjfa8ec112005-01-19 11:55:34 +00001749 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001750 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001751 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001752 }
1753 }
1754 }
sewardjde4a1d02002-03-22 01:27:54 +00001755
njn45270a22005-03-27 01:00:11 +00001756 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001757
sewardjd153fae2005-01-10 17:24:47 +00001758 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1759 VG_(clo_gen_suppressions) = 0;
1760 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1761 VG_(clo_gen_suppressions) = 1;
1762 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1763 VG_(clo_gen_suppressions) = 2;
1764
nethercote71980f02004-01-24 18:18:54 +00001765 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001766 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001767 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001768 }
njn8c0b3bb2005-03-12 21:20:39 +00001769 skip_arg:
1770 if (arg != vg_argv[i])
1771 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001772 }
1773
sewardj998d40d2004-12-06 14:24:52 +00001774 /* Make VEX control parameters sane */
1775
1776 if (VG_(clo_vex_control).guest_chase_thresh
1777 >= VG_(clo_vex_control).guest_max_insns)
1778 VG_(clo_vex_control).guest_chase_thresh
1779 = VG_(clo_vex_control).guest_max_insns - 1;
1780
1781 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1782 VG_(clo_vex_control).guest_chase_thresh = 0;
1783
1784 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001785
njnf9ebf672003-05-12 21:41:30 +00001786 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001787 VG_(clo_verbosity) = 0;
1788
nethercote04d0fbc2004-01-26 16:48:06 +00001789 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001790 VG_(message)(Vg_UserMsg, "");
1791 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001792 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001793 VG_(message)(Vg_UserMsg,
1794 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001795 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001796 }
1797
njnbe9b47b2005-05-15 16:22:58 +00001798 if (VG_(clo_gen_suppressions) > 0 &&
1799 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1800 VG_(message)(Vg_UserMsg,
1801 "Can't use --gen-suppressions= with this tool,");
1802 VG_(message)(Vg_UserMsg,
1803 "as it doesn't generate errors.");
1804 VG_(bad_option)("--gen-suppressions=");
1805 }
1806
sewardj71bc3cb2005-05-19 00:25:45 +00001807 /* If we've been asked to emit XML, mash around various other
1808 options so as to constrain the output somewhat, and to remove
1809 any need for user input during the run. */
1810 if (VG_(clo_xml)) {
1811 /* Disable suppression generation (requires user input) */
1812 VG_(clo_gen_suppressions) = 0;
1813 /* Disable attaching to GDB (requires user input) */
1814 VG_(clo_db_attach) = False;
1815 /* Set a known verbosity level */
1816 VG_(clo_verbosity) = 1;
1817 /* Disable error limits (this might be a bad idea!) */
1818 VG_(clo_error_limit) = False;
1819 /* Disable emulation warnings */
1820 VG_(clo_show_emwarns) = False;
1821 /* Disable waiting for GDB to debug Valgrind */
1822 VG_(clo_wait_for_gdb) = False;
1823 /* No file-descriptor leak checking yet */
1824 VG_(clo_track_fds) = False;
1825 /* Also, we want to set options for the leak checker, but that
1826 will have to be done in Memcheck's flag-handling code, not
1827 here. */
1828 }
1829
njnbe9b47b2005-05-15 16:22:58 +00001830 /* All non-logging-related options have been checked. If the logging
1831 option specified is ok, we can switch to it, as we know we won't
1832 have to generate any other command-line-related error messages.
1833 (So far we should be still attached to stderr, so we can show on
1834 the terminal any problems to do with processing command line
1835 opts.)
1836
1837 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001838 should be connected to whatever sink has been selected, and we
1839 indiscriminately chuck stuff into it without worrying what the
1840 nature of it is. Oh the wonder of Unix streams. */
1841
njnbe9b47b2005-05-15 16:22:58 +00001842 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1843 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001844
njnbe9b47b2005-05-15 16:22:58 +00001845 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001846
sewardj4cf05692002-10-27 20:28:29 +00001847 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001848 vg_assert(VG_(clo_log_name) == NULL);
1849 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001850 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001851
sewardj4cf05692002-10-27 20:28:29 +00001852 case VgLogTo_File: {
1853 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001854 Int seq = 0;
1855 Int pid = VG_(getpid)();
1856
nethercotef8548672004-06-21 12:42:35 +00001857 vg_assert(VG_(clo_log_name) != NULL);
1858 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001859
nethercote71980f02004-01-24 18:18:54 +00001860 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001861 if (seq == 0)
1862 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001863 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001864 else
1865 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001866 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001867 seq++;
1868
njnbe9b47b2005-05-15 16:22:58 +00001869 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001870 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001871 = VG_(open)(logfilename,
1872 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1873 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001874 if (eventually_log_fd >= 0) {
1875 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001876 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001877 } else {
njnbe9b47b2005-05-15 16:22:58 +00001878 // If the file already existed, we try the next name. If it
1879 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001880 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001881 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001882 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001883 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001884 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001885 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001886 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001887 }
1888 }
1889 }
sewardj603d4102005-01-11 14:01:02 +00001890 break; /* switch (VG_(clo_log_to)) */
1891 }
1892
1893 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001894 vg_assert(VG_(clo_log_name) != NULL);
1895 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001896
1897 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001898 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001899 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1900 VKI_S_IRUSR|VKI_S_IWUSR);
1901 if (eventually_log_fd >= 0) {
1902 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001903 } else {
sewardj603d4102005-01-11 14:01:02 +00001904 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001905 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001906 VG_(clo_log_name));
1907 VG_(bad_option)(
1908 "--log-file-exactly=<file> (didn't work out for some reason.)");
1909 /*NOTREACHED*/
1910 }
1911 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001912 }
1913
1914 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001915 vg_assert(VG_(clo_log_name) != NULL);
1916 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1917 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1918 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001919 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001920 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001921 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001922 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001923 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001924 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001925 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001926 }
nethercotef8548672004-06-21 12:42:35 +00001927 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001928 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001929 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001930 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001931 VG_(message)(Vg_UserMsg,
1932 "Log messages will sent to stderr instead." );
1933 VG_(message)(Vg_UserMsg,
1934 "" );
1935 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001936 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001937 } else {
nethercotef8548672004-06-21 12:42:35 +00001938 vg_assert(eventually_log_fd > 0);
1939 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001940 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001941 }
sewardj73cf3bc2002-11-03 03:20:15 +00001942 break;
1943 }
sewardj4cf05692002-10-27 20:28:29 +00001944 }
1945
sewardj71bc3cb2005-05-19 00:25:45 +00001946
1947 /* Check that the requested tool actually supports XML output. */
1948 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1949 VG_(clo_xml) = False;
1950 VG_(message)(Vg_UserMsg,
1951 "Currently only Memcheck supports XML output.");
1952 VG_(bad_option)("--xml=yes");
1953 /*NOTREACHED*/
1954 }
1955
njnbe9b47b2005-05-15 16:22:58 +00001956 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1957 // XXX: this is more or less duplicating the behaviour of the calls to
1958 // VG_(safe_fd)() above, although this does not close the original fd.
1959 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1960 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001961 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001962 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001963 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1964 else {
nethercotef8548672004-06-21 12:42:35 +00001965 VG_(clo_log_fd) = eventually_log_fd;
1966 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001967 }
1968
sewardj4cf05692002-10-27 20:28:29 +00001969 /* Ok, the logging sink is running now. Print a suitable preamble.
1970 If logging to file or a socket, write details of parent PID and
1971 command line args, to help people trying to interpret the
1972 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001973
sewardj71bc3cb2005-05-19 00:25:45 +00001974 if (VG_(clo_xml)) {
1975 VG_(message)(Vg_UserMsg, "");
1976 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1977 VG_(message)(Vg_UserMsg, "");
1978 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1979 VG_(message)(Vg_UserMsg, "");
1980 }
1981
1982 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1983 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1984
sewardj83adf412002-05-01 01:25:45 +00001985 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001986 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001987 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1988 xpre,
njnd04b7c62002-10-03 14:05:52 +00001989 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001990 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001991 NULL == VG_(details).version
1992 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001993 VG_(details).description,
1994 xpost);
1995 VG_(message)(Vg_UserMsg, "%s%s%s",
1996 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001997
njnd04b7c62002-10-03 14:05:52 +00001998 /* Core details */
1999 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002000 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
2001 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00002002 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002003 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
2004 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00002005 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002006 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
2007 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00002008 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00002009 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
2010 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00002011 }
2012
njnbe9b47b2005-05-15 16:22:58 +00002013 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002014 VG_(message)(Vg_UserMsg, "");
2015 VG_(message)(Vg_UserMsg,
2016 "My PID = %d, parent PID = %d. Prog and args are:",
2017 VG_(getpid)(), VG_(getppid)() );
2018 for (i = 0; i < VG_(client_argc); i++)
2019 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2020 }
sewardj71bc3cb2005-05-19 00:25:45 +00002021 else
2022 if (VG_(clo_xml)) {
2023 VG_(message)(Vg_UserMsg, "");
2024 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
2025 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00002026 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00002027 VG_(message)(Vg_UserMsg, "");
2028 VG_(message)(Vg_UserMsg, "<argv>");
2029 for (i = 0; i < VG_(client_argc); i++)
2030 VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
2031 VG_(message)(Vg_UserMsg, "</argv>");
2032 }
sewardj4cf05692002-10-27 20:28:29 +00002033
sewardjde4a1d02002-03-22 01:27:54 +00002034 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002035 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00002036 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002037 VG_(message)(Vg_DebugMsg, "");
2038 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2039 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002040 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002041 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002042
njn1fd5eb22005-03-13 05:43:23 +00002043 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002044 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002045 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002046 }
nethercotea70f7352004-04-18 12:08:46 +00002047
njn1fd5eb22005-03-13 05:43:23 +00002048 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002049 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2050 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002051 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002052 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002053# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002054 Char version_buf[BUF_LEN];
2055 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002056 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002057 if (n > 0) {
2058 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002059 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002060 } else {
njn1fd5eb22005-03-13 05:43:23 +00002061 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002062 }
2063 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002064# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002065 }
sewardjde4a1d02002-03-22 01:27:54 +00002066 }
2067
fitzhardinge98abfc72003-12-16 02:05:15 +00002068 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002069 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002070 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002071 needs one, load the default */
2072 static const Char default_supp[] = "default.supp";
2073 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2074 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2075 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2076 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2077 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002078 }
2079}
2080
nethercotef6a1d502004-08-09 12:21:57 +00002081// Build the string for VALGRINDCLO.
2082Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2083{
2084 /* If we're tracing the children, then we need to start it
2085 with our starter+arguments, which are copied into VALGRINDCLO,
2086 except the --exec= option is changed if present.
2087 */
2088 Int i;
2089 Char *exec;
2090 Char *cp;
2091 Char *optvar;
2092 Int optlen, execlen;
2093
2094 // All these allocated blocks are not free - because we're either
2095 // going to exec, or panic when we fail.
2096
2097 // Create --exec= option: "--exec=<exename>"
2098 exec = VG_(arena_malloc)(VG_AR_CORE,
2099 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2100 vg_assert(NULL != exec);
2101 VG_(sprintf)(exec, "--exec=%s", exename);
2102
2103 // Allocate space for optvar (may overestimate by counting --exec twice,
2104 // no matter)
2105 optlen = 1;
2106 for (i = 0; i < vg_argc; i++)
2107 optlen += VG_(strlen)(vg_argv[i]) + 1;
2108 optlen += VG_(strlen)(exec)+1;
2109 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2110
2111 // Copy all valgrind args except the old --exec (if present)
2112 // VG_CLO_SEP is the separator.
2113 cp = optvar;
2114 for (i = 1; i < vg_argc; i++) {
2115 Char *arg = vg_argv[i];
2116
2117 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2118 // don't copy existing --exec= arg
2119 } else if (VG_(strcmp)(arg, "--") == 0) {
2120 // stop at "--"
2121 break;
2122 } else {
2123 // copy non "--exec" arg
2124 Int len = VG_(strlen)(arg);
2125 VG_(memcpy)(cp, arg, len);
2126 cp += len;
2127 *cp++ = VG_CLO_SEP;
2128 }
2129 }
2130 // Add the new --exec= option
2131 execlen = VG_(strlen)(exec);
2132 VG_(memcpy)(cp, exec, execlen);
2133 cp += execlen;
2134 *cp++ = VG_CLO_SEP;
2135
2136 *cp = '\0';
2137
2138 return optvar;
2139}
2140
2141// Build "/proc/self/fd/<execfd>".
2142Char* VG_(build_child_exename)( void )
2143{
2144 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2145 vg_assert(NULL != exename);
2146 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2147 return exename;
2148}
2149
sewardjde4a1d02002-03-22 01:27:54 +00002150
nethercote71980f02004-01-24 18:18:54 +00002151/*====================================================================*/
2152/*=== File descriptor setup ===*/
2153/*====================================================================*/
2154
2155static void setup_file_descriptors(void)
2156{
2157 struct vki_rlimit rl;
2158
2159 /* Get the current file descriptor limits. */
2160 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2161 rl.rlim_cur = 1024;
2162 rl.rlim_max = 1024;
2163 }
2164
2165 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002166 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2167 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002168 } else {
2169 rl.rlim_cur = rl.rlim_max;
2170 }
2171
2172 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002173 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2174 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002175
2176 /* Update the soft limit. */
2177 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2178
nethercotef6a1d502004-08-09 12:21:57 +00002179 if (vgexecfd != -1)
2180 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002181 if (VG_(clexecfd) != -1)
2182 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2183}
2184
nethercote71980f02004-01-24 18:18:54 +00002185/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002186/*=== Initialise program data/text, etc. ===*/
2187/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002188
sewardjb5f6f512005-03-10 23:59:00 +00002189static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2190 UInt dev, UInt ino, ULong foffset,
2191 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002192{
nethercote71980f02004-01-24 18:18:54 +00002193 /* Only record valgrind mappings for now, without loading any
2194 symbols. This is so we know where the free space is before we
2195 start allocating more memory (note: heap is OK, it's just mmap
2196 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002197 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002198 VG_(debugLog)(2, "main",
2199 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002200 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002201 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002202 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2203 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002204 /* update VG_(valgrind_last) if it looks wrong */
2205 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002206 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002207 }
sewardjde4a1d02002-03-22 01:27:54 +00002208}
2209
nethercote71980f02004-01-24 18:18:54 +00002210// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002211Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002212
sewardjb5f6f512005-03-10 23:59:00 +00002213/*
2214 This second pass adds in client mappings, and loads symbol tables
2215 for all interesting mappings. The trouble is that things can
2216 change as we go, because we're calling the Tool to track memory as
2217 we find it.
2218
2219 So for Valgrind mappings, we don't replace any mappings which
2220 aren't still identical (which will include the .so mappings, so we
2221 will load their symtabs)>
2222 */
2223static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2224 UInt dev, UInt ino, ULong foffset,
2225 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002226{
nethercote71980f02004-01-24 18:18:54 +00002227 UInt flags;
2228 Bool is_stack_segment;
2229 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002230
nethercote71980f02004-01-24 18:18:54 +00002231 is_stack_segment
2232 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002233
sewardj8c615892005-04-25 02:38:28 +00002234 VG_(debugLog)(2, "main",
2235 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002236 (void*)start, (void*)(start+size), prot, is_stack_segment,
2237 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002238
nethercote71980f02004-01-24 18:18:54 +00002239 if (is_stack_segment)
2240 flags = SF_STACK | SF_GROWDOWN;
2241 else
2242 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002243
nethercote71980f02004-01-24 18:18:54 +00002244 if (filename != NULL)
2245 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002246
sewardjb5f6f512005-03-10 23:59:00 +00002247#if 0
2248 // This needs to be fixed properly. jrs 20050307
2249 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2250 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002251
sewardjb5f6f512005-03-10 23:59:00 +00002252 /* We have to be a bit careful about inserting new mappings into
2253 the Valgrind part of the address space. We're actively
2254 changing things as we parse these mappings, particularly in
2255 shadow memory, and so we don't want to overwrite those
2256 changes. Therefore, we only insert/update a mapping if it is
2257 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002258
sewardjb5f6f512005-03-10 23:59:00 +00002259 NOTE: we're only talking about the Segment list mapping
2260 metadata; this doesn't actually mmap anything more. */
2261 if (filename || (s && s->addr == start && s->len == size)) {
2262 flags |= SF_VALGRIND;
2263 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2264 } else {
2265 /* assert range is already mapped */
2266 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2267 }
2268 } else
2269#endif
2270 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2271
2272 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2273 VG_TRACK( new_mem_startup, start, size,
2274 !!(prot & VKI_PROT_READ),
2275 !!(prot & VKI_PROT_WRITE),
2276 !!(prot & VKI_PROT_EXEC));
2277 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002278
nethercote71980f02004-01-24 18:18:54 +00002279 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002280 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002281 vg_assert(0 != r_esp);
2282 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002283 if (0) {
2284 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002285 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002286 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2287 r_esp, start+size);
2288 }
nethercote71980f02004-01-24 18:18:54 +00002289 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002290 // what's this for?
2291 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002292 }
sewardjde4a1d02002-03-22 01:27:54 +00002293}
2294
2295
nethercote71980f02004-01-24 18:18:54 +00002296/*====================================================================*/
2297/*=== Sanity check machinery (permanently engaged) ===*/
2298/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002299
2300/* A fast sanity check -- suitable for calling circa once per
2301 millisecond. */
2302
nethercote885dd912004-08-03 23:14:00 +00002303void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002304{
sewardjb5f6f512005-03-10 23:59:00 +00002305 ThreadId tid;
2306
njn37cea302002-09-30 11:24:00 +00002307 VGP_PUSHCC(VgpCoreCheapSanity);
2308
nethercote27fec902004-06-16 21:26:32 +00002309 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002310
2311 /* --- First do all the tests that we can do quickly. ---*/
2312
nethercote297effd2004-08-02 15:07:57 +00002313 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002314
njn25e49d8e72002-09-23 09:36:25 +00002315 /* Check stuff pertaining to the memory check system. */
2316
2317 /* Check that nobody has spuriously claimed that the first or
2318 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002319 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002320 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002321 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002322 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002323 }
njn25e49d8e72002-09-23 09:36:25 +00002324
2325 /* --- Now some more expensive checks. ---*/
2326
2327 /* Once every 25 times, check some more expensive stuff. */
2328 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002329 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002330 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002331
njn37cea302002-09-30 11:24:00 +00002332 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002333 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002334
2335# if 0
2336 { void zzzmemscan(void); zzzmemscan(); }
2337# endif
2338
nethercote297effd2004-08-02 15:07:57 +00002339 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002340 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002341
2342 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002343 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002344 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002345 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002346 }
sewardjb5f6f512005-03-10 23:59:00 +00002347
2348 /* Check that Segments and /proc/self/maps match up */
2349 //vg_assert(VG_(sanity_check_memory)());
2350
2351 /* Look for stack overruns. Visit all threads. */
2352 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002353 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002354
2355 if (VG_(threads)[tid].status == VgTs_Empty ||
2356 VG_(threads)[tid].status == VgTs_Zombie)
2357 continue;
2358
2359 remains = VGA_(stack_unused)(tid);
2360 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002361 VG_(message)(Vg_DebugMsg,
2362 "WARNING: Thread %d is within %d bytes "
2363 "of running out of stack!",
2364 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002365 }
2366
njn25e49d8e72002-09-23 09:36:25 +00002367 /*
nethercote297effd2004-08-02 15:07:57 +00002368 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002369 */
njn37cea302002-09-30 11:24:00 +00002370 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002371 }
2372
nethercote27fec902004-06-16 21:26:32 +00002373 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002374 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002375 /* Check sanity of the low-level memory manager. Note that bugs
2376 in the client's code can cause this to fail, so we don't do
2377 this check unless specially asked for. And because it's
2378 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002379 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002380 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002381 }
njn37cea302002-09-30 11:24:00 +00002382 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002383}
nethercote71980f02004-01-24 18:18:54 +00002384
2385
2386/*====================================================================*/
2387/*=== main() ===*/
2388/*====================================================================*/
2389
nethercotec314eba2004-07-15 12:59:41 +00002390/*
2391 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002392 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002393 loads the client executable (and the dynamic linker, if necessary)
2394 into the client part, and calls into Valgrind proper.
2395
2396 The code is careful not to allow spurious mappings to appear in the
2397 wrong parts of the address space. In particular, to make sure
2398 dlopen puts things in the right place, it will pad out the forbidden
2399 chunks of address space so that dlopen is forced to put things where
2400 we want them.
2401
2402 The memory map it creates is:
2403
njn311c5d82005-05-15 21:03:42 +00002404 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002405 | client address space |
2406 : :
2407 : :
2408 | client stack |
2409 client_end +-------------------------+
2410 | redzone |
2411 shadow_base +-------------------------+
2412 | |
nethercote996901a2004-08-03 13:29:09 +00002413 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002414 | (may be 0 sized) |
2415 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002416 valgrind_base +-------------------------+
2417 | kickstart executable |
2418 | valgrind heap vvvvvvvvv| (barely used)
2419 - -
2420 | valgrind .so files |
2421 | and mappings |
2422 - -
2423 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002424 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002425 : kernel :
2426
2427 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2428 VG_(mmap)(), we need to build the segment skip-list, so we know where
2429 we can put things. However, building that structure requires
2430 allocating memory. So we need to a bootstrapping process. It's done
2431 by making VG_(arena_malloc)() have a special static superblock that's
2432 used for the first 1MB's worth of allocations. This is enough to
2433 build the segment skip-list.
2434*/
2435
thughes4ad52d02004-06-27 17:37:21 +00002436
sewardj1cf558c2005-04-25 01:36:56 +00002437/* This may be needed before m_mylibc is OK to run. */
2438static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2439{
2440 while (True) {
2441 if (*s1 == 0 && *s2 == 0) return 0;
2442 if (*s1 == 0) return -1;
2443 if (*s2 == 0) return 1;
2444
2445 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2446 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2447
2448 s1++; s2++;
2449 }
2450}
2451
2452
sewardjb5f6f512005-03-10 23:59:00 +00002453int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002454{
2455 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002456 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002457 const char *exec = NULL;
2458 char *preload; /* tool-specific LD_PRELOAD .so */
2459 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002460 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002461 struct exeinfo info;
2462 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002463 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002464 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002465 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002466 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002467 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002468
2469 //============================================================
2470 // Nb: startup is complex. Prerequisites are shown at every step.
2471 //
2472 // *** Be very careful when messing with the order ***
2473 //============================================================
2474
sewardj1cf558c2005-04-25 01:36:56 +00002475 //--------------------------------------------------------------
2476 // Start up the logging mechanism
2477 // p: none
2478 //--------------------------------------------------------------
2479 /* Start the debugging-log system ASAP. First find out how many
2480 "-d"s were specified. This is a pre-scan of the command line. */
2481 loglevel = 0;
2482 for (i = 1; i < argc; i++) {
2483 if (argv[i][0] != '-')
2484 break;
2485 if (0 == local_strcmp(argv[i], "--"))
2486 break;
2487 if (0 == local_strcmp(argv[i], "-d"))
2488 loglevel++;
2489 }
2490
2491 /* ... and start the debug logger. Now we can safely emit logging
2492 messages all through startup. */
2493 VG_(debugLog_startup)(loglevel, "Stage 2");
2494
nethercotef4928da2004-06-15 10:54:40 +00002495 //============================================================
2496 // Command line argument handling order:
2497 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002498 // (including the tool-specific usage)
2499 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002500 // * Then, if client is missing, abort with error msg
2501 // * Then, if any cmdline args are bad, abort with error msg
2502 //============================================================
2503
fitzhardingeb50068f2004-02-24 23:42:55 +00002504 // Get the current process datasize rlimit, and set it to zero.
2505 // This prevents any internal uses of brk() from having any effect.
2506 // We remember the old value so we can restore it on exec, so that
2507 // child processes will have a reasonable brk value.
2508 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2509 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2510 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002511
2512 // Get the current process stack rlimit.
2513 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2514
nethercote71980f02004-01-24 18:18:54 +00002515 //--------------------------------------------------------------
2516 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002517 // p: none
nethercote71980f02004-01-24 18:18:54 +00002518 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002519 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002520 {
sewardj1fbc1a52005-04-25 02:05:54 +00002521 void* init_sp = argv - 1;
2522 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002523 }
2524
2525 //--------------------------------------------------------------
2526 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002527 // p: none
nethercote71980f02004-01-24 18:18:54 +00002528 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002529 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002530 if (cp != NULL)
2531 VG_(libdir) = cp;
2532 }
2533
2534 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002535 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2536 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002537 // p: none
nethercote71980f02004-01-24 18:18:54 +00002538 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002539 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002540 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002541 pre_process_cmd_line_options(&need_help, &tool, &exec);
2542
2543 //==============================================================
2544 // Nb: once a tool is specified, the tool.so must be loaded even if
2545 // they specified --help or didn't specify a client program.
2546 //==============================================================
2547
2548 //--------------------------------------------------------------
2549 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002550 // p: set-libdir [for VG_(libdir)]
2551 // p: pre_process_cmd_line_options() [for 'tool']
2552 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002553 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002554 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002555
2556 //==============================================================
2557 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002558 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002559 //==============================================================
2560
2561 //--------------------------------------------------------------
2562 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002563 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002564 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002565 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002566 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002567
2568 //--------------------------------------------------------------
2569 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002570 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2571 // p: layout_remaining_space [so there's space]
2572 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002573 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002574 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002575
2576 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002577 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002578 // p: layout_remaining_space() [everything must be mapped in before now]
2579 // p: load_client() [ditto]
2580 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002581 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2582 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002583
2584 //--------------------------------------------------------------
2585 // Set up client's environment
2586 // p: set-libdir [for VG_(libdir)]
2587 // p: load_tool() [for 'preload']
2588 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002589 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002590 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002591
2592 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002593 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002594 // p: load_client() [for 'info']
2595 // p: fix_environment() [for 'env']
2596 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002597 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002598 {
sewardj1fbc1a52005-04-25 02:05:54 +00002599 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002600
sewardj1fbc1a52005-04-25 02:05:54 +00002601 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2602 &client_auxv);
2603 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002604 }
nethercote71980f02004-01-24 18:18:54 +00002605
sewardj1fbc1a52005-04-25 02:05:54 +00002606 VG_(debugLog)(2, "main",
2607 "Client info: "
2608 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2609 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2610 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002611
2612 //==============================================================
2613 // Finished setting up operating environment. Now initialise
2614 // Valgrind. (This is where the old VG_(main)() started.)
2615 //==============================================================
2616
2617 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002618 // setup file descriptors
2619 // p: n/a
2620 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002621 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002622 setup_file_descriptors();
2623
2624 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002625 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002626 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002627 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002628 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002629 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2630
2631 //==============================================================
2632 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2633 //==============================================================
2634
2635 //--------------------------------------------------------------
2636 // Init tool: pre_clo_init, process cmd line, post_clo_init
2637 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002638 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002639 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2640 // p: parse_procselfmaps [so VG segments are setup so tool can
2641 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002642 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002643 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002644 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002645 VG_(sanity_check_needs)();
2646
nethercotef4928da2004-06-15 10:54:40 +00002647 // If --tool and --help/--help-debug was given, now give the core+tool
2648 // help message
nethercotef4928da2004-06-15 10:54:40 +00002649 if (need_help) {
2650 usage(/*--help-debug?*/2 == need_help);
2651 }
nethercotec314eba2004-07-15 12:59:41 +00002652 process_cmd_line_options(client_auxv, tool);
2653
njn51d827b2005-05-09 01:02:08 +00002654 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002655
2656 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002657 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002658 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002659 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002660 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002661 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002662 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002663 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002664 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002665 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002666
sewardj21c6d0f2005-05-02 10:33:44 +00002667#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002668 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002669 // Protect client trampoline page (which is also sysinfo stuff)
2670 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002671 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002672 {
2673 Segment *seg;
2674 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2675 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002676
sewardjb5f6f512005-03-10 23:59:00 +00002677 /* Make sure this segment isn't treated as stack */
2678 seg = VG_(find_segment)(VG_(client_trampoline_code));
2679 if (seg)
2680 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2681 }
sewardj21c6d0f2005-05-02 10:33:44 +00002682#endif
sewardjb5f6f512005-03-10 23:59:00 +00002683
nethercotec314eba2004-07-15 12:59:41 +00002684 //==============================================================
2685 // Can use VG_(map)() after segments set up
2686 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002687
2688 //--------------------------------------------------------------
2689 // Allow GDB attach
2690 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2691 //--------------------------------------------------------------
2692 /* Hook to delay things long enough so we can get the pid and
2693 attach GDB in another shell. */
2694 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002695 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002696 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2697 /* jrs 20050206: I don't understand why this works on x86. On
2698 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2699 work. */
2700 /* do "jump *$eip" to skip this in gdb (x86) */
2701 //VG_(do_syscall0)(__NR_pause);
2702 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002703 }
2704
sewardjb5d320c2005-03-13 18:57:15 +00002705 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002706 // Search for file descriptors that are inherited from our parent
2707 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2708 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002709 if (VG_(clo_track_fds)) {
2710 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002711 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002712 }
nethercote71980f02004-01-24 18:18:54 +00002713
2714 //--------------------------------------------------------------
2715 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002716 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2717 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002718 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002719 VG_(scheduler_init)();
2720
2721 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002722 // Initialise the pthread model
2723 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002724 // load_client() [for 'client_eip']
2725 // setup_client_stack() [for 'sp_at_startup']
2726 // setup_scheduler() [for the rest of state 1 stuff]
2727 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002728 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002729 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002730
2731 // Tell the tool that we just wrote to the registers.
2732 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2733 sizeof(VexGuestArchState));
2734
sewardj2a99cf62004-11-24 10:44:19 +00002735 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002736 // Initialise the pthread model
2737 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002738 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002739 //if (VG_(clo_model_pthreads))
2740 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002741
2742 //--------------------------------------------------------------
2743 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002744 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002745 //--------------------------------------------------------------
2746 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002747 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002748 VG_(sigstartup_actions)();
2749
2750 //--------------------------------------------------------------
2751 // Perhaps we're profiling Valgrind?
2752 // p: process_cmd_line_options() [for VG_(clo_profile)]
2753 // p: others?
2754 //
2755 // XXX: this seems to be broken? It always says the tool wasn't built
2756 // for profiling; vg_profile.c's functions don't seem to be overriding
2757 // vg_dummy_profile.c's?
2758 //
2759 // XXX: want this as early as possible. Looking for --profile
2760 // in pre_process_cmd_line_options() could get it earlier.
2761 //--------------------------------------------------------------
2762 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002763 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002764
2765 VGP_PUSHCC(VgpStartup);
2766
2767 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002768 // Read suppression file
2769 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2770 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002771 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2772 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002773 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002774 }
nethercote71980f02004-01-24 18:18:54 +00002775
2776 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002777 // Initialise translation table and translation cache
2778 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2779 // aren't identified as part of the client, which would waste
2780 // > 20M of virtual address space.]
2781 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002782 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002783 VG_(init_tt_tc)();
2784
2785 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002786 // Read debug info to find glibc entry points to intercept
2787 // p: parse_procselfmaps? [XXX for debug info?]
2788 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2789 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002790 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002791 VG_(setup_code_redirect_table)();
2792
2793 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002794 // Verbosity message
2795 // p: end_rdtsc_calibration [so startup message is printed first]
2796 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002797 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002798 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2799 if (VG_(clo_verbosity) > 0)
2800 VG_(message)(Vg_UserMsg, "");
2801
2802 //--------------------------------------------------------------
2803 // Setup pointercheck
2804 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2805 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002806 if (VG_(clo_pointercheck))
2807 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002808
nethercote71980f02004-01-24 18:18:54 +00002809 //--------------------------------------------------------------
2810 // Run!
2811 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002812 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002813
sewardj71bc3cb2005-05-19 00:25:45 +00002814 if (VG_(clo_xml)) {
2815 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2816 VG_(message)(Vg_UserMsg, "");
2817 }
2818
sewardj1fbc1a52005-04-25 02:05:54 +00002819 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002820 /* As a result of the following call, the last thread standing
2821 eventually winds up running VG_(shutdown_actions_NORETURN) just
2822 below. */
2823 VGP_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002824
sewardj1d887112005-05-30 21:44:08 +00002825 /*NOTREACHED*/
2826 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002827}
2828
2829
2830/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002831void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2832 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002833{
sewardj1d887112005-05-30 21:44:08 +00002834 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2835
2836 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002837 vg_assert(VG_(is_running_thread)(tid));
2838
2839 // Wait for all other threads to exit.
2840 VGA_(reap_threads)(tid);
2841
2842 VG_(clo_model_pthreads) = False;
2843
2844 // Clean the client up before the final report
2845 VGA_(final_tidyup)(tid);
2846
2847 // OK, done
2848 VG_(exit_thread)(tid);
2849
2850 /* should be no threads left */
2851 vg_assert(VG_(count_living_threads)() == 0);
2852
2853 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002854 //--------------------------------------------------------------
2855 // Finalisation: cleanup, messages, etc. Order no so important, only
2856 // affects what order the messages come.
2857 //--------------------------------------------------------------
2858 if (VG_(clo_verbosity) > 0)
2859 VG_(message)(Vg_UserMsg, "");
2860
sewardj71bc3cb2005-05-19 00:25:45 +00002861 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002862 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2863 VG_(show_error_counts_as_XML)();
2864 VG_(message)(Vg_UserMsg, "");
2865 }
sewardj71bc3cb2005-05-19 00:25:45 +00002866 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2867 VG_(message)(Vg_UserMsg, "");
2868 }
2869
nethercote71980f02004-01-24 18:18:54 +00002870 /* Print out file descriptor summary and stats. */
2871 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002872 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002873
njn95ec8702004-11-22 16:46:13 +00002874 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002875 VG_(show_all_errors)();
2876
njn51d827b2005-05-09 01:02:08 +00002877 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002878
sewardj71bc3cb2005-05-19 00:25:45 +00002879 if (VG_(clo_xml)) {
2880 VG_(message)(Vg_UserMsg, "");
2881 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2882 VG_(message)(Vg_UserMsg, "");
2883 }
2884
nethercote885dd912004-08-03 23:14:00 +00002885 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002886
2887 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002888 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002889
nethercote71980f02004-01-24 18:18:54 +00002890 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002891 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002892 if (VG_(clo_profile_flags) > 0)
2893 VG_(show_BB_profile)();
2894
sewardj8b635a42004-11-22 19:01:47 +00002895 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002896 if (0)
2897 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002898
2899 /* Ok, finally exit in the os-specific way. In short, if the
2900 (last) thread exited by calling sys_exit, do likewise; if the
2901 (last) thread stopped due to a fatal signal, terminate the
2902 entire system with that same fatal signal. */
2903 VGO_(terminate_NORETURN)( tid, tids_schedretcode );
njne96be672005-05-08 19:08:54 +00002904}
sewardj8b635a42004-11-22 19:01:47 +00002905
sewardjde4a1d02002-03-22 01:27:54 +00002906/*--------------------------------------------------------------------*/
2907/*--- end vg_main.c ---*/
2908/*--------------------------------------------------------------------*/