blob: 3bc1792be2b85c3a97036e864ee7dc33f7b40a20 [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
njn26f02512004-11-22 18:33:15 +00001215 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001216 ok = (NULL != toolinfo);
1217 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001218 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
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) &&
1224 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001225 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"
1229 " Interface version used by core is: %d.%d (size %d)\n"
1230 " Interface version used by tool is: %d.%d (size %d)\n"
1231 " The major version numbers must match.\n",
1232 VG_CORE_INTERFACE_MAJOR_VERSION,
1233 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001234 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001235 toolinfo->interface_major_version,
1236 toolinfo->interface_minor_version,
1237 toolinfo->sizeof_ToolInfo);
1238 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1239 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 else
nethercote996901a2004-08-03 13:29:09 +00001242 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001243 goto bad_load;
1244 }
1245
njn8a97c6d2005-03-31 04:37:24 +00001246 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001247 *toolinfo_out = toolinfo;
1248 *preloadpath_out = preloadpath;
1249 return;
1250
1251
1252 bad_load:
1253 if (handle != NULL)
1254 dlclose(handle);
1255
nethercotef4928da2004-06-15 10:54:40 +00001256 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001257 list_tools();
1258 exit(127);
1259}
1260
nethercotef4928da2004-06-15 10:54:40 +00001261
1262/*====================================================================*/
1263/*=== Command line errors ===*/
1264/*====================================================================*/
1265
1266static void abort_msg ( void )
1267{
nethercotef8548672004-06-21 12:42:35 +00001268 VG_(clo_log_to) = VgLogTo_Fd;
1269 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001270}
1271
1272void VG_(bad_option) ( Char* opt )
1273{
1274 abort_msg();
1275 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1276 VG_(printf)("valgrind: Use --help for more information.\n");
1277 VG_(exit)(1);
1278}
1279
nethercotef4928da2004-06-15 10:54:40 +00001280static void missing_prog ( void )
1281{
1282 abort_msg();
1283 VG_(printf)("valgrind: no program specified\n");
1284 VG_(printf)("valgrind: Use --help for more information.\n");
1285 VG_(exit)(1);
1286}
1287
1288static void config_error ( Char* msg )
1289{
1290 abort_msg();
1291 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1292 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1293 VG_(exit)(1);
1294}
1295
1296
nethercote71980f02004-01-24 18:18:54 +00001297/*====================================================================*/
1298/*=== Loading the client ===*/
1299/*====================================================================*/
1300
nethercotef4928da2004-06-15 10:54:40 +00001301static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001302 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1303{
1304 // If they didn't specify an executable with --exec, and didn't specify
1305 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001306 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001307 if (cl_argv[0] == NULL ||
1308 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1309 {
nethercotef4928da2004-06-15 10:54:40 +00001310 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001311 }
1312 }
1313
1314 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001315 info->exe_base = VG_(client_base);
1316 info->exe_end = VG_(client_end);
1317 info->argv = cl_argv;
1318
nethercotef4928da2004-06-15 10:54:40 +00001319 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001320 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001321 // Totally zero 'info' before continuing.
1322 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001323 } else {
1324 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001325 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001326 ret = do_exec(exec, info);
1327 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001328 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1329 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001330 exit(127);
1331 }
1332 }
1333
1334 /* Copy necessary bits of 'info' that were filled in */
1335 *client_eip = info->init_eip;
1336 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1337}
1338
nethercote969ecf12004-10-13 17:29:01 +00001339/*====================================================================*/
1340/*=== Address space unpadding ===*/
1341/*====================================================================*/
1342
1343typedef struct {
1344 char* killpad_start;
1345 char* killpad_end;
1346 struct stat* killpad_padstat;
1347} killpad_extra;
1348
1349static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1350 int maj, int min, int ino, void* ex)
1351{
1352 killpad_extra* extra = ex;
1353 void *b, *e;
1354 int res;
1355
1356 vg_assert(NULL != extra->killpad_padstat);
1357
1358 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1359 extra->killpad_padstat->st_ino != ino)
1360 return 1;
1361
1362 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1363 return 1;
1364
1365 if (segstart <= extra->killpad_start)
1366 b = extra->killpad_start;
1367 else
1368 b = segstart;
1369
1370 if (segend >= extra->killpad_end)
1371 e = extra->killpad_end;
1372 else
1373 e = segend;
1374
1375 res = munmap(b, (char *)e-(char *)b);
1376 vg_assert(0 == res);
1377
1378 return 1;
1379}
1380
1381// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001382static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001383{
1384 static struct stat padstat;
1385 killpad_extra extra;
1386 int res;
1387
sewardjb5f6f512005-03-10 23:59:00 +00001388 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001389
1390 res = fstat(padfile, &padstat);
1391 vg_assert(0 == res);
1392 extra.killpad_padstat = &padstat;
1393 extra.killpad_start = start;
1394 extra.killpad_end = end;
1395 foreach_map(killpad, &extra);
1396}
1397
sewardj2c5ffbe2005-03-12 13:32:06 +00001398static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001399{
1400 int res = close(padfile);
1401 vg_assert(0 == res);
1402}
1403
nethercote71980f02004-01-24 18:18:54 +00001404
1405/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001406/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001407/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001408
njn25e49d8e72002-09-23 09:36:25 +00001409/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001410VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001411Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001412Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001413Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001414Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001415Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001416Int VG_(clo_verbosity) = 1;
1417Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001418Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001419
nethercotef1e5e152004-09-01 23:58:16 +00001420/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001421 fd is initially stdout, for --help, but gets moved to stderr by default
1422 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001423VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001424Int VG_(clo_log_fd) = 1;
1425Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001426
thughes6233a382004-08-21 11:10:44 +00001427Bool VG_(clo_time_stamp) = False;
1428
sewardj6024b212003-07-13 10:54:33 +00001429Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001430Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001431Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001432Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001433UChar VG_(clo_trace_flags) = 0; // 00000000b
1434UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001435Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001436Bool VG_(clo_trace_syscalls) = False;
1437Bool VG_(clo_trace_signals) = False;
1438Bool VG_(clo_trace_symtab) = False;
sewardjce058b02005-05-01 08:55:38 +00001439Bool VG_(clo_trace_cfi) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001440Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001441Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001442Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001443Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001444Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001445Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001446Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001447Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001448Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001449Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001450Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001451Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001452Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001453Bool VG_(clo_show_emwarns) = False;
sewardj97724e52005-04-02 23:40:59 +00001454Int VG_(clo_max_stackframe) = 2000000;
sewardj2370f3b2002-11-30 15:01:01 +00001455
jsgf855d93d2003-10-13 22:26:55 +00001456static Bool VG_(clo_wait_for_gdb) = False;
1457
sewardjde4a1d02002-03-22 01:27:54 +00001458
sewardj2c5ffbe2005-03-12 13:32:06 +00001459static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001460{
njn25e49d8e72002-09-23 09:36:25 +00001461 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001462"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001463"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001464" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001465" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001466" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001467" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001468" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001469" -q --quiet run silently; only print error msgs\n"
1470" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001471" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001472" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001473" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001474"\n"
1475" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001476" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001477" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001478" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001479" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001480" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001481"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001482" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001483" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1484" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001485" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001486" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001487" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001488" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001489" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1490" --show-below-main=no|yes continue stack traces below main() [no]\n"
1491" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001492" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001493" --db-attach=no|yes start debugger when errors detected? [no]\n"
1494" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1495" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001496" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1497" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001498"\n";
njn7cf0bd32002-06-08 13:36:03 +00001499
njn25e49d8e72002-09-23 09:36:25 +00001500 Char* usage2 =
1501"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001502" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --sanity-level=<number> level of sanity checking to do [1]\n"
1504" --single-step=no|yes translate each instr separately? [no]\n"
1505" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001506" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001507" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001508" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1509" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001510" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001511" --trace-syscalls=no|yes show all system calls? [no]\n"
1512" --trace-signals=no|yes show signal handling details? [no]\n"
1513" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001514" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001515" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001516" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001517#if 0
1518" --model-pthreads=yes|no model the pthreads library [no]\n"
1519#endif
1520" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001521"\n"
1522" --vex-iropt-verbosity 0 .. 9 [0]\n"
1523" --vex-iropt-level 0 .. 2 [2]\n"
1524" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001525" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1526" --vex-guest-max-insns 1 .. 100 [50]\n"
1527" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1528"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001529" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001530" 1000 0000 show conversion into IR\n"
1531" 0100 0000 show after initial opt\n"
1532" 0010 0000 show after instrumentation\n"
1533" 0001 0000 show after second opt\n"
1534" 0000 1000 show after tree building\n"
1535" 0000 0100 show selecting insns\n"
1536" 0000 0010 show after reg-alloc\n"
1537" 0000 0001 show final assembly\n"
1538"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001539" debugging options for Valgrind tools that report errors\n"
1540" --dump-error=<number> show translation for basic block associated\n"
1541" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001542"\n";
njn3e884182003-04-15 13:03:23 +00001543
1544 Char* usage3 =
1545"\n"
nethercote71980f02004-01-24 18:18:54 +00001546" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n"
njn53612422005-03-12 16:22:54 +00001548" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001549" and licensed under the GNU General Public License, version 2.\n"
1550" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001551"\n"
nethercote137bc552003-11-14 17:47:54 +00001552" Tools are copyright and licensed by their authors. See each\n"
1553" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001554"\n";
njn7cf0bd32002-06-08 13:36:03 +00001555
fitzhardinge98abfc72003-12-16 02:05:15 +00001556 VG_(printf)(usage1);
1557 if (VG_(details).name) {
1558 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001560 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001561 else
1562 VG_(printf)(" (none)\n");
1563 }
nethercote6c999f22004-01-31 22:55:15 +00001564 if (debug_help) {
1565 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001566
nethercote6c999f22004-01-31 22:55:15 +00001567 if (VG_(details).name) {
1568 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1569
1570 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001571 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001572 else
1573 VG_(printf)(" (none)\n");
1574 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001575 }
nethercote421281e2003-11-20 16:20:55 +00001576 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001577 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001578}
sewardjde4a1d02002-03-22 01:27:54 +00001579
nethercote71980f02004-01-24 18:18:54 +00001580static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001581 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001582{
nethercote71980f02004-01-24 18:18:54 +00001583 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001584
sewardj8b635a42004-11-22 19:01:47 +00001585 LibVEX_default_VexControl(& VG_(clo_vex_control));
1586
nethercote71980f02004-01-24 18:18:54 +00001587 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001588 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001589
nethercotef6a1d502004-08-09 12:21:57 +00001590 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001591 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001592 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001593
nethercotef6a1d502004-08-09 12:21:57 +00001594 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1595 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001596 *need_help = 1;
1597
nethercotef6a1d502004-08-09 12:21:57 +00001598 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001599 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001600
nethercotef6c99d72004-11-09 14:35:43 +00001601 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001602 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001603
nethercotef6a1d502004-08-09 12:21:57 +00001604 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1605 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001606 }
1607 }
nethercote71980f02004-01-24 18:18:54 +00001608}
1609
nethercote5ee67ca2004-06-22 14:00:09 +00001610static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001611{
nethercotef8548672004-06-21 12:42:35 +00001612 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001613 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001614
nethercotee1730692003-11-20 10:38:07 +00001615 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001616 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001617
sewardj19d81412002-06-03 01:10:40 +00001618 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001619 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001620 config_error("Please use absolute paths in "
1621 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001622
njnc6168192004-11-29 13:54:10 +00001623// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001624#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001625 {
sewardjb5f6f512005-03-10 23:59:00 +00001626 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001627 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1628 switch(auxp[0]) {
1629 case AT_SYSINFO:
1630 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1631 break;
1632 }
1633 }
1634 }
1635#endif
sewardjde4a1d02002-03-22 01:27:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001640 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001641
thughes3bfd5a02004-07-18 08:05:44 +00001642 /* Look for a colon in the switch name */
1643 while (*colon && *colon != ':' && *colon != '=')
1644 colon++;
nethercote71980f02004-01-24 18:18:54 +00001645
1646 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001647 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001648 if (VG_CLO_STREQN(2, arg, "--") &&
1649 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1650 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1651 {
1652 // prefix matches, convert "--toolname:foo" to "--foo"
1653 if (0)
1654 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001655 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001656 arg[0] = '-';
1657 arg[1] = '-';
1658
1659 } else {
1660 // prefix doesn't match, skip to next arg
1661 continue;
1662 }
1663 }
1664
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001666 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1667 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1668 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001669
njn45270a22005-03-27 01:00:11 +00001670 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001671
nethercote71980f02004-01-24 18:18:54 +00001672 else if (VG_CLO_STREQ(arg, "-v") ||
1673 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001674 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001675
nethercote71980f02004-01-24 18:18:54 +00001676 else if (VG_CLO_STREQ(arg, "-q") ||
1677 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001678 VG_(clo_verbosity)--;
1679
sewardj1cf558c2005-04-25 01:36:56 +00001680 else if (VG_CLO_STREQ(arg, "-d")) {
1681 /* do nothing */
1682 }
1683
njn45270a22005-03-27 01:00:11 +00001684 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1685 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1686 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1687 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1688 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1689 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1690 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001691 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001692 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1693 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1694 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1695 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1696 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1697 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1698 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1699 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1700 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001701 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001702 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1703 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1704 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1705 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1706 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001707
njn45270a22005-03-27 01:00:11 +00001708 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1709 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001710
njn45270a22005-03-27 01:00:11 +00001711 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1712 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1713 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1714 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1715 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001716
njn45270a22005-03-27 01:00:11 +00001717 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001718 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001719 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001720 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001721 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001722 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001723 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001724 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001725 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001726 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001727 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001728 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1729
nethercotef8548672004-06-21 12:42:35 +00001730 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1731 VG_(clo_log_to) = VgLogTo_Fd;
1732 VG_(clo_log_name) = NULL;
1733 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001734 }
1735
nethercotef8548672004-06-21 12:42:35 +00001736 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1737 VG_(clo_log_to) = VgLogTo_File;
1738 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001739 }
njnd6bc3c32005-03-27 00:44:31 +00001740
sewardj603d4102005-01-11 14:01:02 +00001741 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1742 VG_(clo_log_to) = VgLogTo_FileExactly;
1743 VG_(clo_log_name) = &arg[19];
1744 }
sewardjde4a1d02002-03-22 01:27:54 +00001745
nethercotef8548672004-06-21 12:42:35 +00001746 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1747 VG_(clo_log_to) = VgLogTo_Socket;
1748 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001749 }
1750
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001752 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001753 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001754 VG_(message)(Vg_UserMsg,
1755 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001756 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001757 }
nethercote71980f02004-01-24 18:18:54 +00001758 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001759 VG_(clo_n_suppressions)++;
1760 }
sewardjde4a1d02002-03-22 01:27:54 +00001761
sewardjfa8ec112005-01-19 11:55:34 +00001762 /* "stuvwxyz" --> stuvwxyz (binary) */
1763 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1764 Int j;
1765 char* opt = & arg[14];
1766
1767 if (8 != VG_(strlen)(opt)) {
1768 VG_(message)(Vg_UserMsg,
1769 "--trace-flags argument must have 8 digits");
1770 VG_(bad_option)(arg);
1771 }
1772 for (j = 0; j < 8; j++) {
1773 if ('0' == opt[j]) { /* do nothing */ }
1774 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1775 else {
1776 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1777 "contain 0s and 1s");
1778 VG_(bad_option)(arg);
1779 }
1780 }
1781 }
1782
1783 /* "stuvwxyz" --> stuvwxyz (binary) */
1784 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001785 Int j;
nethercote71980f02004-01-24 18:18:54 +00001786 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001787
sewardj2a99cf62004-11-24 10:44:19 +00001788 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001789 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001790 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001791 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001792 }
sewardj8b635a42004-11-22 19:01:47 +00001793 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001794 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001795 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001796 else {
sewardjfa8ec112005-01-19 11:55:34 +00001797 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001798 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001799 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001800 }
1801 }
1802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
njn45270a22005-03-27 01:00:11 +00001804 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001805
sewardjd153fae2005-01-10 17:24:47 +00001806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1807 VG_(clo_gen_suppressions) = 0;
1808 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1809 VG_(clo_gen_suppressions) = 1;
1810 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1811 VG_(clo_gen_suppressions) = 2;
1812
nethercote71980f02004-01-24 18:18:54 +00001813 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001814 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
njn8c0b3bb2005-03-12 21:20:39 +00001817 skip_arg:
1818 if (arg != vg_argv[i])
1819 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
1821
sewardj998d40d2004-12-06 14:24:52 +00001822 /* Make VEX control parameters sane */
1823
1824 if (VG_(clo_vex_control).guest_chase_thresh
1825 >= VG_(clo_vex_control).guest_max_insns)
1826 VG_(clo_vex_control).guest_chase_thresh
1827 = VG_(clo_vex_control).guest_max_insns - 1;
1828
1829 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1830 VG_(clo_vex_control).guest_chase_thresh = 0;
1831
1832 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001833
njnf9ebf672003-05-12 21:41:30 +00001834 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001835 VG_(clo_verbosity) = 0;
1836
nethercote04d0fbc2004-01-26 16:48:06 +00001837 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001838 VG_(message)(Vg_UserMsg, "");
1839 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001840 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(message)(Vg_UserMsg,
1842 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001843 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001844 }
1845
nethercotef8548672004-06-21 12:42:35 +00001846 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001847 should be connected to whatever sink has been selected, and we
1848 indiscriminately chuck stuff into it without worrying what the
1849 nature of it is. Oh the wonder of Unix streams. */
1850
nethercotee1730692003-11-20 10:38:07 +00001851 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001852 the terminal any problems to do with processing command line
1853 opts. */
nethercotef8548672004-06-21 12:42:35 +00001854 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001855 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001856
1857 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001858
sewardj4cf05692002-10-27 20:28:29 +00001859 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(VG_(clo_log_name) == NULL);
1861 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001862 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001863
sewardj4cf05692002-10-27 20:28:29 +00001864 case VgLogTo_File: {
1865 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001866 Int seq = 0;
1867 Int pid = VG_(getpid)();
1868
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_name) != NULL);
1870 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001871
nethercote71980f02004-01-24 18:18:54 +00001872 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001873 if (seq == 0)
1874 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001875 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001876 else
1877 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001878 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001879 seq++;
1880
nethercotef8548672004-06-21 12:42:35 +00001881 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001882 = VG_(open)(logfilename,
1883 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1884 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001885 if (eventually_log_fd >= 0) {
1886 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001887 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001888 } else {
nethercotef8548672004-06-21 12:42:35 +00001889 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001890 VG_(message)(Vg_UserMsg,
1891 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001892 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001893 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001894 "--log-file=<file> (didn't work out for some reason.)");
1895 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001896 }
1897 }
1898 }
sewardj603d4102005-01-11 14:01:02 +00001899 break; /* switch (VG_(clo_log_to)) */
1900 }
1901
1902 case VgLogTo_FileExactly: {
1903 Char logfilename[1000];
1904
1905 vg_assert(VG_(clo_log_name) != NULL);
1906 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1907 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1908
1909 eventually_log_fd
1910 = VG_(open)(logfilename,
1911 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1912 VKI_S_IRUSR|VKI_S_IWUSR);
1913 if (eventually_log_fd >= 0) {
1914 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1915 }
1916 else if (eventually_log_fd != -VKI_EEXIST) {
1917 VG_(message)(Vg_UserMsg,
1918 "Can't create/open log file `%s'; giving up!",
1919 VG_(clo_log_name));
1920 VG_(bad_option)(
1921 "--log-file-exactly=<file> (didn't work out for some reason.)");
1922 /*NOTREACHED*/
1923 }
1924 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001925 }
1926
1927 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001928 vg_assert(VG_(clo_log_name) != NULL);
1929 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1930 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1931 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001932 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001933 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001935 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001937 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001938 }
nethercotef8548672004-06-21 12:42:35 +00001939 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001940 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001941 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001942 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001943 VG_(message)(Vg_UserMsg,
1944 "Log messages will sent to stderr instead." );
1945 VG_(message)(Vg_UserMsg,
1946 "" );
1947 /* We don't change anything here. */
1948 } else {
nethercotef8548672004-06-21 12:42:35 +00001949 vg_assert(eventually_log_fd > 0);
1950 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001951 VG_(logging_to_filedes) = False;
1952 }
sewardj73cf3bc2002-11-03 03:20:15 +00001953 break;
1954 }
1955
sewardj4cf05692002-10-27 20:28:29 +00001956 }
1957
nethercotef8548672004-06-21 12:42:35 +00001958 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001959 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001960 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001961 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1962 else {
nethercotef8548672004-06-21 12:42:35 +00001963 VG_(clo_log_fd) = eventually_log_fd;
1964 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001965 }
1966
sewardj4cf05692002-10-27 20:28:29 +00001967 /* Ok, the logging sink is running now. Print a suitable preamble.
1968 If logging to file or a socket, write details of parent PID and
1969 command line args, to help people trying to interpret the
1970 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001971
sewardj83adf412002-05-01 01:25:45 +00001972 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001973 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001974 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001975 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001976 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001977 NULL == VG_(details).version
1978 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001979 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001980 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001981
njnd04b7c62002-10-03 14:05:52 +00001982 /* Core details */
1983 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001984 "Using LibVEX rev %s, a library for dynamic binary translation.",
1985 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001986 VG_(message)(Vg_UserMsg,
1987 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1988 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001989 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001990 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001992 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001993 }
1994
nethercotec1e395d2003-11-10 13:26:49 +00001995 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001996 VG_(message)(Vg_UserMsg, "");
1997 VG_(message)(Vg_UserMsg,
1998 "My PID = %d, parent PID = %d. Prog and args are:",
1999 VG_(getpid)(), VG_(getppid)() );
2000 for (i = 0; i < VG_(client_argc); i++)
2001 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2002 }
2003
sewardjde4a1d02002-03-22 01:27:54 +00002004 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002005 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002006 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002007 VG_(message)(Vg_DebugMsg, "");
2008 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2009 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002010 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002012
njn1fd5eb22005-03-13 05:43:23 +00002013 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002014 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002015 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
nethercotea70f7352004-04-18 12:08:46 +00002017
njn1fd5eb22005-03-13 05:43:23 +00002018 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002019 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2020 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002021 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002022 } else {
2023 #define BUF_LEN 256
2024 Char version_buf[BUF_LEN];
2025 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2026 vg_assert(n <= 256);
2027 if (n > 0) {
2028 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002029 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002030 } else {
njn1fd5eb22005-03-13 05:43:23 +00002031 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002032 }
2033 VG_(close)(fd);
2034 #undef BUF_LEN
2035 }
sewardjde4a1d02002-03-22 01:27:54 +00002036 }
2037
fitzhardinge98abfc72003-12-16 02:05:15 +00002038 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002039 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002040 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002041 needs one, load the default */
2042 static const Char default_supp[] = "default.supp";
2043 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2044 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2045 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2046 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2047 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002048 }
sewardj4cf05692002-10-27 20:28:29 +00002049
sewardjd153fae2005-01-10 17:24:47 +00002050 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002051 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002052 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002053 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002054 VG_(message)(Vg_UserMsg,
2055 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002056 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002057 }
sewardjde4a1d02002-03-22 01:27:54 +00002058}
2059
nethercotef6a1d502004-08-09 12:21:57 +00002060// Build the string for VALGRINDCLO.
2061Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2062{
2063 /* If we're tracing the children, then we need to start it
2064 with our starter+arguments, which are copied into VALGRINDCLO,
2065 except the --exec= option is changed if present.
2066 */
2067 Int i;
2068 Char *exec;
2069 Char *cp;
2070 Char *optvar;
2071 Int optlen, execlen;
2072
2073 // All these allocated blocks are not free - because we're either
2074 // going to exec, or panic when we fail.
2075
2076 // Create --exec= option: "--exec=<exename>"
2077 exec = VG_(arena_malloc)(VG_AR_CORE,
2078 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2079 vg_assert(NULL != exec);
2080 VG_(sprintf)(exec, "--exec=%s", exename);
2081
2082 // Allocate space for optvar (may overestimate by counting --exec twice,
2083 // no matter)
2084 optlen = 1;
2085 for (i = 0; i < vg_argc; i++)
2086 optlen += VG_(strlen)(vg_argv[i]) + 1;
2087 optlen += VG_(strlen)(exec)+1;
2088 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2089
2090 // Copy all valgrind args except the old --exec (if present)
2091 // VG_CLO_SEP is the separator.
2092 cp = optvar;
2093 for (i = 1; i < vg_argc; i++) {
2094 Char *arg = vg_argv[i];
2095
2096 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2097 // don't copy existing --exec= arg
2098 } else if (VG_(strcmp)(arg, "--") == 0) {
2099 // stop at "--"
2100 break;
2101 } else {
2102 // copy non "--exec" arg
2103 Int len = VG_(strlen)(arg);
2104 VG_(memcpy)(cp, arg, len);
2105 cp += len;
2106 *cp++ = VG_CLO_SEP;
2107 }
2108 }
2109 // Add the new --exec= option
2110 execlen = VG_(strlen)(exec);
2111 VG_(memcpy)(cp, exec, execlen);
2112 cp += execlen;
2113 *cp++ = VG_CLO_SEP;
2114
2115 *cp = '\0';
2116
2117 return optvar;
2118}
2119
2120// Build "/proc/self/fd/<execfd>".
2121Char* VG_(build_child_exename)( void )
2122{
2123 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2124 vg_assert(NULL != exename);
2125 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2126 return exename;
2127}
2128
sewardjde4a1d02002-03-22 01:27:54 +00002129
nethercote71980f02004-01-24 18:18:54 +00002130/*====================================================================*/
2131/*=== File descriptor setup ===*/
2132/*====================================================================*/
2133
2134static void setup_file_descriptors(void)
2135{
2136 struct vki_rlimit rl;
2137
2138 /* Get the current file descriptor limits. */
2139 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2140 rl.rlim_cur = 1024;
2141 rl.rlim_max = 1024;
2142 }
2143
2144 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002145 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2146 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002147 } else {
2148 rl.rlim_cur = rl.rlim_max;
2149 }
2150
2151 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002152 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2153 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002154
2155 /* Update the soft limit. */
2156 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2157
nethercotef6a1d502004-08-09 12:21:57 +00002158 if (vgexecfd != -1)
2159 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002160 if (VG_(clexecfd) != -1)
2161 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2162}
2163
nethercote71980f02004-01-24 18:18:54 +00002164/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002165/*=== Initialise program data/text, etc. ===*/
2166/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002167
sewardjb5f6f512005-03-10 23:59:00 +00002168static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2169 UInt dev, UInt ino, ULong foffset,
2170 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002171{
nethercote71980f02004-01-24 18:18:54 +00002172 /* Only record valgrind mappings for now, without loading any
2173 symbols. This is so we know where the free space is before we
2174 start allocating more memory (note: heap is OK, it's just mmap
2175 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002176 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002177 VG_(debugLog)(2, "main",
2178 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002179 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002180 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002181 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2182 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002183 /* update VG_(valgrind_last) if it looks wrong */
2184 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002185 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002186 }
sewardjde4a1d02002-03-22 01:27:54 +00002187}
2188
nethercote71980f02004-01-24 18:18:54 +00002189// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002190Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002191
sewardjb5f6f512005-03-10 23:59:00 +00002192/*
2193 This second pass adds in client mappings, and loads symbol tables
2194 for all interesting mappings. The trouble is that things can
2195 change as we go, because we're calling the Tool to track memory as
2196 we find it.
2197
2198 So for Valgrind mappings, we don't replace any mappings which
2199 aren't still identical (which will include the .so mappings, so we
2200 will load their symtabs)>
2201 */
2202static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2203 UInt dev, UInt ino, ULong foffset,
2204 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002205{
nethercote71980f02004-01-24 18:18:54 +00002206 UInt flags;
2207 Bool is_stack_segment;
2208 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002209
nethercote71980f02004-01-24 18:18:54 +00002210 is_stack_segment
2211 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002212
sewardj8c615892005-04-25 02:38:28 +00002213 VG_(debugLog)(2, "main",
2214 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002215 (void*)start, (void*)(start+size), prot, is_stack_segment,
2216 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002217
nethercote71980f02004-01-24 18:18:54 +00002218 if (is_stack_segment)
2219 flags = SF_STACK | SF_GROWDOWN;
2220 else
2221 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002222
nethercote71980f02004-01-24 18:18:54 +00002223 if (filename != NULL)
2224 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002225
sewardjb5f6f512005-03-10 23:59:00 +00002226#if 0
2227 // This needs to be fixed properly. jrs 20050307
2228 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2229 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002230
sewardjb5f6f512005-03-10 23:59:00 +00002231 /* We have to be a bit careful about inserting new mappings into
2232 the Valgrind part of the address space. We're actively
2233 changing things as we parse these mappings, particularly in
2234 shadow memory, and so we don't want to overwrite those
2235 changes. Therefore, we only insert/update a mapping if it is
2236 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002237
sewardjb5f6f512005-03-10 23:59:00 +00002238 NOTE: we're only talking about the Segment list mapping
2239 metadata; this doesn't actually mmap anything more. */
2240 if (filename || (s && s->addr == start && s->len == size)) {
2241 flags |= SF_VALGRIND;
2242 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2243 } else {
2244 /* assert range is already mapped */
2245 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2246 }
2247 } else
2248#endif
2249 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2250
2251 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2252 VG_TRACK( new_mem_startup, start, size,
2253 !!(prot & VKI_PROT_READ),
2254 !!(prot & VKI_PROT_WRITE),
2255 !!(prot & VKI_PROT_EXEC));
2256 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002257
nethercote71980f02004-01-24 18:18:54 +00002258 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002259 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002260 vg_assert(0 != r_esp);
2261 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002262 if (0) {
2263 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002264 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002265 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2266 r_esp, start+size);
2267 }
nethercote71980f02004-01-24 18:18:54 +00002268 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002269 // what's this for?
2270 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002271 }
sewardjde4a1d02002-03-22 01:27:54 +00002272}
2273
2274
nethercote71980f02004-01-24 18:18:54 +00002275/*====================================================================*/
2276/*=== Sanity check machinery (permanently engaged) ===*/
2277/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002278
2279/* A fast sanity check -- suitable for calling circa once per
2280 millisecond. */
2281
nethercote885dd912004-08-03 23:14:00 +00002282void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002283{
sewardjb5f6f512005-03-10 23:59:00 +00002284 ThreadId tid;
2285
njn37cea302002-09-30 11:24:00 +00002286 VGP_PUSHCC(VgpCoreCheapSanity);
2287
nethercote27fec902004-06-16 21:26:32 +00002288 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002289
2290 /* --- First do all the tests that we can do quickly. ---*/
2291
nethercote297effd2004-08-02 15:07:57 +00002292 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002293
njn25e49d8e72002-09-23 09:36:25 +00002294 /* Check stuff pertaining to the memory check system. */
2295
2296 /* Check that nobody has spuriously claimed that the first or
2297 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002298 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002299 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002300 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002301 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002302 }
njn25e49d8e72002-09-23 09:36:25 +00002303
2304 /* --- Now some more expensive checks. ---*/
2305
2306 /* Once every 25 times, check some more expensive stuff. */
2307 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002308 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002309 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002310
njn37cea302002-09-30 11:24:00 +00002311 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002312 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002313
2314# if 0
2315 { void zzzmemscan(void); zzzmemscan(); }
2316# endif
2317
nethercote297effd2004-08-02 15:07:57 +00002318 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002319 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002320
2321 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002322 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002323 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002324 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002325 }
sewardjb5f6f512005-03-10 23:59:00 +00002326
2327 /* Check that Segments and /proc/self/maps match up */
2328 //vg_assert(VG_(sanity_check_memory)());
2329
2330 /* Look for stack overruns. Visit all threads. */
2331 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002332 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002333
2334 if (VG_(threads)[tid].status == VgTs_Empty ||
2335 VG_(threads)[tid].status == VgTs_Zombie)
2336 continue;
2337
2338 remains = VGA_(stack_unused)(tid);
2339 if (remains < VKI_PAGE_SIZE)
2340 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2341 tid, remains);
2342 }
2343
njn25e49d8e72002-09-23 09:36:25 +00002344 /*
nethercote297effd2004-08-02 15:07:57 +00002345 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002346 */
njn37cea302002-09-30 11:24:00 +00002347 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002348 }
2349
nethercote27fec902004-06-16 21:26:32 +00002350 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002351 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002352 /* Check sanity of the low-level memory manager. Note that bugs
2353 in the client's code can cause this to fail, so we don't do
2354 this check unless specially asked for. And because it's
2355 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002356 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002357 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002358 }
njn37cea302002-09-30 11:24:00 +00002359 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002360}
nethercote71980f02004-01-24 18:18:54 +00002361
2362
2363/*====================================================================*/
2364/*=== main() ===*/
2365/*====================================================================*/
2366
nethercotec314eba2004-07-15 12:59:41 +00002367/*
2368 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002369 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002370 loads the client executable (and the dynamic linker, if necessary)
2371 into the client part, and calls into Valgrind proper.
2372
2373 The code is careful not to allow spurious mappings to appear in the
2374 wrong parts of the address space. In particular, to make sure
2375 dlopen puts things in the right place, it will pad out the forbidden
2376 chunks of address space so that dlopen is forced to put things where
2377 we want them.
2378
2379 The memory map it creates is:
2380
njn80950732005-03-26 00:18:45 +00002381 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002382 | client address space |
2383 : :
2384 : :
2385 | client stack |
2386 client_end +-------------------------+
2387 | redzone |
2388 shadow_base +-------------------------+
2389 | |
nethercote996901a2004-08-03 13:29:09 +00002390 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002391 | (may be 0 sized) |
2392 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002393 valgrind_base +-------------------------+
2394 | kickstart executable |
2395 | valgrind heap vvvvvvvvv| (barely used)
2396 - -
2397 | valgrind .so files |
2398 | and mappings |
2399 - -
2400 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002401 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002402 : kernel :
2403
2404 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2405 VG_(mmap)(), we need to build the segment skip-list, so we know where
2406 we can put things. However, building that structure requires
2407 allocating memory. So we need to a bootstrapping process. It's done
2408 by making VG_(arena_malloc)() have a special static superblock that's
2409 used for the first 1MB's worth of allocations. This is enough to
2410 build the segment skip-list.
2411*/
2412
thughes4ad52d02004-06-27 17:37:21 +00002413
sewardj1cf558c2005-04-25 01:36:56 +00002414/* This may be needed before m_mylibc is OK to run. */
2415static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2416{
2417 while (True) {
2418 if (*s1 == 0 && *s2 == 0) return 0;
2419 if (*s1 == 0) return -1;
2420 if (*s2 == 0) return 1;
2421
2422 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2423 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2424
2425 s1++; s2++;
2426 }
2427}
2428
2429
sewardjb5f6f512005-03-10 23:59:00 +00002430int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002431{
2432 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002433 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002434 const char *exec = NULL;
2435 char *preload; /* tool-specific LD_PRELOAD .so */
2436 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002437 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002438 struct exeinfo info;
2439 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002440 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002441 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002442 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002443 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002444 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002445
2446 //============================================================
2447 // Nb: startup is complex. Prerequisites are shown at every step.
2448 //
2449 // *** Be very careful when messing with the order ***
2450 //============================================================
2451
sewardj1cf558c2005-04-25 01:36:56 +00002452 //--------------------------------------------------------------
2453 // Start up the logging mechanism
2454 // p: none
2455 //--------------------------------------------------------------
2456 /* Start the debugging-log system ASAP. First find out how many
2457 "-d"s were specified. This is a pre-scan of the command line. */
2458 loglevel = 0;
2459 for (i = 1; i < argc; i++) {
2460 if (argv[i][0] != '-')
2461 break;
2462 if (0 == local_strcmp(argv[i], "--"))
2463 break;
2464 if (0 == local_strcmp(argv[i], "-d"))
2465 loglevel++;
2466 }
2467
2468 /* ... and start the debug logger. Now we can safely emit logging
2469 messages all through startup. */
2470 VG_(debugLog_startup)(loglevel, "Stage 2");
2471
nethercotef4928da2004-06-15 10:54:40 +00002472 //============================================================
2473 // Command line argument handling order:
2474 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002475 // (including the tool-specific usage)
2476 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002477 // * Then, if client is missing, abort with error msg
2478 // * Then, if any cmdline args are bad, abort with error msg
2479 //============================================================
2480
fitzhardingeb50068f2004-02-24 23:42:55 +00002481 // Get the current process datasize rlimit, and set it to zero.
2482 // This prevents any internal uses of brk() from having any effect.
2483 // We remember the old value so we can restore it on exec, so that
2484 // child processes will have a reasonable brk value.
2485 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2486 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2487 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002488
2489 // Get the current process stack rlimit.
2490 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2491
nethercote71980f02004-01-24 18:18:54 +00002492 //--------------------------------------------------------------
2493 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002494 // p: none
nethercote71980f02004-01-24 18:18:54 +00002495 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002496 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002497 {
sewardj1fbc1a52005-04-25 02:05:54 +00002498 void* init_sp = argv - 1;
2499 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002500 }
2501
2502 //--------------------------------------------------------------
2503 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002504 // p: none
nethercote71980f02004-01-24 18:18:54 +00002505 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002506 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002507 if (cp != NULL)
2508 VG_(libdir) = cp;
2509 }
2510
2511 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002512 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2513 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002514 // p: none
nethercote71980f02004-01-24 18:18:54 +00002515 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002516 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002517 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002518 pre_process_cmd_line_options(&need_help, &tool, &exec);
2519
2520 //==============================================================
2521 // Nb: once a tool is specified, the tool.so must be loaded even if
2522 // they specified --help or didn't specify a client program.
2523 //==============================================================
2524
2525 //--------------------------------------------------------------
2526 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002527 // p: set-libdir [for VG_(libdir)]
2528 // p: pre_process_cmd_line_options() [for 'tool']
2529 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002530 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002531 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002532
2533 //==============================================================
2534 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002535 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002536 //==============================================================
2537
2538 //--------------------------------------------------------------
2539 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002540 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002541 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002542 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002543 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002544
2545 //--------------------------------------------------------------
2546 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002547 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2548 // p: layout_remaining_space [so there's space]
2549 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002550 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002551 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002552
2553 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002554 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002555 // p: layout_remaining_space() [everything must be mapped in before now]
2556 // p: load_client() [ditto]
2557 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002558 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2559 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002560
2561 //--------------------------------------------------------------
2562 // Set up client's environment
2563 // p: set-libdir [for VG_(libdir)]
2564 // p: load_tool() [for 'preload']
2565 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002566 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002567 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002568
2569 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002570 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002571 // p: load_client() [for 'info']
2572 // p: fix_environment() [for 'env']
2573 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002574 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002575 {
sewardj1fbc1a52005-04-25 02:05:54 +00002576 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002577
sewardj1fbc1a52005-04-25 02:05:54 +00002578 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2579 &client_auxv);
2580 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002581 }
nethercote71980f02004-01-24 18:18:54 +00002582
sewardj1fbc1a52005-04-25 02:05:54 +00002583 VG_(debugLog)(2, "main",
2584 "Client info: "
2585 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2586 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2587 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002588
2589 //==============================================================
2590 // Finished setting up operating environment. Now initialise
2591 // Valgrind. (This is where the old VG_(main)() started.)
2592 //==============================================================
2593
2594 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002595 // setup file descriptors
2596 // p: n/a
2597 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002598 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002599 setup_file_descriptors();
2600
2601 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002602 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002603 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002604 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002605 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002606 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2607
2608 //==============================================================
2609 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2610 //==============================================================
2611
2612 //--------------------------------------------------------------
2613 // Init tool: pre_clo_init, process cmd line, post_clo_init
2614 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002615 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002616 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2617 // p: parse_procselfmaps [so VG segments are setup so tool can
2618 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002619 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002620 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002621 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002622 VG_(sanity_check_needs)();
2623
nethercotef4928da2004-06-15 10:54:40 +00002624 // If --tool and --help/--help-debug was given, now give the core+tool
2625 // help message
nethercotef4928da2004-06-15 10:54:40 +00002626 if (need_help) {
2627 usage(/*--help-debug?*/2 == need_help);
2628 }
nethercotec314eba2004-07-15 12:59:41 +00002629 process_cmd_line_options(client_auxv, tool);
2630
njn26f02512004-11-22 18:33:15 +00002631 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002632
2633 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002634 // Determine CPU architecture and subarchitecture
2635 // p: none
2636 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002637 VG_(debugLog)(1, "main", "Check CPU arch/subarch\n");
sewardj51ac0872004-12-21 01:20:49 +00002638 { Bool ok = VGA_(getArchAndSubArch)(
2639 & VG_(vex_arch), & VG_(vex_subarch) );
2640 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002641 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002642 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002643 VG_(printf)(" Supported CPUs are:\n");
2644 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2645 "AMD Athlon or above)\n");
2646 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002647 VG_(exit)(1);
2648 }
2649 if (VG_(clo_verbosity) > 2) {
2650 VG_(message)(Vg_DebugMsg,
2651 "Host CPU: arch = %s, subarch = %s",
2652 LibVEX_ppVexArch( VG_(vex_arch) ),
2653 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2654 }
2655 }
2656
2657 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002658 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002659 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002660 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002661 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002662 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002663 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002664 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002665 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002666 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002667
sewardj21c6d0f2005-05-02 10:33:44 +00002668#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002669 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002670 // Protect client trampoline page (which is also sysinfo stuff)
2671 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002672 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002673 {
2674 Segment *seg;
2675 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2676 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002677
sewardjb5f6f512005-03-10 23:59:00 +00002678 /* Make sure this segment isn't treated as stack */
2679 seg = VG_(find_segment)(VG_(client_trampoline_code));
2680 if (seg)
2681 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2682 }
sewardj21c6d0f2005-05-02 10:33:44 +00002683#endif
sewardjb5f6f512005-03-10 23:59:00 +00002684
nethercotec314eba2004-07-15 12:59:41 +00002685 //==============================================================
2686 // Can use VG_(map)() after segments set up
2687 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002688
2689 //--------------------------------------------------------------
2690 // Allow GDB attach
2691 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2692 //--------------------------------------------------------------
2693 /* Hook to delay things long enough so we can get the pid and
2694 attach GDB in another shell. */
2695 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002696 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002697 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2698 /* jrs 20050206: I don't understand why this works on x86. On
2699 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2700 work. */
2701 /* do "jump *$eip" to skip this in gdb (x86) */
2702 //VG_(do_syscall0)(__NR_pause);
2703 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002704 }
2705
sewardjb5d320c2005-03-13 18:57:15 +00002706 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002707 // Search for file descriptors that are inherited from our parent
2708 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2709 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002710 if (VG_(clo_track_fds)) {
2711 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002712 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002713 }
nethercote71980f02004-01-24 18:18:54 +00002714
2715 //--------------------------------------------------------------
2716 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002717 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2718 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002719 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002720 VG_(scheduler_init)();
2721
2722 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002723 // Initialise the pthread model
2724 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002725 // load_client() [for 'client_eip']
2726 // setup_client_stack() [for 'sp_at_startup']
2727 // setup_scheduler() [for the rest of state 1 stuff]
2728 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002729 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002730 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002731
2732 // Tell the tool that we just wrote to the registers.
2733 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2734 sizeof(VexGuestArchState));
2735
sewardj2a99cf62004-11-24 10:44:19 +00002736 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002737 // Initialise the pthread model
2738 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002739 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002740 //if (VG_(clo_model_pthreads))
2741 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002742
2743 //--------------------------------------------------------------
2744 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002745 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002746 //--------------------------------------------------------------
2747 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002748 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002749 VG_(sigstartup_actions)();
2750
2751 //--------------------------------------------------------------
2752 // Perhaps we're profiling Valgrind?
2753 // p: process_cmd_line_options() [for VG_(clo_profile)]
2754 // p: others?
2755 //
2756 // XXX: this seems to be broken? It always says the tool wasn't built
2757 // for profiling; vg_profile.c's functions don't seem to be overriding
2758 // vg_dummy_profile.c's?
2759 //
2760 // XXX: want this as early as possible. Looking for --profile
2761 // in pre_process_cmd_line_options() could get it earlier.
2762 //--------------------------------------------------------------
2763 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002764 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002765
2766 VGP_PUSHCC(VgpStartup);
2767
2768 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002769 // Read suppression file
2770 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2771 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002772 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2773 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002774 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002775 }
nethercote71980f02004-01-24 18:18:54 +00002776
2777 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002778 // Initialise translation table and translation cache
2779 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2780 // aren't identified as part of the client, which would waste
2781 // > 20M of virtual address space.]
2782 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002783 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002784 VG_(init_tt_tc)();
2785
2786 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002787 // Read debug info to find glibc entry points to intercept
2788 // p: parse_procselfmaps? [XXX for debug info?]
2789 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2790 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002791 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002792 VG_(setup_code_redirect_table)();
tom748a1312005-04-02 15:53:01 +00002793 VGP_(setup_redirects)();
sewardjb5d320c2005-03-13 18:57:15 +00002794
2795 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002796 // Verbosity message
2797 // p: end_rdtsc_calibration [so startup message is printed first]
2798 //--------------------------------------------------------------
2799 if (VG_(clo_verbosity) == 1)
2800 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2801 if (VG_(clo_verbosity) > 0)
2802 VG_(message)(Vg_UserMsg, "");
2803
2804 //--------------------------------------------------------------
2805 // Setup pointercheck
2806 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2807 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002808 if (VG_(clo_pointercheck))
2809 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002810
nethercote71980f02004-01-24 18:18:54 +00002811 //--------------------------------------------------------------
2812 // Run!
2813 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002814 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002815
sewardjb5f6f512005-03-10 23:59:00 +00002816 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002817
sewardj1fbc1a52005-04-25 02:05:54 +00002818 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardjb5f6f512005-03-10 23:59:00 +00002819 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002820
sewardjb5f6f512005-03-10 23:59:00 +00002821 abort();
2822}
2823
2824
2825/* Do everything which needs doing when the last thread exits */
2826void VG_(shutdown_actions)(ThreadId tid)
2827{
2828 vg_assert(tid == VG_(master_tid));
2829 vg_assert(VG_(is_running_thread)(tid));
2830
2831 // Wait for all other threads to exit.
2832 VGA_(reap_threads)(tid);
2833
2834 VG_(clo_model_pthreads) = False;
2835
2836 // Clean the client up before the final report
2837 VGA_(final_tidyup)(tid);
2838
2839 // OK, done
2840 VG_(exit_thread)(tid);
2841
2842 /* should be no threads left */
2843 vg_assert(VG_(count_living_threads)() == 0);
2844
2845 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002846 //--------------------------------------------------------------
2847 // Finalisation: cleanup, messages, etc. Order no so important, only
2848 // affects what order the messages come.
2849 //--------------------------------------------------------------
2850 if (VG_(clo_verbosity) > 0)
2851 VG_(message)(Vg_UserMsg, "");
2852
nethercote71980f02004-01-24 18:18:54 +00002853 /* Print out file descriptor summary and stats. */
2854 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002855 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002856
njn95ec8702004-11-22 16:46:13 +00002857 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002858 VG_(show_all_errors)();
2859
sewardjb5f6f512005-03-10 23:59:00 +00002860 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002861
nethercote885dd912004-08-03 23:14:00 +00002862 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002863
2864 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002865 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002866
nethercote71980f02004-01-24 18:18:54 +00002867 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002868 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002869 if (VG_(clo_profile_flags) > 0)
2870 VG_(show_BB_profile)();
2871
sewardj8b635a42004-11-22 19:01:47 +00002872 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002873 if (0)
2874 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002875
nethercote71980f02004-01-24 18:18:54 +00002876}
2877
sewardjde4a1d02002-03-22 01:27:54 +00002878/*--------------------------------------------------------------------*/
2879/*--- end vg_main.c ---*/
2880/*--------------------------------------------------------------------*/