blob: ba89b423d96c3da1605f73026c692c5b4058972b [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
39#include "pub_core_syscalls.h"
nethercote71980f02004-01-24 18:18:54 +000040
41#include <dirent.h>
42#include <dlfcn.h>
43#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000046#include <string.h>
47#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000048#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000049#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <sys/wait.h>
51#include <unistd.h>
52
sewardjb5f6f512005-03-10 23:59:00 +000053#include "memcheck/memcheck.h"
54
thughes74b8de22004-04-22 18:12:31 +000055#ifndef AT_DCACHEBSIZE
56#define AT_DCACHEBSIZE 19
57#endif /* AT_DCACHEBSIZE */
58
59#ifndef AT_ICACHEBSIZE
60#define AT_ICACHEBSIZE 20
61#endif /* AT_ICACHEBSIZE */
62
63#ifndef AT_UCACHEBSIZE
64#define AT_UCACHEBSIZE 21
65#endif /* AT_UCACHEBSIZE */
66
nethercote71980f02004-01-24 18:18:54 +000067#ifndef AT_SYSINFO
68#define AT_SYSINFO 32
69#endif /* AT_SYSINFO */
70
71#ifndef AT_SYSINFO_EHDR
72#define AT_SYSINFO_EHDR 33
73#endif /* AT_SYSINFO_EHDR */
74
75#ifndef AT_SECURE
76#define AT_SECURE 23 /* secure mode boolean */
77#endif /* AT_SECURE */
78
nethercote71980f02004-01-24 18:18:54 +000079/* redzone gap between client address space and shadow */
80#define REDZONE_SIZE (1 * 1024*1024)
81
82/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000083#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000084
nethercotee2097312004-06-27 12:29:56 +000085/* Proportion of client space for its heap (rest is for mmaps + stack) */
86#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000087
njn14319cc2005-03-13 06:26:22 +000088/* Number of file descriptors that Valgrind tries to reserve for
89 it's own use - just a small constant. */
90#define N_RESERVED_FDS (10)
91
92/* Default debugger command. */
93#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
94
nethercote71980f02004-01-24 18:18:54 +000095/*====================================================================*/
96/*=== Global entities not referenced from generated code ===*/
97/*====================================================================*/
98
sewardjde4a1d02002-03-22 01:27:54 +000099/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000100 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000101 ------------------------------------------------------------------ */
102
nethercote71980f02004-01-24 18:18:54 +0000103/* Client address space, lowest to highest (see top of ume.c) */
104Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000105Addr VG_(client_end);
106Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000107Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108Addr VG_(clstk_base);
109Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000110
111Addr VG_(brk_base); /* start of brk */
112Addr VG_(brk_limit); /* current brk */
113
nethercote996901a2004-08-03 13:29:09 +0000114Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000115Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000116
117Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000118
nethercote820bd8c2004-09-07 23:04:49 +0000119// Note that VG_(valgrind_last) names the last byte of the section, whereas
120// the VG_(*_end) vars name the byte one past the end of the section.
121Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000122
nethercote73b526f2004-10-31 18:48:21 +0000123struct vki_rlimit VG_(client_rlimit_data);
124struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000125
fitzhardinge98abfc72003-12-16 02:05:15 +0000126/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000127static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000128
129/* client executable */
130Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000131
132/* Path to library directory */
133const Char *VG_(libdir) = VG_LIBDIR;
134
135/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000136static Int vg_argc;
137static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000138
sewardjb5f6f512005-03-10 23:59:00 +0000139/* The master thread the one which will be responsible for mopping
140 everything up at exit. Normally it is tid 1, since that's the
141 first thread created, but it may be something else after a
142 fork(). */
143ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000144
thughesad1c9562004-06-26 11:27:52 +0000145/* Application-visible file descriptor limits */
146Int VG_(fd_soft_limit) = -1;
147Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000148
nethercote4ad74312004-10-26 09:59:49 +0000149/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000150 envp[] as extracted from the client's stack at startup-time. */
151Int VG_(client_argc);
152Char** VG_(client_argv);
153Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000154
sewardj51ac0872004-12-21 01:20:49 +0000155/* Indicates what arch and subarch we are running on. */
156VexArch VG_(vex_arch) = VexArch_INVALID;
157VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
158
159
sewardjde4a1d02002-03-22 01:27:54 +0000160/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000161 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000162 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/* Counts downwards in VG_(run_innerloop). */
165UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000166
167/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000168ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000169
nethercote71980f02004-01-24 18:18:54 +0000170/* Tell the logging mechanism whether we are logging to a file
171 descriptor or a socket descriptor. */
172Bool VG_(logging_to_filedes) = True;
173
sewardj73cf3bc2002-11-03 03:20:15 +0000174
nethercote71980f02004-01-24 18:18:54 +0000175/*====================================================================*/
176/*=== Counters, for profiling purposes only ===*/
177/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000178
sewardjde4a1d02002-03-22 01:27:54 +0000179/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000180static UInt sanity_fast_count = 0;
181static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000182
nethercote3a42fb82004-08-03 18:08:50 +0000183static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000184{
nethercote3a42fb82004-08-03 18:08:50 +0000185 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000186 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000187 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000188 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000189
nethercote3a42fb82004-08-03 18:08:50 +0000190 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000191 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000192
nethercote71980f02004-01-24 18:18:54 +0000193 VG_(message)(Vg_DebugMsg,
194 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000195 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000196
njn9271cbc2005-03-13 05:38:25 +0000197 VG_(print_ExeContext_stats)();
198
nethercote3a42fb82004-08-03 18:08:50 +0000199 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000200 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000201 VG_(message)(Vg_DebugMsg, "");
202 VG_(message)(Vg_DebugMsg,
203 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000204 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000205 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000206 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000207 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000208 }
nethercote71980f02004-01-24 18:18:54 +0000209}
210
211
212/*====================================================================*/
213/*=== Miscellaneous global functions ===*/
214/*====================================================================*/
215
nethercotecf97ffb2004-09-09 13:40:31 +0000216static Int ptrace_setregs(Int pid, ThreadId tid)
217{
sewardj2a99cf62004-11-24 10:44:19 +0000218 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000219}
220
nethercote04d0fbc2004-01-26 16:48:06 +0000221/* Start debugger and get it to attach to this process. Called if the
222 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000223 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000224 meaningfully get the debugger to continue the program, though; to
225 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000226void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000227{
228 Int pid;
229
230 if ((pid = fork()) == 0) {
231 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000232 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000233
234 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000235 Int status;
236 Int res;
237
nethercote71980f02004-01-24 18:18:54 +0000238 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
239 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000240 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000241 kill(pid, SIGSTOP) == 0 &&
242 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000243 Char pidbuf[15];
244 Char file[30];
245 Char buf[100];
246 Char *bufptr;
247 Char *cmdptr;
248
249 VG_(sprintf)(pidbuf, "%d", pid);
250 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
251
252 bufptr = buf;
253 cmdptr = VG_(clo_db_command);
254
255 while (*cmdptr) {
256 switch (*cmdptr) {
257 case '%':
258 switch (*++cmdptr) {
259 case 'f':
260 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
261 bufptr += VG_(strlen)(file);
262 cmdptr++;
263 break;
264 case 'p':
265 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
266 bufptr += VG_(strlen)(pidbuf);
267 cmdptr++;
268 break;
269 default:
270 *bufptr++ = *cmdptr++;
271 break;
272 }
273 break;
274 default:
275 *bufptr++ = *cmdptr++;
276 break;
277 }
278 }
279
280 *bufptr++ = '\0';
281
282 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000283 res = VG_(system)(buf);
284 if (res == 0) {
285 VG_(message)(Vg_UserMsg, "");
286 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000287 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000288 } else {
289 VG_(message)(Vg_UserMsg, "Apparently failed!");
290 VG_(message)(Vg_UserMsg, "");
291 }
292 }
293
nethercote73b526f2004-10-31 18:48:21 +0000294 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000295 VG_(waitpid)(pid, &status, 0);
296 }
297}
298
299
300/* Print some helpful-ish text about unimplemented things, and give
301 up. */
302void VG_(unimplemented) ( Char* msg )
303{
304 VG_(message)(Vg_UserMsg, "");
305 VG_(message)(Vg_UserMsg,
306 "Valgrind detected that your program requires");
307 VG_(message)(Vg_UserMsg,
308 "the following unimplemented functionality:");
309 VG_(message)(Vg_UserMsg, " %s", msg);
310 VG_(message)(Vg_UserMsg,
311 "This may be because the functionality is hard to implement,");
312 VG_(message)(Vg_UserMsg,
313 "or because no reasonable program would behave this way,");
314 VG_(message)(Vg_UserMsg,
315 "or because nobody has yet needed it. In any case, let us know at");
316 VG_(message)(Vg_UserMsg,
317 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
318 VG_(message)(Vg_UserMsg,
319 "");
320 VG_(message)(Vg_UserMsg,
321 "Valgrind has to exit now. Sorry. Bye!");
322 VG_(message)(Vg_UserMsg,
323 "");
324 VG_(pp_sched_status)();
325 VG_(exit)(1);
326}
327
sewardj2a99cf62004-11-24 10:44:19 +0000328/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000329Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000330{
njncf45fd42004-11-24 16:30:22 +0000331 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000332}
333
njn67516132005-03-22 04:02:43 +0000334Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000335{
336 return INSTR_PTR( VG_(threads)[tid].arch );
337}
338
njnea4b28c2004-11-30 16:04:58 +0000339
nethercote71980f02004-01-24 18:18:54 +0000340/*====================================================================*/
341/*=== Check we were launched by stage 1 ===*/
342/*====================================================================*/
343
344/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000345static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000346{
nethercoteebf1d862004-11-01 18:22:05 +0000347 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000348 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000349
350 for (; auxv->a_type != AT_NULL; auxv++)
351 switch(auxv->a_type) {
352 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000353 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000354 found |= 1;
355 break;
356
357 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000358 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000359 found |= 2;
360 break;
nethercote7f390022004-10-25 17:18:24 +0000361
362 case AT_PHDR:
363 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
364 break;
nethercote71980f02004-01-24 18:18:54 +0000365 }
366
nethercote361a14e2004-07-26 11:11:56 +0000367 if ( found != (1|2) ) {
368 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000369 exit(127);
370 }
nethercote31779c72004-07-30 21:50:15 +0000371 vg_assert(padfile >= 0);
372 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000373}
374
375
376/*====================================================================*/
377/*=== Address space determination ===*/
378/*====================================================================*/
379
nethercote7f390022004-10-25 17:18:24 +0000380extern char _start[];
381
nethercote31779c72004-07-30 21:50:15 +0000382static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000383{
nethercotea3c3cf22004-11-01 18:38:00 +0000384 Int ires;
385 void* vres;
386 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000387
nethercote7f390022004-10-25 17:18:24 +0000388 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
389 // this is a workable approximation
390 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000391 VG_(valgrind_base) = PGROUNDDN(&_start);
392 }
393
nethercote820bd8c2004-09-07 23:04:49 +0000394 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000395
nethercote31779c72004-07-30 21:50:15 +0000396 // This gives the client the largest possible address space while
397 // taking into account the tool's shadow needs.
398 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000399 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000400 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000401 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000402 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000403 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000404 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000405
nethercote31779c72004-07-30 21:50:15 +0000406 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000407 VG_(shadow_end) = VG_(valgrind_base);
408 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000409
nethercotee2097312004-06-27 12:29:56 +0000410#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
411
nethercote71980f02004-01-24 18:18:54 +0000412 if (0)
nethercotee2097312004-06-27 12:29:56 +0000413 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000414 "client_base %p (%dMB)\n"
415 "client_mapbase %p (%dMB)\n"
416 "client_end %p (%dMB)\n"
417 "shadow_base %p (%dMB)\n"
418 "shadow_end %p\n"
419 "valgrind_base %p (%dMB)\n"
420 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000421 VG_(client_base), SEGSIZE(client_base, client_mapbase),
422 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
423 VG_(client_end), SEGSIZE(client_end, shadow_base),
424 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000425 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000426 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
427 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000428 );
429
430#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000431
432 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000433 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000434 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000435 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000436
437 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000438 ires = munmap((void*)VG_(client_base), client_size);
439 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000440
441 // Map shadow memory.
442 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000443 if (shadow_size != 0) {
444 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000445 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000446 if ((void*)-1 == vres) {
447 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000448 "valgrind: Could not allocate address space (%p bytes)\n"
449 "valgrind: for shadow memory\n"
450 "valgrind: Possible causes:\n"
451 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
452 "valgrind: needs at least 1.5GB swap space.\n"
453 "valgrind: - Or, your virtual memory size may be limited (check\n"
454 "valgrind: with 'ulimit -v').\n"
455 "valgrind: - Or, your system may use a kernel that provides only a\n"
456 "valgrind: too-small (eg. 2GB) user address space.\n"
457 , (void*)shadow_size
458 );
nethercoted4722622004-08-30 19:36:42 +0000459 exit(1);
460 }
nethercotee567e702004-07-10 17:49:17 +0000461 }
nethercote71980f02004-01-24 18:18:54 +0000462}
463
464/*====================================================================*/
465/*=== Command line setup ===*/
466/*====================================================================*/
467
468/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
469static char* get_file_clo(char* dir)
470{
471# define FLEN 512
472 Int fd, n;
473 struct stat s1;
474 char* f_clo = NULL;
475 char filename[FLEN];
476
477 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
478 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
479 if ( fd > 0 ) {
480 if ( 0 == fstat(fd, &s1) ) {
481 f_clo = malloc(s1.st_size+1);
482 vg_assert(f_clo);
483 n = read(fd, f_clo, s1.st_size);
484 if (n == -1) n = 0;
485 f_clo[n] = '\0';
486 }
487 close(fd);
488 }
489 return f_clo;
490# undef FLEN
491}
492
493static Int count_args(char* s)
494{
495 Int n = 0;
496 if (s) {
497 char* cp = s;
498 while (True) {
499 // We have alternating sequences: blanks, non-blanks, blanks...
500 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000501 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000502 if ( !*cp ) break;
503 n++;
njn0c0f32a2005-03-26 04:14:01 +0000504 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000505 }
506 }
507 return n;
508}
509
510/* add args out of environment, skipping multiple spaces and -- args */
511static char** copy_args( char* s, char** to )
512{
513 if (s) {
514 char* cp = s;
515 while (True) {
516 // We have alternating sequences: blanks, non-blanks, blanks...
517 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000518 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000519 if ( !*cp ) break;
520 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000521 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000522 if ( *cp ) *cp++ = '\0'; // terminate if necessary
523 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
524 }
525 }
526 return to;
527}
528
529// Augment command line with arguments from environment and .valgrindrc
530// files.
531static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
532{
nethercotef6a1d502004-08-09 12:21:57 +0000533 int vg_argc0 = *vg_argc_inout;
534 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000535
536 char* env_clo = getenv(VALGRINDOPTS);
537 char* f1_clo = get_file_clo( getenv("HOME") );
538 char* f2_clo = get_file_clo(".");
539
540 /* copy any extra args from file or environment, if present */
541 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
542 /* ' ' separated extra options */
543 char **from;
544 char **to;
thughescaca0022004-09-13 10:20:34 +0000545 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
546
547 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
548
nethercote71980f02004-01-24 18:18:54 +0000549 env_arg_count = count_args(env_clo);
550 f1_arg_count = count_args(f1_clo);
551 f2_arg_count = count_args(f2_clo);
552
553 if (0)
554 printf("extra-argc=%d %d %d\n",
555 env_arg_count, f1_arg_count, f2_arg_count);
556
557 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000558 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000559 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000560 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000561 vg_assert(vg_argv0);
562 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000563
564 /* copy argv[0] */
565 *to++ = *from++;
566
567 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
568 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
569 * to override less local ones. */
570 to = copy_args(f1_clo, to);
571 to = copy_args(env_clo, to);
572 to = copy_args(f2_clo, to);
573
574 /* copy original arguments, stopping at command or -- */
575 while (*from) {
576 if (**from != '-')
577 break;
578 if (VG_STREQ(*from, "--")) {
579 from++; /* skip -- */
580 break;
581 }
582 *to++ = *from++;
583 }
584
585 /* add -- */
586 *to++ = "--";
587
nethercotef6a1d502004-08-09 12:21:57 +0000588 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000589
590 /* copy rest of original command line, then NULL */
591 while (*from) *to++ = *from++;
592 *to = NULL;
593 }
594
nethercotef6a1d502004-08-09 12:21:57 +0000595 *vg_argc_inout = vg_argc0;
596 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000597}
598
nethercotef6a1d502004-08-09 12:21:57 +0000599#define VG_CLO_SEP '\01'
600
nethercote71980f02004-01-24 18:18:54 +0000601static void get_command_line( int argc, char** argv,
602 Int* vg_argc_out, Char*** vg_argv_out,
603 char*** cl_argv_out )
604{
nethercotef6a1d502004-08-09 12:21:57 +0000605 int vg_argc0;
606 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000607 char** cl_argv;
608 char* env_clo = getenv(VALGRINDCLO);
609
610 if (env_clo != NULL && *env_clo != '\0') {
611 char *cp;
612 char **cpp;
613
nethercotef6a1d502004-08-09 12:21:57 +0000614 /* OK, VALGRINDCLO is set, which means we must be a child of another
615 Valgrind process using --trace-children, so we're getting all our
616 arguments from VALGRINDCLO, and the entire command line belongs to
617 the client (including argv[0]) */
618 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000619 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000620 if (*cp == VG_CLO_SEP)
621 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000622
nethercotef6a1d502004-08-09 12:21:57 +0000623 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
624 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000625
nethercotef6a1d502004-08-09 12:21:57 +0000626 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000627
628 *cpp++ = "valgrind"; /* nominal argv[0] */
629 *cpp++ = env_clo;
630
nethercotef6a1d502004-08-09 12:21:57 +0000631 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000632 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000633 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000634 *cp++ = '\0'; /* chop it up in place */
635 *cpp++ = cp;
636 }
637 }
638 *cpp = NULL;
639 cl_argv = argv;
640
641 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000642 Bool noaugment = False;
643
nethercote71980f02004-01-24 18:18:54 +0000644 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000645 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000646
nethercotef6a1d502004-08-09 12:21:57 +0000647 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000648 Char* arg = argv[vg_argc0];
649 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000650 break;
sewardjb5f6f512005-03-10 23:59:00 +0000651 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000652 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000653 break;
654 }
njn45270a22005-03-27 01:00:11 +0000655 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000656 }
nethercotef6a1d502004-08-09 12:21:57 +0000657 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000658
659 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000660 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000661 those extra args will already be present in VALGRINDCLO.
662 (We also don't do it when --command-line-only=yes.) */
663 if (!noaugment)
664 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000665 }
666
667 if (0) {
668 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000669 for (i = 0; i < vg_argc0; i++)
670 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000671 }
672
nethercotef6a1d502004-08-09 12:21:57 +0000673 *vg_argc_out = vg_argc0;
674 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000675 *cl_argv_out = cl_argv;
676}
677
678
679/*====================================================================*/
680/*=== Environment and stack setup ===*/
681/*====================================================================*/
682
683/* Scan a colon-separated list, and call a function on each element.
684 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000685 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000686 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000687
688 This routine will return True if (*func) returns True and False if
689 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000690*/
thughes4ad52d02004-06-27 17:37:21 +0000691static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000692{
693 char *cp, *entry;
694 int end;
695
696 if (colsep == NULL ||
697 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000698 return False;
nethercote71980f02004-01-24 18:18:54 +0000699
700 entry = cp = colsep;
701
702 do {
703 end = (*cp == '\0');
704
705 if (*cp == ':' || *cp == '\0') {
706 char save = *cp;
707
708 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000709 if ((*func)(entry)) {
710 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000711 return True;
thughes21942d92004-07-12 09:35:37 +0000712 }
nethercote71980f02004-01-24 18:18:54 +0000713 *cp = save;
714 entry = cp+1;
715 }
716 cp++;
717 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000718
719 return False;
720}
721
nethercote71980f02004-01-24 18:18:54 +0000722/* Prepare the client's environment. This is basically a copy of our
723 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000724 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000725
sewardjb5f6f512005-03-10 23:59:00 +0000726 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000727
728 Yummy. String hacking in C.
729
730 If this needs to handle any more variables it should be hacked
731 into something table driven.
732 */
733static char **fix_environment(char **origenv, const char *preload)
734{
735 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000736 static const char ld_preload[] = "LD_PRELOAD=";
737 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000738 static const int ld_preload_len = sizeof(ld_preload)-1;
739 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
740 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000741 char *inject_path;
742 int inject_path_len;
743 int vgliblen = strlen(VG_(libdir));
744 char **cpp;
745 char **ret;
746 int envc;
747 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
748
749 /* Find the vg_inject.so; also make room for the tool preload
750 library */
751 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
752 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000753 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000754
755 if (preload)
756 snprintf(inject_path, inject_path_len, "%s/%s:%s",
757 VG_(libdir), inject_so, preload);
758 else
759 snprintf(inject_path, inject_path_len, "%s/%s",
760 VG_(libdir), inject_so);
761
762 /* Count the original size of the env */
763 envc = 0; /* trailing NULL */
764 for (cpp = origenv; cpp && *cpp; cpp++)
765 envc++;
766
767 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000768 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000769 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000770
771 /* copy it over */
772 for (cpp = ret; *origenv; )
773 *cpp++ = *origenv++;
774 *cpp = NULL;
775
776 vg_assert(envc == (cpp - ret));
777
778 /* Walk over the new environment, mashing as we go */
779 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000780 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000781 int len = strlen(*cpp) + inject_path_len;
782 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000783 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000784
785 snprintf(cp, len, "%s%s:%s",
786 ld_preload, inject_path, (*cpp)+ld_preload_len);
787
788 *cpp = cp;
789
790 ld_preload_done = 1;
791 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
792 *cpp = "";
793 }
794 }
795
796 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000797 if (!ld_preload_done) {
798 int len = ld_preload_len + inject_path_len;
799 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000800 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000801
802 snprintf(cp, len, "%s%s",
803 ld_preload, inject_path);
804
805 ret[envc++] = cp;
806 }
807
sewardjb5f6f512005-03-10 23:59:00 +0000808 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000809 ret[envc] = NULL;
810
811 return ret;
812}
813
814extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000815
816/* Add a string onto the string table, and return its address */
817static char *copy_str(char **tab, const char *str)
818{
819 char *cp = *tab;
820 char *orig = cp;
821
822 while(*str)
823 *cp++ = *str++;
824 *cp++ = '\0';
825
826 if (0)
nethercote545fe672004-11-01 16:52:43 +0000827 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000828
829 *tab = cp;
830
831 return orig;
832}
833
834/*
835 This sets up the client's initial stack, containing the args,
836 environment and aux vector.
837
838 The format of the stack is:
839
840 higher address +-----------------+
841 | Trampoline code |
842 +-----------------+
843 | |
844 : string table :
845 | |
846 +-----------------+
847 | AT_NULL |
848 - -
849 | auxv |
850 +-----------------+
851 | NULL |
852 - -
853 | envp |
854 +-----------------+
855 | NULL |
856 - -
857 | argv |
858 +-----------------+
859 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000860 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000861 | undefined |
862 : :
863 */
nethercotec25c4492004-10-18 11:52:17 +0000864static Addr setup_client_stack(void* init_sp,
865 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000866 const struct exeinfo *info,
867 UInt** client_auxv)
868{
nethercotee567e702004-07-10 17:49:17 +0000869 void* res;
nethercote71980f02004-01-24 18:18:54 +0000870 char **cpp;
871 char *strtab; /* string table */
872 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000873 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000874 struct ume_auxv *auxv;
875 const struct ume_auxv *orig_auxv;
876 const struct ume_auxv *cauxv;
877 unsigned stringsize; /* total size of strings in bytes */
878 unsigned auxsize; /* total size of auxv in bytes */
879 int argc; /* total argc */
880 int envc; /* total number of env vars */
881 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000882 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000883
884 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000885 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000886
887 /* ==================== compute sizes ==================== */
888
889 /* first of all, work out how big the client stack will be */
890 stringsize = 0;
891
892 /* paste on the extra args if the loader needs them (ie, the #!
893 interpreter and its argument) */
894 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000895 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000896 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000897 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000898 }
nethercoted6a56872004-07-26 15:32:47 +0000899 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000900 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000901 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000902 }
903
904 /* now scan the args we're given... */
905 for (cpp = orig_argv; *cpp; cpp++) {
906 argc++;
907 stringsize += strlen(*cpp) + 1;
908 }
909
910 /* ...and the environment */
911 envc = 0;
912 for (cpp = orig_envp; cpp && *cpp; cpp++) {
913 envc++;
914 stringsize += strlen(*cpp) + 1;
915 }
916
917 /* now, how big is the auxv? */
918 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
919 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
920 if (cauxv->a_type == AT_PLATFORM)
921 stringsize += strlen(cauxv->u.a_ptr) + 1;
922 auxsize += sizeof(*cauxv);
923 }
924
925 /* OK, now we know how big the client stack is */
926 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000927 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000928 sizeof(char **)*argc + /* argv */
929 sizeof(char **) + /* terminal NULL */
930 sizeof(char **)*envc + /* envp */
931 sizeof(char **) + /* terminal NULL */
932 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000933 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000934 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000935
sewardj79048ce2005-02-18 08:28:32 +0000936 if (0) VG_(printf)("stacksize = %d\n", stacksize);
937
nethercotef84f6952004-07-15 14:58:33 +0000938 // decide where stack goes!
939 VG_(clstk_end) = VG_(client_end);
940
nethercote73b526f2004-10-31 18:48:21 +0000941 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000942
nethercote71980f02004-01-24 18:18:54 +0000943 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000944 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000945 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
946
nethercote71980f02004-01-24 18:18:54 +0000947 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000948 stringbase = strtab = (char *)(VG_(client_trampoline_code)
949 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000950
951 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000952
sewardj79048ce2005-02-18 08:28:32 +0000953 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000954 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000955 "clstk_base %p\n"
956 "clstk_end %p\n",
957 stringsize, auxsize, stacksize,
958 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000959
nethercote71980f02004-01-24 18:18:54 +0000960 /* ==================== allocate space ==================== */
961
962 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000963 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000964 PROT_READ | PROT_WRITE | PROT_EXEC,
965 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
966 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000967
968 /* ==================== copy client stack ==================== */
969
nethercotea3c3cf22004-11-01 18:38:00 +0000970 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000971
972 /* --- argc --- */
973 *ptr++ = argc; /* client argc */
974
975 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000976 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000977 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000978 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000979 }
nethercoted6a56872004-07-26 15:32:47 +0000980 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000981 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000982 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000983 }
984 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000985 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000986 }
987 *ptr++ = 0;
988
989 /* --- envp --- */
990 VG_(client_envp) = (Char **)ptr;
991 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000992 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000993 *ptr++ = 0;
994
995 /* --- auxv --- */
996 auxv = (struct ume_auxv *)ptr;
997 *client_auxv = (UInt *)auxv;
998
999 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1000 /* copy the entry... */
1001 *auxv = *orig_auxv;
1002
1003 /* ...and fix up the copy */
1004 switch(auxv->a_type) {
1005 case AT_PHDR:
1006 if (info->phdr == 0)
1007 auxv->a_type = AT_IGNORE;
1008 else
1009 auxv->u.a_val = info->phdr;
1010 break;
1011
1012 case AT_PHNUM:
1013 if (info->phdr == 0)
1014 auxv->a_type = AT_IGNORE;
1015 else
1016 auxv->u.a_val = info->phnum;
1017 break;
1018
1019 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001020 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001021 break;
1022
1023 case AT_PLATFORM: /* points to a platform description string */
1024 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1025 break;
1026
1027 case AT_ENTRY:
1028 auxv->u.a_val = info->entry;
1029 break;
1030
1031 case AT_IGNORE:
1032 case AT_EXECFD:
1033 case AT_PHENT:
1034 case AT_PAGESZ:
1035 case AT_FLAGS:
1036 case AT_NOTELF:
1037 case AT_UID:
1038 case AT_EUID:
1039 case AT_GID:
1040 case AT_EGID:
1041 case AT_CLKTCK:
1042 case AT_HWCAP:
1043 case AT_FPUCW:
1044 case AT_DCACHEBSIZE:
1045 case AT_ICACHEBSIZE:
1046 case AT_UCACHEBSIZE:
1047 /* All these are pointerless, so we don't need to do anything
1048 about them. */
1049 break;
1050
1051 case AT_SECURE:
1052 /* If this is 1, then it means that this program is running
1053 suid, and therefore the dynamic linker should be careful
1054 about LD_PRELOAD, etc. However, since stage1 (the thing
1055 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001056 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001057 set AT_SECURE to 0. */
1058 auxv->u.a_val = 0;
1059 break;
1060
1061 case AT_SYSINFO:
1062 /* Leave this unmolested for now, but we'll update it later
1063 when we set up the client trampoline code page */
1064 break;
1065
1066 case AT_SYSINFO_EHDR:
1067 /* Trash this, because we don't reproduce it */
1068 auxv->a_type = AT_IGNORE;
1069 break;
1070
1071 default:
1072 /* stomp out anything we don't know about */
1073 if (0)
nethercote545fe672004-11-01 16:52:43 +00001074 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001075 auxv->a_type = AT_IGNORE;
1076 break;
1077
1078 }
1079 }
1080 *auxv = *orig_auxv;
1081 vg_assert(auxv->a_type == AT_NULL);
1082
njnc6168192004-11-29 13:54:10 +00001083// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1084// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001085#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001086 /* --- trampoline page --- */
1087 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1088 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001089#endif
nethercotef84f6952004-07-15 14:58:33 +00001090
nethercote71980f02004-01-24 18:18:54 +00001091 vg_assert((strtab-stringbase) == stringsize);
1092
nethercote5ee67ca2004-06-22 14:00:09 +00001093 /* We know the initial ESP is pointing at argc/argv */
1094 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001095 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001096
sewardj79048ce2005-02-18 08:28:32 +00001097 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001098 return cl_esp;
1099}
1100
1101/*====================================================================*/
1102/*=== Find executable ===*/
1103/*====================================================================*/
1104
thughes4ad52d02004-06-27 17:37:21 +00001105static const char* executable_name;
1106
1107static Bool match_executable(const char *entry) {
1108 char buf[strlen(entry) + strlen(executable_name) + 2];
1109
1110 /* empty PATH element means . */
1111 if (*entry == '\0')
1112 entry = ".";
1113
1114 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1115
1116 if (access(buf, R_OK|X_OK) == 0) {
1117 executable_name = strdup(buf);
1118 vg_assert(NULL != executable_name);
1119 return True;
1120 }
1121 return False;
1122}
1123
nethercote71980f02004-01-24 18:18:54 +00001124static const char* find_executable(const char* exec)
1125{
1126 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001127 executable_name = exec;
1128 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001129 /* no '/' - we need to search the path */
1130 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001131 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001132 }
thughes4ad52d02004-06-27 17:37:21 +00001133 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001134}
1135
1136
1137/*====================================================================*/
1138/*=== Loading tools ===*/
1139/*====================================================================*/
1140
1141static void list_tools(void)
1142{
1143 DIR *dir = opendir(VG_(libdir));
1144 struct dirent *de;
1145 int first = 1;
1146
1147 if (dir == NULL) {
1148 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001149 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001150 return;
1151 }
1152
nethercotef4928da2004-06-15 10:54:40 +00001153 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001154 int len = strlen(de->d_name);
1155
njn063c5402004-11-22 16:58:05 +00001156 /* look for vgtool_TOOL.so names */
1157 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1158 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001159 VG_STREQ(de->d_name + len - 3, ".so")) {
1160 if (first) {
1161 fprintf(stderr, "Available tools:\n");
1162 first = 0;
1163 }
1164 de->d_name[len-3] = '\0';
1165 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001166 }
1167 }
1168
1169 closedir(dir);
1170
1171 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001172 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1173 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001174}
1175
1176
1177/* Find and load a tool, and check it looks ok. Also looks to see if there's
1178 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001179static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001180 ToolInfo** toolinfo_out, char **preloadpath_out )
1181{
1182 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001183 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001184 char buf[len];
1185 void* handle;
1186 ToolInfo* toolinfo;
1187 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001188
1189 // XXX: allowing full paths for --tool option -- does it make sense?
1190 // Doesn't allow for vgpreload_<tool>.so.
1191
1192 if (strchr(toolname, '/') != 0) {
1193 /* toolname contains '/', and so must be a pathname */
1194 handle = dlopen(toolname, RTLD_NOW);
1195 } else {
1196 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001197 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001198 handle = dlopen(buf, RTLD_NOW);
1199
1200 if (handle != NULL) {
1201 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1202 if (access(buf, R_OK) == 0) {
1203 preloadpath = strdup(buf);
1204 vg_assert(NULL != preloadpath);
1205 }
1206 }
1207 }
1208
1209 ok = (NULL != handle);
1210 if (!ok) {
1211 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1212 goto bad_load;
1213 }
1214
njn51d827b2005-05-09 01:02:08 +00001215 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001216 ok = (NULL != toolinfo);
1217 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001218 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001219 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1220 goto bad_load;
1221 }
1222
1223 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001224 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1225 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001226 if (!ok) {
1227 fprintf(stderr, "Error:\n"
1228 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001229 " Interface version used by core is: %d (size %d)\n"
1230 " Interface version used by tool is: %d (size %d)\n"
1231 " The version numbers must match.\n",
1232 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001233 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001234 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001235 toolinfo->sizeof_ToolInfo);
1236 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001237 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001238 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001239 else
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 goto bad_load;
1242 }
1243
njn8a97c6d2005-03-31 04:37:24 +00001244 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001245 *toolinfo_out = toolinfo;
1246 *preloadpath_out = preloadpath;
1247 return;
1248
1249
1250 bad_load:
1251 if (handle != NULL)
1252 dlclose(handle);
1253
nethercotef4928da2004-06-15 10:54:40 +00001254 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001255 list_tools();
1256 exit(127);
1257}
1258
nethercotef4928da2004-06-15 10:54:40 +00001259
1260/*====================================================================*/
1261/*=== Command line errors ===*/
1262/*====================================================================*/
1263
1264static void abort_msg ( void )
1265{
nethercotef8548672004-06-21 12:42:35 +00001266 VG_(clo_log_to) = VgLogTo_Fd;
1267 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001268}
1269
1270void VG_(bad_option) ( Char* opt )
1271{
1272 abort_msg();
1273 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1274 VG_(printf)("valgrind: Use --help for more information.\n");
1275 VG_(exit)(1);
1276}
1277
nethercotef4928da2004-06-15 10:54:40 +00001278static void missing_prog ( void )
1279{
1280 abort_msg();
1281 VG_(printf)("valgrind: no program specified\n");
1282 VG_(printf)("valgrind: Use --help for more information.\n");
1283 VG_(exit)(1);
1284}
1285
1286static void config_error ( Char* msg )
1287{
1288 abort_msg();
1289 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1290 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1291 VG_(exit)(1);
1292}
1293
1294
nethercote71980f02004-01-24 18:18:54 +00001295/*====================================================================*/
1296/*=== Loading the client ===*/
1297/*====================================================================*/
1298
nethercotef4928da2004-06-15 10:54:40 +00001299static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001300 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1301{
1302 // If they didn't specify an executable with --exec, and didn't specify
1303 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001304 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001305 if (cl_argv[0] == NULL ||
1306 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1307 {
nethercotef4928da2004-06-15 10:54:40 +00001308 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001309 }
1310 }
1311
1312 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001313 info->exe_base = VG_(client_base);
1314 info->exe_end = VG_(client_end);
1315 info->argv = cl_argv;
1316
nethercotef4928da2004-06-15 10:54:40 +00001317 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001318 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001319 // Totally zero 'info' before continuing.
1320 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001321 } else {
1322 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001323 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001324 ret = do_exec(exec, info);
1325 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001326 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1327 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001328 exit(127);
1329 }
1330 }
1331
1332 /* Copy necessary bits of 'info' that were filled in */
1333 *client_eip = info->init_eip;
1334 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1335}
1336
nethercote969ecf12004-10-13 17:29:01 +00001337/*====================================================================*/
1338/*=== Address space unpadding ===*/
1339/*====================================================================*/
1340
1341typedef struct {
1342 char* killpad_start;
1343 char* killpad_end;
1344 struct stat* killpad_padstat;
1345} killpad_extra;
1346
1347static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1348 int maj, int min, int ino, void* ex)
1349{
1350 killpad_extra* extra = ex;
1351 void *b, *e;
1352 int res;
1353
1354 vg_assert(NULL != extra->killpad_padstat);
1355
1356 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1357 extra->killpad_padstat->st_ino != ino)
1358 return 1;
1359
1360 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1361 return 1;
1362
1363 if (segstart <= extra->killpad_start)
1364 b = extra->killpad_start;
1365 else
1366 b = segstart;
1367
1368 if (segend >= extra->killpad_end)
1369 e = extra->killpad_end;
1370 else
1371 e = segend;
1372
1373 res = munmap(b, (char *)e-(char *)b);
1374 vg_assert(0 == res);
1375
1376 return 1;
1377}
1378
1379// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001380static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001381{
1382 static struct stat padstat;
1383 killpad_extra extra;
1384 int res;
1385
sewardjb5f6f512005-03-10 23:59:00 +00001386 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001387
1388 res = fstat(padfile, &padstat);
1389 vg_assert(0 == res);
1390 extra.killpad_padstat = &padstat;
1391 extra.killpad_start = start;
1392 extra.killpad_end = end;
1393 foreach_map(killpad, &extra);
1394}
1395
sewardj2c5ffbe2005-03-12 13:32:06 +00001396static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001397{
1398 int res = close(padfile);
1399 vg_assert(0 == res);
1400}
1401
nethercote71980f02004-01-24 18:18:54 +00001402
1403/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001404/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001405/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001406
njn25e49d8e72002-09-23 09:36:25 +00001407/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001408VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001409Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001410Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001411Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001412Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001413Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001414Int VG_(clo_verbosity) = 1;
1415Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001416Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001417
nethercotef1e5e152004-09-01 23:58:16 +00001418/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001419 fd is initially stdout, for --help, but gets moved to stderr by default
1420 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001421VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001422Int VG_(clo_log_fd) = 1;
1423Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001424
thughes6233a382004-08-21 11:10:44 +00001425Bool VG_(clo_time_stamp) = False;
1426
sewardj6024b212003-07-13 10:54:33 +00001427Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001428Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001429Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001430Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001431UChar VG_(clo_trace_flags) = 0; // 00000000b
1432UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001433Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001434Bool VG_(clo_trace_syscalls) = False;
1435Bool VG_(clo_trace_signals) = False;
1436Bool VG_(clo_trace_symtab) = False;
sewardjce058b02005-05-01 08:55:38 +00001437Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001438Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001439Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001440Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001441Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001442Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001443Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001444Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001445Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001446Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001447Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001448Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001449Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001450Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001451Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001452Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001453
jsgf855d93d2003-10-13 22:26:55 +00001454static Bool VG_(clo_wait_for_gdb) = False;
1455
sewardjde4a1d02002-03-22 01:27:54 +00001456
sewardj2c5ffbe2005-03-12 13:32:06 +00001457static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001458{
njn25e49d8e72002-09-23 09:36:25 +00001459 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001460"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001461"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001462" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001463" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001464" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001465" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001466" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001467" -q --quiet run silently; only print error msgs\n"
1468" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001469" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001470" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001471" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001472"\n"
1473" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001474" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001475" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001476" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001477" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001478" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001479"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001480" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001481" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1482" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001483" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001484" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001485" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001486" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001487" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1488" --show-below-main=no|yes continue stack traces below main() [no]\n"
1489" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001490" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001491" --db-attach=no|yes start debugger when errors detected? [no]\n"
1492" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1493" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001494" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1495" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001496"\n";
njn7cf0bd32002-06-08 13:36:03 +00001497
njn25e49d8e72002-09-23 09:36:25 +00001498 Char* usage2 =
1499"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001500" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001501" --sanity-level=<number> level of sanity checking to do [1]\n"
1502" --single-step=no|yes translate each instr separately? [no]\n"
1503" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001504" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001505" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001506" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1507" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001508" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001509" --trace-syscalls=no|yes show all system calls? [no]\n"
1510" --trace-signals=no|yes show signal handling details? [no]\n"
1511" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001512" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001513" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001514" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001515#if 0
1516" --model-pthreads=yes|no model the pthreads library [no]\n"
1517#endif
1518" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001519"\n"
1520" --vex-iropt-verbosity 0 .. 9 [0]\n"
1521" --vex-iropt-level 0 .. 2 [2]\n"
1522" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001523" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1524" --vex-guest-max-insns 1 .. 100 [50]\n"
1525" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1526"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001527" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001528" 1000 0000 show conversion into IR\n"
1529" 0100 0000 show after initial opt\n"
1530" 0010 0000 show after instrumentation\n"
1531" 0001 0000 show after second opt\n"
1532" 0000 1000 show after tree building\n"
1533" 0000 0100 show selecting insns\n"
1534" 0000 0010 show after reg-alloc\n"
1535" 0000 0001 show final assembly\n"
1536"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" debugging options for Valgrind tools that report errors\n"
1538" --dump-error=<number> show translation for basic block associated\n"
1539" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001540"\n";
njn3e884182003-04-15 13:03:23 +00001541
1542 Char* usage3 =
1543"\n"
nethercote71980f02004-01-24 18:18:54 +00001544" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n"
njn53612422005-03-12 16:22:54 +00001546" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001547" and licensed under the GNU General Public License, version 2.\n"
1548" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001549"\n"
nethercote137bc552003-11-14 17:47:54 +00001550" Tools are copyright and licensed by their authors. See each\n"
1551" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001552"\n";
njn7cf0bd32002-06-08 13:36:03 +00001553
fitzhardinge98abfc72003-12-16 02:05:15 +00001554 VG_(printf)(usage1);
1555 if (VG_(details).name) {
1556 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001557 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001558 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559 else
1560 VG_(printf)(" (none)\n");
1561 }
nethercote6c999f22004-01-31 22:55:15 +00001562 if (debug_help) {
1563 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001564
nethercote6c999f22004-01-31 22:55:15 +00001565 if (VG_(details).name) {
1566 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1567
1568 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001569 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001570 else
1571 VG_(printf)(" (none)\n");
1572 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001573 }
nethercote421281e2003-11-20 16:20:55 +00001574 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001575 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001576}
sewardjde4a1d02002-03-22 01:27:54 +00001577
nethercote71980f02004-01-24 18:18:54 +00001578static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001579 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001580{
nethercote71980f02004-01-24 18:18:54 +00001581 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001582
sewardj8b635a42004-11-22 19:01:47 +00001583 LibVEX_default_VexControl(& VG_(clo_vex_control));
1584
nethercote71980f02004-01-24 18:18:54 +00001585 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001586 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001589 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001590 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1593 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001594 *need_help = 1;
1595
nethercotef6a1d502004-08-09 12:21:57 +00001596 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001597 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001598
nethercotef6c99d72004-11-09 14:35:43 +00001599 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001600 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001601
nethercotef6a1d502004-08-09 12:21:57 +00001602 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1603 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001604 }
1605 }
nethercote71980f02004-01-24 18:18:54 +00001606}
1607
nethercote5ee67ca2004-06-22 14:00:09 +00001608static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001609{
nethercotef8548672004-06-21 12:42:35 +00001610 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001611 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001612
nethercotee1730692003-11-20 10:38:07 +00001613 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001614 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001615
sewardj19d81412002-06-03 01:10:40 +00001616 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001618 config_error("Please use absolute paths in "
1619 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001620
njnc6168192004-11-29 13:54:10 +00001621// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001622#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001623 {
sewardjb5f6f512005-03-10 23:59:00 +00001624 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001625 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1626 switch(auxp[0]) {
1627 case AT_SYSINFO:
1628 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1629 break;
1630 }
1631 }
1632 }
1633#endif
sewardjde4a1d02002-03-22 01:27:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001638 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001639
thughes3bfd5a02004-07-18 08:05:44 +00001640 /* Look for a colon in the switch name */
1641 while (*colon && *colon != ':' && *colon != '=')
1642 colon++;
nethercote71980f02004-01-24 18:18:54 +00001643
1644 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001645 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001646 if (VG_CLO_STREQN(2, arg, "--") &&
1647 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1648 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1649 {
1650 // prefix matches, convert "--toolname:foo" to "--foo"
1651 if (0)
1652 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001653 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001654 arg[0] = '-';
1655 arg[1] = '-';
1656
1657 } else {
1658 // prefix doesn't match, skip to next arg
1659 continue;
1660 }
1661 }
1662
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001664 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1665 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1666 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001667
njn45270a22005-03-27 01:00:11 +00001668 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001669
nethercote71980f02004-01-24 18:18:54 +00001670 else if (VG_CLO_STREQ(arg, "-v") ||
1671 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001672 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001673
nethercote71980f02004-01-24 18:18:54 +00001674 else if (VG_CLO_STREQ(arg, "-q") ||
1675 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001676 VG_(clo_verbosity)--;
1677
sewardj1cf558c2005-04-25 01:36:56 +00001678 else if (VG_CLO_STREQ(arg, "-d")) {
1679 /* do nothing */
1680 }
1681
njn45270a22005-03-27 01:00:11 +00001682 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1683 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1684 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1685 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1686 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1687 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1688 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001689 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001690 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1691 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1692 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1693 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1694 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1695 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1696 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1697 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1698 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001699 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001700 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1701 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1702 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1703 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1704 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001705
njn45270a22005-03-27 01:00:11 +00001706 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1707 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001708
njn45270a22005-03-27 01:00:11 +00001709 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1710 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1711 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1712 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1713 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001714
njn45270a22005-03-27 01:00:11 +00001715 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001716 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001717 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001718 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001719 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001720 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001721 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001722 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001723 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001724 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001725 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001726 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1727
nethercotef8548672004-06-21 12:42:35 +00001728 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1729 VG_(clo_log_to) = VgLogTo_Fd;
1730 VG_(clo_log_name) = NULL;
1731 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001732 }
1733
nethercotef8548672004-06-21 12:42:35 +00001734 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1735 VG_(clo_log_to) = VgLogTo_File;
1736 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001737 }
njnd6bc3c32005-03-27 00:44:31 +00001738
sewardj603d4102005-01-11 14:01:02 +00001739 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1740 VG_(clo_log_to) = VgLogTo_FileExactly;
1741 VG_(clo_log_name) = &arg[19];
1742 }
sewardjde4a1d02002-03-22 01:27:54 +00001743
nethercotef8548672004-06-21 12:42:35 +00001744 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1745 VG_(clo_log_to) = VgLogTo_Socket;
1746 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001747 }
1748
nethercote71980f02004-01-24 18:18:54 +00001749 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001750 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001751 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001752 VG_(message)(Vg_UserMsg,
1753 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001754 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001755 }
nethercote71980f02004-01-24 18:18:54 +00001756 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001757 VG_(clo_n_suppressions)++;
1758 }
sewardjde4a1d02002-03-22 01:27:54 +00001759
sewardjfa8ec112005-01-19 11:55:34 +00001760 /* "stuvwxyz" --> stuvwxyz (binary) */
1761 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1762 Int j;
1763 char* opt = & arg[14];
1764
1765 if (8 != VG_(strlen)(opt)) {
1766 VG_(message)(Vg_UserMsg,
1767 "--trace-flags argument must have 8 digits");
1768 VG_(bad_option)(arg);
1769 }
1770 for (j = 0; j < 8; j++) {
1771 if ('0' == opt[j]) { /* do nothing */ }
1772 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1773 else {
1774 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1775 "contain 0s and 1s");
1776 VG_(bad_option)(arg);
1777 }
1778 }
1779 }
1780
1781 /* "stuvwxyz" --> stuvwxyz (binary) */
1782 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001783 Int j;
nethercote71980f02004-01-24 18:18:54 +00001784 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001785
sewardj2a99cf62004-11-24 10:44:19 +00001786 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001787 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001788 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001789 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001790 }
sewardj8b635a42004-11-22 19:01:47 +00001791 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001792 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001793 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001794 else {
sewardjfa8ec112005-01-19 11:55:34 +00001795 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001796 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001797 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001798 }
1799 }
1800 }
sewardjde4a1d02002-03-22 01:27:54 +00001801
njn45270a22005-03-27 01:00:11 +00001802 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001803
sewardjd153fae2005-01-10 17:24:47 +00001804 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1805 VG_(clo_gen_suppressions) = 0;
1806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1807 VG_(clo_gen_suppressions) = 1;
1808 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1809 VG_(clo_gen_suppressions) = 2;
1810
nethercote71980f02004-01-24 18:18:54 +00001811 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001812 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001813 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001814 }
njn8c0b3bb2005-03-12 21:20:39 +00001815 skip_arg:
1816 if (arg != vg_argv[i])
1817 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001818 }
1819
sewardj998d40d2004-12-06 14:24:52 +00001820 /* Make VEX control parameters sane */
1821
1822 if (VG_(clo_vex_control).guest_chase_thresh
1823 >= VG_(clo_vex_control).guest_max_insns)
1824 VG_(clo_vex_control).guest_chase_thresh
1825 = VG_(clo_vex_control).guest_max_insns - 1;
1826
1827 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1828 VG_(clo_vex_control).guest_chase_thresh = 0;
1829
1830 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001831
njnf9ebf672003-05-12 21:41:30 +00001832 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001833 VG_(clo_verbosity) = 0;
1834
nethercote04d0fbc2004-01-26 16:48:06 +00001835 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(message)(Vg_UserMsg, "");
1837 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001838 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001839 VG_(message)(Vg_UserMsg,
1840 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001841 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001842 }
1843
nethercotef8548672004-06-21 12:42:35 +00001844 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001845 should be connected to whatever sink has been selected, and we
1846 indiscriminately chuck stuff into it without worrying what the
1847 nature of it is. Oh the wonder of Unix streams. */
1848
nethercotee1730692003-11-20 10:38:07 +00001849 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001850 the terminal any problems to do with processing command line
1851 opts. */
nethercotef8548672004-06-21 12:42:35 +00001852 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001853 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001854
1855 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001856
sewardj4cf05692002-10-27 20:28:29 +00001857 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001858 vg_assert(VG_(clo_log_name) == NULL);
1859 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001860 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001861
sewardj4cf05692002-10-27 20:28:29 +00001862 case VgLogTo_File: {
1863 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001864 Int seq = 0;
1865 Int pid = VG_(getpid)();
1866
nethercotef8548672004-06-21 12:42:35 +00001867 vg_assert(VG_(clo_log_name) != NULL);
1868 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001869
nethercote71980f02004-01-24 18:18:54 +00001870 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001871 if (seq == 0)
1872 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001873 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001874 else
1875 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001876 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001877 seq++;
1878
nethercotef8548672004-06-21 12:42:35 +00001879 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001880 = VG_(open)(logfilename,
1881 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1882 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001883 if (eventually_log_fd >= 0) {
1884 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001885 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001886 } else {
nethercotef8548672004-06-21 12:42:35 +00001887 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001888 VG_(message)(Vg_UserMsg,
1889 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001890 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001891 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001892 "--log-file=<file> (didn't work out for some reason.)");
1893 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001894 }
1895 }
1896 }
sewardj603d4102005-01-11 14:01:02 +00001897 break; /* switch (VG_(clo_log_to)) */
1898 }
1899
1900 case VgLogTo_FileExactly: {
1901 Char logfilename[1000];
1902
1903 vg_assert(VG_(clo_log_name) != NULL);
1904 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1905 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1906
1907 eventually_log_fd
1908 = VG_(open)(logfilename,
1909 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1910 VKI_S_IRUSR|VKI_S_IWUSR);
1911 if (eventually_log_fd >= 0) {
1912 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1913 }
1914 else if (eventually_log_fd != -VKI_EEXIST) {
1915 VG_(message)(Vg_UserMsg,
1916 "Can't create/open log file `%s'; giving up!",
1917 VG_(clo_log_name));
1918 VG_(bad_option)(
1919 "--log-file-exactly=<file> (didn't work out for some reason.)");
1920 /*NOTREACHED*/
1921 }
1922 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001923 }
1924
1925 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001926 vg_assert(VG_(clo_log_name) != NULL);
1927 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1928 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1929 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001930 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001931 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001932 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001933 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001935 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001936 }
nethercotef8548672004-06-21 12:42:35 +00001937 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001938 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001939 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001940 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001941 VG_(message)(Vg_UserMsg,
1942 "Log messages will sent to stderr instead." );
1943 VG_(message)(Vg_UserMsg,
1944 "" );
1945 /* We don't change anything here. */
1946 } else {
nethercotef8548672004-06-21 12:42:35 +00001947 vg_assert(eventually_log_fd > 0);
1948 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001949 VG_(logging_to_filedes) = False;
1950 }
sewardj73cf3bc2002-11-03 03:20:15 +00001951 break;
1952 }
1953
sewardj4cf05692002-10-27 20:28:29 +00001954 }
1955
nethercotef8548672004-06-21 12:42:35 +00001956 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001957 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001958 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001959 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1960 else {
nethercotef8548672004-06-21 12:42:35 +00001961 VG_(clo_log_fd) = eventually_log_fd;
1962 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001963 }
1964
sewardj4cf05692002-10-27 20:28:29 +00001965 /* Ok, the logging sink is running now. Print a suitable preamble.
1966 If logging to file or a socket, write details of parent PID and
1967 command line args, to help people trying to interpret the
1968 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001969
sewardj83adf412002-05-01 01:25:45 +00001970 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001971 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001972 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001973 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001974 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001975 NULL == VG_(details).version
1976 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001977 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001978 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001979
njnd04b7c62002-10-03 14:05:52 +00001980 /* Core details */
1981 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001982 "Using LibVEX rev %s, a library for dynamic binary translation.",
1983 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001984 VG_(message)(Vg_UserMsg,
1985 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1986 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001987 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001988 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001989 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001990 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001991 }
1992
nethercotec1e395d2003-11-10 13:26:49 +00001993 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001994 VG_(message)(Vg_UserMsg, "");
1995 VG_(message)(Vg_UserMsg,
1996 "My PID = %d, parent PID = %d. Prog and args are:",
1997 VG_(getpid)(), VG_(getppid)() );
1998 for (i = 0; i < VG_(client_argc); i++)
1999 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2000 }
2001
sewardjde4a1d02002-03-22 01:27:54 +00002002 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002003 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002004 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002005 VG_(message)(Vg_DebugMsg, "");
2006 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2007 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002008 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002009 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002010
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002012 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002013 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002014 }
nethercotea70f7352004-04-18 12:08:46 +00002015
njn1fd5eb22005-03-13 05:43:23 +00002016 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002017 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2018 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002019 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002020 } else {
2021 #define BUF_LEN 256
2022 Char version_buf[BUF_LEN];
2023 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2024 vg_assert(n <= 256);
2025 if (n > 0) {
2026 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002027 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002028 } else {
njn1fd5eb22005-03-13 05:43:23 +00002029 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002030 }
2031 VG_(close)(fd);
2032 #undef BUF_LEN
2033 }
sewardjde4a1d02002-03-22 01:27:54 +00002034 }
2035
fitzhardinge98abfc72003-12-16 02:05:15 +00002036 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002037 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002038 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002039 needs one, load the default */
2040 static const Char default_supp[] = "default.supp";
2041 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2042 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2043 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2044 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2045 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002046 }
sewardj4cf05692002-10-27 20:28:29 +00002047
sewardjd153fae2005-01-10 17:24:47 +00002048 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002049 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002050 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002051 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002052 VG_(message)(Vg_UserMsg,
2053 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002054 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002055 }
sewardjde4a1d02002-03-22 01:27:54 +00002056}
2057
nethercotef6a1d502004-08-09 12:21:57 +00002058// Build the string for VALGRINDCLO.
2059Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2060{
2061 /* If we're tracing the children, then we need to start it
2062 with our starter+arguments, which are copied into VALGRINDCLO,
2063 except the --exec= option is changed if present.
2064 */
2065 Int i;
2066 Char *exec;
2067 Char *cp;
2068 Char *optvar;
2069 Int optlen, execlen;
2070
2071 // All these allocated blocks are not free - because we're either
2072 // going to exec, or panic when we fail.
2073
2074 // Create --exec= option: "--exec=<exename>"
2075 exec = VG_(arena_malloc)(VG_AR_CORE,
2076 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2077 vg_assert(NULL != exec);
2078 VG_(sprintf)(exec, "--exec=%s", exename);
2079
2080 // Allocate space for optvar (may overestimate by counting --exec twice,
2081 // no matter)
2082 optlen = 1;
2083 for (i = 0; i < vg_argc; i++)
2084 optlen += VG_(strlen)(vg_argv[i]) + 1;
2085 optlen += VG_(strlen)(exec)+1;
2086 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2087
2088 // Copy all valgrind args except the old --exec (if present)
2089 // VG_CLO_SEP is the separator.
2090 cp = optvar;
2091 for (i = 1; i < vg_argc; i++) {
2092 Char *arg = vg_argv[i];
2093
2094 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2095 // don't copy existing --exec= arg
2096 } else if (VG_(strcmp)(arg, "--") == 0) {
2097 // stop at "--"
2098 break;
2099 } else {
2100 // copy non "--exec" arg
2101 Int len = VG_(strlen)(arg);
2102 VG_(memcpy)(cp, arg, len);
2103 cp += len;
2104 *cp++ = VG_CLO_SEP;
2105 }
2106 }
2107 // Add the new --exec= option
2108 execlen = VG_(strlen)(exec);
2109 VG_(memcpy)(cp, exec, execlen);
2110 cp += execlen;
2111 *cp++ = VG_CLO_SEP;
2112
2113 *cp = '\0';
2114
2115 return optvar;
2116}
2117
2118// Build "/proc/self/fd/<execfd>".
2119Char* VG_(build_child_exename)( void )
2120{
2121 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2122 vg_assert(NULL != exename);
2123 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2124 return exename;
2125}
2126
sewardjde4a1d02002-03-22 01:27:54 +00002127
nethercote71980f02004-01-24 18:18:54 +00002128/*====================================================================*/
2129/*=== File descriptor setup ===*/
2130/*====================================================================*/
2131
2132static void setup_file_descriptors(void)
2133{
2134 struct vki_rlimit rl;
2135
2136 /* Get the current file descriptor limits. */
2137 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2138 rl.rlim_cur = 1024;
2139 rl.rlim_max = 1024;
2140 }
2141
2142 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002143 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2144 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002145 } else {
2146 rl.rlim_cur = rl.rlim_max;
2147 }
2148
2149 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002150 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2151 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002152
2153 /* Update the soft limit. */
2154 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2155
nethercotef6a1d502004-08-09 12:21:57 +00002156 if (vgexecfd != -1)
2157 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002158 if (VG_(clexecfd) != -1)
2159 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2160}
2161
nethercote71980f02004-01-24 18:18:54 +00002162/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002163/*=== Initialise program data/text, etc. ===*/
2164/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002165
sewardjb5f6f512005-03-10 23:59:00 +00002166static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2167 UInt dev, UInt ino, ULong foffset,
2168 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002169{
nethercote71980f02004-01-24 18:18:54 +00002170 /* Only record valgrind mappings for now, without loading any
2171 symbols. This is so we know where the free space is before we
2172 start allocating more memory (note: heap is OK, it's just mmap
2173 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002174 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002175 VG_(debugLog)(2, "main",
2176 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002177 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002178 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002179 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2180 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002181 /* update VG_(valgrind_last) if it looks wrong */
2182 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002183 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002184 }
sewardjde4a1d02002-03-22 01:27:54 +00002185}
2186
nethercote71980f02004-01-24 18:18:54 +00002187// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002188Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002189
sewardjb5f6f512005-03-10 23:59:00 +00002190/*
2191 This second pass adds in client mappings, and loads symbol tables
2192 for all interesting mappings. The trouble is that things can
2193 change as we go, because we're calling the Tool to track memory as
2194 we find it.
2195
2196 So for Valgrind mappings, we don't replace any mappings which
2197 aren't still identical (which will include the .so mappings, so we
2198 will load their symtabs)>
2199 */
2200static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2201 UInt dev, UInt ino, ULong foffset,
2202 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002203{
nethercote71980f02004-01-24 18:18:54 +00002204 UInt flags;
2205 Bool is_stack_segment;
2206 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002207
nethercote71980f02004-01-24 18:18:54 +00002208 is_stack_segment
2209 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002210
sewardj8c615892005-04-25 02:38:28 +00002211 VG_(debugLog)(2, "main",
2212 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002213 (void*)start, (void*)(start+size), prot, is_stack_segment,
2214 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
nethercote71980f02004-01-24 18:18:54 +00002216 if (is_stack_segment)
2217 flags = SF_STACK | SF_GROWDOWN;
2218 else
2219 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002220
nethercote71980f02004-01-24 18:18:54 +00002221 if (filename != NULL)
2222 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002223
sewardjb5f6f512005-03-10 23:59:00 +00002224#if 0
2225 // This needs to be fixed properly. jrs 20050307
2226 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2227 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002228
sewardjb5f6f512005-03-10 23:59:00 +00002229 /* We have to be a bit careful about inserting new mappings into
2230 the Valgrind part of the address space. We're actively
2231 changing things as we parse these mappings, particularly in
2232 shadow memory, and so we don't want to overwrite those
2233 changes. Therefore, we only insert/update a mapping if it is
2234 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002235
sewardjb5f6f512005-03-10 23:59:00 +00002236 NOTE: we're only talking about the Segment list mapping
2237 metadata; this doesn't actually mmap anything more. */
2238 if (filename || (s && s->addr == start && s->len == size)) {
2239 flags |= SF_VALGRIND;
2240 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2241 } else {
2242 /* assert range is already mapped */
2243 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2244 }
2245 } else
2246#endif
2247 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2248
2249 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2250 VG_TRACK( new_mem_startup, start, size,
2251 !!(prot & VKI_PROT_READ),
2252 !!(prot & VKI_PROT_WRITE),
2253 !!(prot & VKI_PROT_EXEC));
2254 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002255
nethercote71980f02004-01-24 18:18:54 +00002256 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002257 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002258 vg_assert(0 != r_esp);
2259 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002260 if (0) {
2261 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002262 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002263 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2264 r_esp, start+size);
2265 }
nethercote71980f02004-01-24 18:18:54 +00002266 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002267 // what's this for?
2268 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002269 }
sewardjde4a1d02002-03-22 01:27:54 +00002270}
2271
2272
nethercote71980f02004-01-24 18:18:54 +00002273/*====================================================================*/
2274/*=== Sanity check machinery (permanently engaged) ===*/
2275/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002276
2277/* A fast sanity check -- suitable for calling circa once per
2278 millisecond. */
2279
nethercote885dd912004-08-03 23:14:00 +00002280void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002281{
sewardjb5f6f512005-03-10 23:59:00 +00002282 ThreadId tid;
2283
njn37cea302002-09-30 11:24:00 +00002284 VGP_PUSHCC(VgpCoreCheapSanity);
2285
nethercote27fec902004-06-16 21:26:32 +00002286 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002287
2288 /* --- First do all the tests that we can do quickly. ---*/
2289
nethercote297effd2004-08-02 15:07:57 +00002290 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002291
njn25e49d8e72002-09-23 09:36:25 +00002292 /* Check stuff pertaining to the memory check system. */
2293
2294 /* Check that nobody has spuriously claimed that the first or
2295 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002296 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002297 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002298 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002299 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002300 }
njn25e49d8e72002-09-23 09:36:25 +00002301
2302 /* --- Now some more expensive checks. ---*/
2303
2304 /* Once every 25 times, check some more expensive stuff. */
2305 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002306 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002307 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002308
njn37cea302002-09-30 11:24:00 +00002309 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002310 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002311
2312# if 0
2313 { void zzzmemscan(void); zzzmemscan(); }
2314# endif
2315
nethercote297effd2004-08-02 15:07:57 +00002316 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002317 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002318
2319 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002320 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002321 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002322 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002323 }
sewardjb5f6f512005-03-10 23:59:00 +00002324
2325 /* Check that Segments and /proc/self/maps match up */
2326 //vg_assert(VG_(sanity_check_memory)());
2327
2328 /* Look for stack overruns. Visit all threads. */
2329 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002330 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002331
2332 if (VG_(threads)[tid].status == VgTs_Empty ||
2333 VG_(threads)[tid].status == VgTs_Zombie)
2334 continue;
2335
2336 remains = VGA_(stack_unused)(tid);
2337 if (remains < VKI_PAGE_SIZE)
2338 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2339 tid, remains);
2340 }
2341
njn25e49d8e72002-09-23 09:36:25 +00002342 /*
nethercote297effd2004-08-02 15:07:57 +00002343 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002344 */
njn37cea302002-09-30 11:24:00 +00002345 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002346 }
2347
nethercote27fec902004-06-16 21:26:32 +00002348 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002349 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002350 /* Check sanity of the low-level memory manager. Note that bugs
2351 in the client's code can cause this to fail, so we don't do
2352 this check unless specially asked for. And because it's
2353 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002354 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002355 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002356 }
njn37cea302002-09-30 11:24:00 +00002357 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002358}
nethercote71980f02004-01-24 18:18:54 +00002359
2360
2361/*====================================================================*/
2362/*=== main() ===*/
2363/*====================================================================*/
2364
nethercotec314eba2004-07-15 12:59:41 +00002365/*
2366 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002367 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002368 loads the client executable (and the dynamic linker, if necessary)
2369 into the client part, and calls into Valgrind proper.
2370
2371 The code is careful not to allow spurious mappings to appear in the
2372 wrong parts of the address space. In particular, to make sure
2373 dlopen puts things in the right place, it will pad out the forbidden
2374 chunks of address space so that dlopen is forced to put things where
2375 we want them.
2376
2377 The memory map it creates is:
2378
njn80950732005-03-26 00:18:45 +00002379 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002380 | client address space |
2381 : :
2382 : :
2383 | client stack |
2384 client_end +-------------------------+
2385 | redzone |
2386 shadow_base +-------------------------+
2387 | |
nethercote996901a2004-08-03 13:29:09 +00002388 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002389 | (may be 0 sized) |
2390 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002391 valgrind_base +-------------------------+
2392 | kickstart executable |
2393 | valgrind heap vvvvvvvvv| (barely used)
2394 - -
2395 | valgrind .so files |
2396 | and mappings |
2397 - -
2398 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002399 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002400 : kernel :
2401
2402 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2403 VG_(mmap)(), we need to build the segment skip-list, so we know where
2404 we can put things. However, building that structure requires
2405 allocating memory. So we need to a bootstrapping process. It's done
2406 by making VG_(arena_malloc)() have a special static superblock that's
2407 used for the first 1MB's worth of allocations. This is enough to
2408 build the segment skip-list.
2409*/
2410
thughes4ad52d02004-06-27 17:37:21 +00002411
sewardj1cf558c2005-04-25 01:36:56 +00002412/* This may be needed before m_mylibc is OK to run. */
2413static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2414{
2415 while (True) {
2416 if (*s1 == 0 && *s2 == 0) return 0;
2417 if (*s1 == 0) return -1;
2418 if (*s2 == 0) return 1;
2419
2420 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2421 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2422
2423 s1++; s2++;
2424 }
2425}
2426
2427
sewardjb5f6f512005-03-10 23:59:00 +00002428int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002429{
2430 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002431 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002432 const char *exec = NULL;
2433 char *preload; /* tool-specific LD_PRELOAD .so */
2434 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002435 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002436 struct exeinfo info;
2437 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002438 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002439 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002440 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002441 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002442 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002443
2444 //============================================================
2445 // Nb: startup is complex. Prerequisites are shown at every step.
2446 //
2447 // *** Be very careful when messing with the order ***
2448 //============================================================
2449
sewardj1cf558c2005-04-25 01:36:56 +00002450 //--------------------------------------------------------------
2451 // Start up the logging mechanism
2452 // p: none
2453 //--------------------------------------------------------------
2454 /* Start the debugging-log system ASAP. First find out how many
2455 "-d"s were specified. This is a pre-scan of the command line. */
2456 loglevel = 0;
2457 for (i = 1; i < argc; i++) {
2458 if (argv[i][0] != '-')
2459 break;
2460 if (0 == local_strcmp(argv[i], "--"))
2461 break;
2462 if (0 == local_strcmp(argv[i], "-d"))
2463 loglevel++;
2464 }
2465
2466 /* ... and start the debug logger. Now we can safely emit logging
2467 messages all through startup. */
2468 VG_(debugLog_startup)(loglevel, "Stage 2");
2469
nethercotef4928da2004-06-15 10:54:40 +00002470 //============================================================
2471 // Command line argument handling order:
2472 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002473 // (including the tool-specific usage)
2474 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002475 // * Then, if client is missing, abort with error msg
2476 // * Then, if any cmdline args are bad, abort with error msg
2477 //============================================================
2478
fitzhardingeb50068f2004-02-24 23:42:55 +00002479 // Get the current process datasize rlimit, and set it to zero.
2480 // This prevents any internal uses of brk() from having any effect.
2481 // We remember the old value so we can restore it on exec, so that
2482 // child processes will have a reasonable brk value.
2483 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2484 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2485 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002486
2487 // Get the current process stack rlimit.
2488 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2489
nethercote71980f02004-01-24 18:18:54 +00002490 //--------------------------------------------------------------
2491 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002492 // p: none
nethercote71980f02004-01-24 18:18:54 +00002493 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002494 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002495 {
sewardj1fbc1a52005-04-25 02:05:54 +00002496 void* init_sp = argv - 1;
2497 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002498 }
2499
2500 //--------------------------------------------------------------
2501 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002502 // p: none
nethercote71980f02004-01-24 18:18:54 +00002503 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002504 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002505 if (cp != NULL)
2506 VG_(libdir) = cp;
2507 }
2508
2509 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002510 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2511 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002512 // p: none
nethercote71980f02004-01-24 18:18:54 +00002513 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002514 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002515 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002516 pre_process_cmd_line_options(&need_help, &tool, &exec);
2517
2518 //==============================================================
2519 // Nb: once a tool is specified, the tool.so must be loaded even if
2520 // they specified --help or didn't specify a client program.
2521 //==============================================================
2522
2523 //--------------------------------------------------------------
2524 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002525 // p: set-libdir [for VG_(libdir)]
2526 // p: pre_process_cmd_line_options() [for 'tool']
2527 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002528 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002529 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002530
2531 //==============================================================
2532 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002533 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002534 //==============================================================
2535
2536 //--------------------------------------------------------------
2537 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002538 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002539 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002540 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002541 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002542
2543 //--------------------------------------------------------------
2544 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002545 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2546 // p: layout_remaining_space [so there's space]
2547 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002548 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002549 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002550
2551 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002552 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002553 // p: layout_remaining_space() [everything must be mapped in before now]
2554 // p: load_client() [ditto]
2555 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002556 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2557 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002558
2559 //--------------------------------------------------------------
2560 // Set up client's environment
2561 // p: set-libdir [for VG_(libdir)]
2562 // p: load_tool() [for 'preload']
2563 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002564 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002565 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002566
2567 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002568 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002569 // p: load_client() [for 'info']
2570 // p: fix_environment() [for 'env']
2571 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002572 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002573 {
sewardj1fbc1a52005-04-25 02:05:54 +00002574 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002575
sewardj1fbc1a52005-04-25 02:05:54 +00002576 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2577 &client_auxv);
2578 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002579 }
nethercote71980f02004-01-24 18:18:54 +00002580
sewardj1fbc1a52005-04-25 02:05:54 +00002581 VG_(debugLog)(2, "main",
2582 "Client info: "
2583 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2584 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2585 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002586
2587 //==============================================================
2588 // Finished setting up operating environment. Now initialise
2589 // Valgrind. (This is where the old VG_(main)() started.)
2590 //==============================================================
2591
2592 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002593 // setup file descriptors
2594 // p: n/a
2595 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002596 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002597 setup_file_descriptors();
2598
2599 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002600 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002601 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002602 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002603 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002604 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2605
2606 //==============================================================
2607 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2608 //==============================================================
2609
2610 //--------------------------------------------------------------
2611 // Init tool: pre_clo_init, process cmd line, post_clo_init
2612 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002613 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002614 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2615 // p: parse_procselfmaps [so VG segments are setup so tool can
2616 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002617 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002618 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002619 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002620 VG_(sanity_check_needs)();
2621
nethercotef4928da2004-06-15 10:54:40 +00002622 // If --tool and --help/--help-debug was given, now give the core+tool
2623 // help message
nethercotef4928da2004-06-15 10:54:40 +00002624 if (need_help) {
2625 usage(/*--help-debug?*/2 == need_help);
2626 }
nethercotec314eba2004-07-15 12:59:41 +00002627 process_cmd_line_options(client_auxv, tool);
2628
njn51d827b2005-05-09 01:02:08 +00002629 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002630
2631 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002632 // Determine CPU architecture and subarchitecture
2633 // p: none
2634 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002635 VG_(debugLog)(1, "main", "Check CPU arch/subarch\n");
sewardj51ac0872004-12-21 01:20:49 +00002636 { Bool ok = VGA_(getArchAndSubArch)(
2637 & VG_(vex_arch), & VG_(vex_subarch) );
2638 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002639 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002640 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002641 VG_(printf)(" Supported CPUs are:\n");
2642 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2643 "AMD Athlon or above)\n");
2644 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002645 VG_(exit)(1);
2646 }
2647 if (VG_(clo_verbosity) > 2) {
2648 VG_(message)(Vg_DebugMsg,
2649 "Host CPU: arch = %s, subarch = %s",
2650 LibVEX_ppVexArch( VG_(vex_arch) ),
2651 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2652 }
2653 }
2654
2655 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002656 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002657 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002658 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002659 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002660 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002661 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002662 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002663 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002664 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002665
sewardj21c6d0f2005-05-02 10:33:44 +00002666#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002667 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002668 // Protect client trampoline page (which is also sysinfo stuff)
2669 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002670 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002671 {
2672 Segment *seg;
2673 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2674 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002675
sewardjb5f6f512005-03-10 23:59:00 +00002676 /* Make sure this segment isn't treated as stack */
2677 seg = VG_(find_segment)(VG_(client_trampoline_code));
2678 if (seg)
2679 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2680 }
sewardj21c6d0f2005-05-02 10:33:44 +00002681#endif
sewardjb5f6f512005-03-10 23:59:00 +00002682
nethercotec314eba2004-07-15 12:59:41 +00002683 //==============================================================
2684 // Can use VG_(map)() after segments set up
2685 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002686
2687 //--------------------------------------------------------------
2688 // Allow GDB attach
2689 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2690 //--------------------------------------------------------------
2691 /* Hook to delay things long enough so we can get the pid and
2692 attach GDB in another shell. */
2693 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002694 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002695 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2696 /* jrs 20050206: I don't understand why this works on x86. On
2697 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2698 work. */
2699 /* do "jump *$eip" to skip this in gdb (x86) */
2700 //VG_(do_syscall0)(__NR_pause);
2701 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002702 }
2703
sewardjb5d320c2005-03-13 18:57:15 +00002704 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002705 // Search for file descriptors that are inherited from our parent
2706 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2707 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002708 if (VG_(clo_track_fds)) {
2709 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002710 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002711 }
nethercote71980f02004-01-24 18:18:54 +00002712
2713 //--------------------------------------------------------------
2714 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002715 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2716 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002717 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002718 VG_(scheduler_init)();
2719
2720 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002721 // Initialise the pthread model
2722 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002723 // load_client() [for 'client_eip']
2724 // setup_client_stack() [for 'sp_at_startup']
2725 // setup_scheduler() [for the rest of state 1 stuff]
2726 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002727 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002728 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002729
2730 // Tell the tool that we just wrote to the registers.
2731 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2732 sizeof(VexGuestArchState));
2733
sewardj2a99cf62004-11-24 10:44:19 +00002734 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002735 // Initialise the pthread model
2736 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002737 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002738 //if (VG_(clo_model_pthreads))
2739 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002740
2741 //--------------------------------------------------------------
2742 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002743 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002744 //--------------------------------------------------------------
2745 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002746 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002747 VG_(sigstartup_actions)();
2748
2749 //--------------------------------------------------------------
2750 // Perhaps we're profiling Valgrind?
2751 // p: process_cmd_line_options() [for VG_(clo_profile)]
2752 // p: others?
2753 //
2754 // XXX: this seems to be broken? It always says the tool wasn't built
2755 // for profiling; vg_profile.c's functions don't seem to be overriding
2756 // vg_dummy_profile.c's?
2757 //
2758 // XXX: want this as early as possible. Looking for --profile
2759 // in pre_process_cmd_line_options() could get it earlier.
2760 //--------------------------------------------------------------
2761 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002762 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002763
2764 VGP_PUSHCC(VgpStartup);
2765
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 // Read suppression file
2768 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2769 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002770 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2771 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002772 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002773 }
nethercote71980f02004-01-24 18:18:54 +00002774
2775 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002776 // Initialise translation table and translation cache
2777 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2778 // aren't identified as part of the client, which would waste
2779 // > 20M of virtual address space.]
2780 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002781 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002782 VG_(init_tt_tc)();
2783
2784 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002785 // Read debug info to find glibc entry points to intercept
2786 // p: parse_procselfmaps? [XXX for debug info?]
2787 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2788 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002789 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002790 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002791 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002792
2793 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002794 // Verbosity message
2795 // p: end_rdtsc_calibration [so startup message is printed first]
2796 //--------------------------------------------------------------
2797 if (VG_(clo_verbosity) == 1)
2798 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
sewardjb5f6f512005-03-10 23:59:00 +00002814 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002815
sewardj1fbc1a52005-04-25 02:05:54 +00002816 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002817 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002818
sewardjb5f6f512005-03-10 23:59:00 +00002819 abort();
2820}
2821
2822
2823/* Do everything which needs doing when the last thread exits */
2824void VG_(shutdown_actions)(ThreadId tid)
2825{
2826 vg_assert(tid == VG_(master_tid));
2827 vg_assert(VG_(is_running_thread)(tid));
2828
2829 // Wait for all other threads to exit.
2830 VGA_(reap_threads)(tid);
2831
2832 VG_(clo_model_pthreads) = False;
2833
2834 // Clean the client up before the final report
2835 VGA_(final_tidyup)(tid);
2836
2837 // OK, done
2838 VG_(exit_thread)(tid);
2839
2840 /* should be no threads left */
2841 vg_assert(VG_(count_living_threads)() == 0);
2842
2843 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002844 //--------------------------------------------------------------
2845 // Finalisation: cleanup, messages, etc. Order no so important, only
2846 // affects what order the messages come.
2847 //--------------------------------------------------------------
2848 if (VG_(clo_verbosity) > 0)
2849 VG_(message)(Vg_UserMsg, "");
2850
nethercote71980f02004-01-24 18:18:54 +00002851 /* Print out file descriptor summary and stats. */
2852 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002853 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002854
njn95ec8702004-11-22 16:46:13 +00002855 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002856 VG_(show_all_errors)();
2857
njn51d827b2005-05-09 01:02:08 +00002858 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002859
nethercote885dd912004-08-03 23:14:00 +00002860 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002861
2862 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002863 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002864
nethercote71980f02004-01-24 18:18:54 +00002865 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002866 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002867 if (VG_(clo_profile_flags) > 0)
2868 VG_(show_BB_profile)();
2869
sewardj8b635a42004-11-22 19:01:47 +00002870 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002871 if (0)
2872 LibVEX_ShowAllocStats();
njne96be672005-05-08 19:08:54 +00002873}
sewardj8b635a42004-11-22 19:01:47 +00002874
sewardjde4a1d02002-03-22 01:27:54 +00002875/*--------------------------------------------------------------------*/
2876/*--- end vg_main.c ---*/
2877/*--------------------------------------------------------------------*/