blob: 20142ede08650474f31d5ac14a812cd90b6590d9 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003/*--- Startup: the real stuff m_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"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn04e16982005-05-31 00:23:43 +000040#include "pub_core_main.h"
njn20242342005-05-16 23:31:24 +000041#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000042#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000043#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000044#include "pub_core_signals.h"
njn2521d322005-05-08 14:45:13 +000045#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000046#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000047#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000048
49#include <dirent.h>
50#include <dlfcn.h>
51#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000052#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000054#include <string.h>
55#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000056#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000057#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000058#include <sys/wait.h>
59#include <unistd.h>
60
sewardjb5f6f512005-03-10 23:59:00 +000061#include "memcheck/memcheck.h"
62
thughes74b8de22004-04-22 18:12:31 +000063#ifndef AT_DCACHEBSIZE
64#define AT_DCACHEBSIZE 19
65#endif /* AT_DCACHEBSIZE */
66
67#ifndef AT_ICACHEBSIZE
68#define AT_ICACHEBSIZE 20
69#endif /* AT_ICACHEBSIZE */
70
71#ifndef AT_UCACHEBSIZE
72#define AT_UCACHEBSIZE 21
73#endif /* AT_UCACHEBSIZE */
74
nethercote71980f02004-01-24 18:18:54 +000075#ifndef AT_SYSINFO
76#define AT_SYSINFO 32
77#endif /* AT_SYSINFO */
78
79#ifndef AT_SYSINFO_EHDR
80#define AT_SYSINFO_EHDR 33
81#endif /* AT_SYSINFO_EHDR */
82
83#ifndef AT_SECURE
84#define AT_SECURE 23 /* secure mode boolean */
85#endif /* AT_SECURE */
86
nethercote71980f02004-01-24 18:18:54 +000087/* redzone gap between client address space and shadow */
88#define REDZONE_SIZE (1 * 1024*1024)
89
90/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000091#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000092
nethercotee2097312004-06-27 12:29:56 +000093/* Proportion of client space for its heap (rest is for mmaps + stack) */
94#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000095
njn14319cc2005-03-13 06:26:22 +000096/* Number of file descriptors that Valgrind tries to reserve for
97 it's own use - just a small constant. */
98#define N_RESERVED_FDS (10)
99
nethercote71980f02004-01-24 18:18:54 +0000100/*====================================================================*/
101/*=== Global entities not referenced from generated code ===*/
102/*====================================================================*/
103
sewardjde4a1d02002-03-22 01:27:54 +0000104/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000105 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000106 ------------------------------------------------------------------ */
107
nethercote73b526f2004-10-31 18:48:21 +0000108struct vki_rlimit VG_(client_rlimit_data);
109struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000110
fitzhardinge98abfc72003-12-16 02:05:15 +0000111/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000112static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000113
114/* client executable */
115Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000116
117/* Path to library directory */
118const Char *VG_(libdir) = VG_LIBDIR;
119
120/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000121static Int vg_argc;
122static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
thughesad1c9562004-06-26 11:27:52 +0000124/* Application-visible file descriptor limits */
125Int VG_(fd_soft_limit) = -1;
126Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000127
nethercote4ad74312004-10-26 09:59:49 +0000128/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000129 envp[] as extracted from the client's stack at startup-time. */
130Int VG_(client_argc);
131Char** VG_(client_argv);
132Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000133
sewardj51ac0872004-12-21 01:20:49 +0000134
sewardjde4a1d02002-03-22 01:27:54 +0000135/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000136 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000137 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000138
sewardjde4a1d02002-03-22 01:27:54 +0000139/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000140ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000141
sewardj73cf3bc2002-11-03 03:20:15 +0000142
nethercote71980f02004-01-24 18:18:54 +0000143/*====================================================================*/
144/*=== Counters, for profiling purposes only ===*/
145/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000146
sewardjde4a1d02002-03-22 01:27:54 +0000147/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000148static UInt sanity_fast_count = 0;
149static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000150
nethercote3a42fb82004-08-03 18:08:50 +0000151static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000152{
nethercote3a42fb82004-08-03 18:08:50 +0000153 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000154 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000155 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000156 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000157
nethercote3a42fb82004-08-03 18:08:50 +0000158 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000159 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161 VG_(message)(Vg_DebugMsg,
162 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000163 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000164
njn9271cbc2005-03-13 05:38:25 +0000165 VG_(print_ExeContext_stats)();
166
nethercote3a42fb82004-08-03 18:08:50 +0000167 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000168 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000169 VG_(message)(Vg_DebugMsg, "");
170 VG_(message)(Vg_DebugMsg,
171 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000172 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000173 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000174 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000175 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000176 }
nethercote71980f02004-01-24 18:18:54 +0000177}
178
179
180/*====================================================================*/
181/*=== Miscellaneous global functions ===*/
182/*====================================================================*/
183
nethercotecf97ffb2004-09-09 13:40:31 +0000184static Int ptrace_setregs(Int pid, ThreadId tid)
185{
sewardj2a99cf62004-11-24 10:44:19 +0000186 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000187}
188
nethercote04d0fbc2004-01-26 16:48:06 +0000189/* Start debugger and get it to attach to this process. Called if the
190 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000191 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000192 meaningfully get the debugger to continue the program, though; to
193 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000194void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000195{
196 Int pid;
197
198 if ((pid = fork()) == 0) {
199 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000200 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000201
202 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000203 Int status;
204 Int res;
205
nethercote71980f02004-01-24 18:18:54 +0000206 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
207 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000208 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000209 kill(pid, SIGSTOP) == 0 &&
210 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000211 Char pidbuf[15];
212 Char file[30];
213 Char buf[100];
214 Char *bufptr;
215 Char *cmdptr;
216
217 VG_(sprintf)(pidbuf, "%d", pid);
218 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
219
220 bufptr = buf;
221 cmdptr = VG_(clo_db_command);
222
223 while (*cmdptr) {
224 switch (*cmdptr) {
225 case '%':
226 switch (*++cmdptr) {
227 case 'f':
228 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
229 bufptr += VG_(strlen)(file);
230 cmdptr++;
231 break;
232 case 'p':
233 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
234 bufptr += VG_(strlen)(pidbuf);
235 cmdptr++;
236 break;
237 default:
238 *bufptr++ = *cmdptr++;
239 break;
240 }
241 break;
242 default:
243 *bufptr++ = *cmdptr++;
244 break;
245 }
246 }
247
248 *bufptr++ = '\0';
249
250 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000251 res = VG_(system)(buf);
252 if (res == 0) {
253 VG_(message)(Vg_UserMsg, "");
254 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000255 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000256 } else {
257 VG_(message)(Vg_UserMsg, "Apparently failed!");
258 VG_(message)(Vg_UserMsg, "");
259 }
260 }
261
nethercote73b526f2004-10-31 18:48:21 +0000262 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000263 VG_(waitpid)(pid, &status, 0);
264 }
265}
266
267
sewardj2a99cf62004-11-24 10:44:19 +0000268/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000269Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000270{
njncf45fd42004-11-24 16:30:22 +0000271 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000272}
273
njn67516132005-03-22 04:02:43 +0000274Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000275{
276 return INSTR_PTR( VG_(threads)[tid].arch );
277}
278
njnea4b28c2004-11-30 16:04:58 +0000279
nethercote71980f02004-01-24 18:18:54 +0000280/*====================================================================*/
281/*=== Check we were launched by stage 1 ===*/
282/*====================================================================*/
283
284/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000285static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000286{
nethercoteebf1d862004-11-01 18:22:05 +0000287 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000288 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000289
290 for (; auxv->a_type != AT_NULL; auxv++)
291 switch(auxv->a_type) {
292 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000293 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000294 found |= 1;
295 break;
296
297 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000298 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000299 found |= 2;
300 break;
nethercote7f390022004-10-25 17:18:24 +0000301
302 case AT_PHDR:
303 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
304 break;
nethercote71980f02004-01-24 18:18:54 +0000305 }
306
nethercote361a14e2004-07-26 11:11:56 +0000307 if ( found != (1|2) ) {
308 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000309 exit(127);
310 }
nethercote31779c72004-07-30 21:50:15 +0000311 vg_assert(padfile >= 0);
312 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000313}
314
315
316/*====================================================================*/
317/*=== Address space determination ===*/
318/*====================================================================*/
319
nethercote7f390022004-10-25 17:18:24 +0000320extern char _start[];
321
nethercote31779c72004-07-30 21:50:15 +0000322static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000323{
nethercotea3c3cf22004-11-01 18:38:00 +0000324 Int ires;
325 void* vres;
326 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000327
nethercote7f390022004-10-25 17:18:24 +0000328 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
329 // this is a workable approximation
330 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000331 VG_(valgrind_base) = PGROUNDDN(&_start);
332 }
333
nethercote820bd8c2004-09-07 23:04:49 +0000334 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000335
nethercote31779c72004-07-30 21:50:15 +0000336 // This gives the client the largest possible address space while
337 // taking into account the tool's shadow needs.
338 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000339 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000340 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000341 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000342 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000343 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000344 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000345
nethercote31779c72004-07-30 21:50:15 +0000346 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000347 VG_(shadow_end) = VG_(valgrind_base);
348 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000349
nethercotee2097312004-06-27 12:29:56 +0000350#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
351
nethercote71980f02004-01-24 18:18:54 +0000352 if (0)
nethercotee2097312004-06-27 12:29:56 +0000353 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000354 "client_base %p (%dMB)\n"
355 "client_mapbase %p (%dMB)\n"
356 "client_end %p (%dMB)\n"
357 "shadow_base %p (%dMB)\n"
358 "shadow_end %p\n"
359 "valgrind_base %p (%dMB)\n"
360 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000361 VG_(client_base), SEGSIZE(client_base, client_mapbase),
362 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
363 VG_(client_end), SEGSIZE(client_end, shadow_base),
364 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000365 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000366 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
367 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000368 );
369
370#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000371
372 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000373 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000374 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000375 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000376
377 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000378 ires = munmap((void*)VG_(client_base), client_size);
379 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000380
381 // Map shadow memory.
382 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000383 if (shadow_size != 0) {
384 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000385 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000386 if ((void*)-1 == vres) {
387 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000388 "valgrind: Could not allocate address space (%p bytes)\n"
389 "valgrind: for shadow memory\n"
390 "valgrind: Possible causes:\n"
391 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
392 "valgrind: needs at least 1.5GB swap space.\n"
393 "valgrind: - Or, your virtual memory size may be limited (check\n"
394 "valgrind: with 'ulimit -v').\n"
395 "valgrind: - Or, your system may use a kernel that provides only a\n"
396 "valgrind: too-small (eg. 2GB) user address space.\n"
397 , (void*)shadow_size
398 );
nethercoted4722622004-08-30 19:36:42 +0000399 exit(1);
400 }
nethercotee567e702004-07-10 17:49:17 +0000401 }
nethercote71980f02004-01-24 18:18:54 +0000402}
403
404/*====================================================================*/
405/*=== Command line setup ===*/
406/*====================================================================*/
407
nethercote71980f02004-01-24 18:18:54 +0000408static char* get_file_clo(char* dir)
409{
410# define FLEN 512
411 Int fd, n;
412 struct stat s1;
413 char* f_clo = NULL;
414 char filename[FLEN];
415
416 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
417 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
418 if ( fd > 0 ) {
419 if ( 0 == fstat(fd, &s1) ) {
420 f_clo = malloc(s1.st_size+1);
421 vg_assert(f_clo);
422 n = read(fd, f_clo, s1.st_size);
423 if (n == -1) n = 0;
424 f_clo[n] = '\0';
425 }
426 close(fd);
427 }
428 return f_clo;
429# undef FLEN
430}
431
432static Int count_args(char* s)
433{
434 Int n = 0;
435 if (s) {
436 char* cp = s;
437 while (True) {
438 // We have alternating sequences: blanks, non-blanks, blanks...
439 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000440 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000441 if ( !*cp ) break;
442 n++;
njn0c0f32a2005-03-26 04:14:01 +0000443 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000444 }
445 }
446 return n;
447}
448
449/* add args out of environment, skipping multiple spaces and -- args */
450static char** copy_args( char* s, char** to )
451{
452 if (s) {
453 char* cp = s;
454 while (True) {
455 // We have alternating sequences: blanks, non-blanks, blanks...
456 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000457 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000458 if ( !*cp ) break;
459 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000460 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000461 if ( *cp ) *cp++ = '\0'; // terminate if necessary
462 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
463 }
464 }
465 return to;
466}
467
468// Augment command line with arguments from environment and .valgrindrc
469// files.
470static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
471{
nethercotef6a1d502004-08-09 12:21:57 +0000472 int vg_argc0 = *vg_argc_inout;
473 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000474
475 char* env_clo = getenv(VALGRINDOPTS);
476 char* f1_clo = get_file_clo( getenv("HOME") );
477 char* f2_clo = get_file_clo(".");
478
479 /* copy any extra args from file or environment, if present */
480 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
481 /* ' ' separated extra options */
482 char **from;
483 char **to;
thughescaca0022004-09-13 10:20:34 +0000484 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
485
486 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
487
nethercote71980f02004-01-24 18:18:54 +0000488 env_arg_count = count_args(env_clo);
489 f1_arg_count = count_args(f1_clo);
490 f2_arg_count = count_args(f2_clo);
491
492 if (0)
493 printf("extra-argc=%d %d %d\n",
494 env_arg_count, f1_arg_count, f2_arg_count);
495
496 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000497 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000498 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000499 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000500 vg_assert(vg_argv0);
501 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000502
503 /* copy argv[0] */
504 *to++ = *from++;
505
506 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
507 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
508 * to override less local ones. */
509 to = copy_args(f1_clo, to);
510 to = copy_args(env_clo, to);
511 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000512
513 // Free memory
514 free(f1_clo);
515 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000516
517 /* copy original arguments, stopping at command or -- */
518 while (*from) {
519 if (**from != '-')
520 break;
521 if (VG_STREQ(*from, "--")) {
522 from++; /* skip -- */
523 break;
524 }
525 *to++ = *from++;
526 }
527
528 /* add -- */
529 *to++ = "--";
530
nethercotef6a1d502004-08-09 12:21:57 +0000531 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000532
533 /* copy rest of original command line, then NULL */
534 while (*from) *to++ = *from++;
535 *to = NULL;
536 }
537
nethercotef6a1d502004-08-09 12:21:57 +0000538 *vg_argc_inout = vg_argc0;
539 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000540}
541
nethercotef6a1d502004-08-09 12:21:57 +0000542#define VG_CLO_SEP '\01'
543
nethercote71980f02004-01-24 18:18:54 +0000544static void get_command_line( int argc, char** argv,
545 Int* vg_argc_out, Char*** vg_argv_out,
546 char*** cl_argv_out )
547{
nethercotef6a1d502004-08-09 12:21:57 +0000548 int vg_argc0;
549 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000550 char** cl_argv;
551 char* env_clo = getenv(VALGRINDCLO);
552
553 if (env_clo != NULL && *env_clo != '\0') {
554 char *cp;
555 char **cpp;
556
nethercotef6a1d502004-08-09 12:21:57 +0000557 /* OK, VALGRINDCLO is set, which means we must be a child of another
558 Valgrind process using --trace-children, so we're getting all our
559 arguments from VALGRINDCLO, and the entire command line belongs to
560 the client (including argv[0]) */
561 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000562 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000563 if (*cp == VG_CLO_SEP)
564 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000565
nethercotef6a1d502004-08-09 12:21:57 +0000566 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
567 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000568
nethercotef6a1d502004-08-09 12:21:57 +0000569 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000570
571 *cpp++ = "valgrind"; /* nominal argv[0] */
572 *cpp++ = env_clo;
573
nethercotef6a1d502004-08-09 12:21:57 +0000574 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000575 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000576 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000577 *cp++ = '\0'; /* chop it up in place */
578 *cpp++ = cp;
579 }
580 }
581 *cpp = NULL;
582 cl_argv = argv;
583
584 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000585 Bool noaugment = False;
586
nethercote71980f02004-01-24 18:18:54 +0000587 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000588 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000589
nethercotef6a1d502004-08-09 12:21:57 +0000590 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000591 Char* arg = argv[vg_argc0];
592 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000593 break;
sewardjb5f6f512005-03-10 23:59:00 +0000594 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000595 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000596 break;
597 }
njn45270a22005-03-27 01:00:11 +0000598 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000599 }
nethercotef6a1d502004-08-09 12:21:57 +0000600 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000601
602 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000603 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000604 those extra args will already be present in VALGRINDCLO.
605 (We also don't do it when --command-line-only=yes.) */
606 if (!noaugment)
607 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000608 }
609
610 if (0) {
611 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000612 for (i = 0; i < vg_argc0; i++)
613 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000614 }
615
nethercotef6a1d502004-08-09 12:21:57 +0000616 *vg_argc_out = vg_argc0;
617 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000618 *cl_argv_out = cl_argv;
619}
620
621
622/*====================================================================*/
623/*=== Environment and stack setup ===*/
624/*====================================================================*/
625
626/* Scan a colon-separated list, and call a function on each element.
627 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000628 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000629 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000630
631 This routine will return True if (*func) returns True and False if
632 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000633*/
thughes4ad52d02004-06-27 17:37:21 +0000634static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000635{
636 char *cp, *entry;
637 int end;
638
639 if (colsep == NULL ||
640 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000641 return False;
nethercote71980f02004-01-24 18:18:54 +0000642
643 entry = cp = colsep;
644
645 do {
646 end = (*cp == '\0');
647
648 if (*cp == ':' || *cp == '\0') {
649 char save = *cp;
650
651 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000652 if ((*func)(entry)) {
653 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000654 return True;
thughes21942d92004-07-12 09:35:37 +0000655 }
nethercote71980f02004-01-24 18:18:54 +0000656 *cp = save;
657 entry = cp+1;
658 }
659 cp++;
660 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000661
662 return False;
663}
664
nethercote71980f02004-01-24 18:18:54 +0000665/* Prepare the client's environment. This is basically a copy of our
666 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000667 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000668
sewardjb5f6f512005-03-10 23:59:00 +0000669 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000670
671 Yummy. String hacking in C.
672
673 If this needs to handle any more variables it should be hacked
674 into something table driven.
675 */
676static char **fix_environment(char **origenv, const char *preload)
677{
678 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000679 static const char ld_preload[] = "LD_PRELOAD=";
680 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000681 static const int ld_preload_len = sizeof(ld_preload)-1;
682 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
683 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000684 char *inject_path;
685 int inject_path_len;
686 int vgliblen = strlen(VG_(libdir));
687 char **cpp;
688 char **ret;
689 int envc;
690 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
691
692 /* Find the vg_inject.so; also make room for the tool preload
693 library */
694 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
695 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000696 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000697
698 if (preload)
699 snprintf(inject_path, inject_path_len, "%s/%s:%s",
700 VG_(libdir), inject_so, preload);
701 else
702 snprintf(inject_path, inject_path_len, "%s/%s",
703 VG_(libdir), inject_so);
704
705 /* Count the original size of the env */
706 envc = 0; /* trailing NULL */
707 for (cpp = origenv; cpp && *cpp; cpp++)
708 envc++;
709
710 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000711 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000712 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000713
714 /* copy it over */
715 for (cpp = ret; *origenv; )
716 *cpp++ = *origenv++;
717 *cpp = NULL;
718
719 vg_assert(envc == (cpp - ret));
720
721 /* Walk over the new environment, mashing as we go */
722 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000723 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000724 int len = strlen(*cpp) + inject_path_len;
725 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000726 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000727
728 snprintf(cp, len, "%s%s:%s",
729 ld_preload, inject_path, (*cpp)+ld_preload_len);
730
731 *cpp = cp;
732
733 ld_preload_done = 1;
734 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
735 *cpp = "";
736 }
737 }
738
739 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000740 if (!ld_preload_done) {
741 int len = ld_preload_len + inject_path_len;
742 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000743 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000744
745 snprintf(cp, len, "%s%s",
746 ld_preload, inject_path);
747
748 ret[envc++] = cp;
749 }
750
sewardjb5f6f512005-03-10 23:59:00 +0000751 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000752 ret[envc] = NULL;
753
754 return ret;
755}
756
757extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000758
759/* Add a string onto the string table, and return its address */
760static char *copy_str(char **tab, const char *str)
761{
762 char *cp = *tab;
763 char *orig = cp;
764
765 while(*str)
766 *cp++ = *str++;
767 *cp++ = '\0';
768
769 if (0)
nethercote545fe672004-11-01 16:52:43 +0000770 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000771
772 *tab = cp;
773
774 return orig;
775}
776
777/*
778 This sets up the client's initial stack, containing the args,
779 environment and aux vector.
780
781 The format of the stack is:
782
783 higher address +-----------------+
784 | Trampoline code |
785 +-----------------+
786 | |
787 : string table :
788 | |
789 +-----------------+
790 | AT_NULL |
791 - -
792 | auxv |
793 +-----------------+
794 | NULL |
795 - -
796 | envp |
797 +-----------------+
798 | NULL |
799 - -
800 | argv |
801 +-----------------+
802 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000803 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000804 | undefined |
805 : :
806 */
nethercotec25c4492004-10-18 11:52:17 +0000807static Addr setup_client_stack(void* init_sp,
808 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000809 const struct exeinfo *info,
810 UInt** client_auxv)
811{
nethercotee567e702004-07-10 17:49:17 +0000812 void* res;
nethercote71980f02004-01-24 18:18:54 +0000813 char **cpp;
814 char *strtab; /* string table */
815 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000816 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000817 struct ume_auxv *auxv;
818 const struct ume_auxv *orig_auxv;
819 const struct ume_auxv *cauxv;
820 unsigned stringsize; /* total size of strings in bytes */
821 unsigned auxsize; /* total size of auxv in bytes */
822 int argc; /* total argc */
823 int envc; /* total number of env vars */
824 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000825 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000826
827 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000828 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000829
830 /* ==================== compute sizes ==================== */
831
832 /* first of all, work out how big the client stack will be */
833 stringsize = 0;
834
835 /* paste on the extra args if the loader needs them (ie, the #!
836 interpreter and its argument) */
837 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000838 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000839 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000840 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000841 }
nethercoted6a56872004-07-26 15:32:47 +0000842 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000843 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000844 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000845 }
846
847 /* now scan the args we're given... */
848 for (cpp = orig_argv; *cpp; cpp++) {
849 argc++;
850 stringsize += strlen(*cpp) + 1;
851 }
852
853 /* ...and the environment */
854 envc = 0;
855 for (cpp = orig_envp; cpp && *cpp; cpp++) {
856 envc++;
857 stringsize += strlen(*cpp) + 1;
858 }
859
860 /* now, how big is the auxv? */
861 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
862 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
863 if (cauxv->a_type == AT_PLATFORM)
864 stringsize += strlen(cauxv->u.a_ptr) + 1;
865 auxsize += sizeof(*cauxv);
866 }
867
868 /* OK, now we know how big the client stack is */
869 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000870 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000871 sizeof(char **)*argc + /* argv */
872 sizeof(char **) + /* terminal NULL */
873 sizeof(char **)*envc + /* envp */
874 sizeof(char **) + /* terminal NULL */
875 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000876 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000877 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000878
sewardj79048ce2005-02-18 08:28:32 +0000879 if (0) VG_(printf)("stacksize = %d\n", stacksize);
880
nethercotef84f6952004-07-15 14:58:33 +0000881 // decide where stack goes!
882 VG_(clstk_end) = VG_(client_end);
883
nethercote73b526f2004-10-31 18:48:21 +0000884 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000885
nethercote71980f02004-01-24 18:18:54 +0000886 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000887 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000888 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
889
nethercote71980f02004-01-24 18:18:54 +0000890 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000891 stringbase = strtab = (char *)(VG_(client_trampoline_code)
892 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000893
894 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000895
sewardj79048ce2005-02-18 08:28:32 +0000896 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000897 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000898 "clstk_base %p\n"
899 "clstk_end %p\n",
900 stringsize, auxsize, stacksize,
901 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000902
nethercote71980f02004-01-24 18:18:54 +0000903 /* ==================== allocate space ==================== */
904
905 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000906 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000907 PROT_READ | PROT_WRITE | PROT_EXEC,
908 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
909 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000910
911 /* ==================== copy client stack ==================== */
912
nethercotea3c3cf22004-11-01 18:38:00 +0000913 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000914
915 /* --- argc --- */
916 *ptr++ = argc; /* client argc */
917
918 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000919 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000920 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000921 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000922 }
nethercoted6a56872004-07-26 15:32:47 +0000923 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000924 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000925 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000926 }
927 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000928 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000929 }
930 *ptr++ = 0;
931
932 /* --- envp --- */
933 VG_(client_envp) = (Char **)ptr;
934 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000935 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000936 *ptr++ = 0;
937
938 /* --- auxv --- */
939 auxv = (struct ume_auxv *)ptr;
940 *client_auxv = (UInt *)auxv;
941
942 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
943 /* copy the entry... */
944 *auxv = *orig_auxv;
945
946 /* ...and fix up the copy */
947 switch(auxv->a_type) {
948 case AT_PHDR:
949 if (info->phdr == 0)
950 auxv->a_type = AT_IGNORE;
951 else
952 auxv->u.a_val = info->phdr;
953 break;
954
955 case AT_PHNUM:
956 if (info->phdr == 0)
957 auxv->a_type = AT_IGNORE;
958 else
959 auxv->u.a_val = info->phnum;
960 break;
961
962 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000963 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000964 break;
965
966 case AT_PLATFORM: /* points to a platform description string */
967 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
968 break;
969
970 case AT_ENTRY:
971 auxv->u.a_val = info->entry;
972 break;
973
974 case AT_IGNORE:
975 case AT_EXECFD:
976 case AT_PHENT:
977 case AT_PAGESZ:
978 case AT_FLAGS:
979 case AT_NOTELF:
980 case AT_UID:
981 case AT_EUID:
982 case AT_GID:
983 case AT_EGID:
984 case AT_CLKTCK:
985 case AT_HWCAP:
986 case AT_FPUCW:
987 case AT_DCACHEBSIZE:
988 case AT_ICACHEBSIZE:
989 case AT_UCACHEBSIZE:
990 /* All these are pointerless, so we don't need to do anything
991 about them. */
992 break;
993
994 case AT_SECURE:
995 /* If this is 1, then it means that this program is running
996 suid, and therefore the dynamic linker should be careful
997 about LD_PRELOAD, etc. However, since stage1 (the thing
998 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000999 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001000 set AT_SECURE to 0. */
1001 auxv->u.a_val = 0;
1002 break;
1003
1004 case AT_SYSINFO:
1005 /* Leave this unmolested for now, but we'll update it later
1006 when we set up the client trampoline code page */
1007 break;
1008
1009 case AT_SYSINFO_EHDR:
1010 /* Trash this, because we don't reproduce it */
1011 auxv->a_type = AT_IGNORE;
1012 break;
1013
1014 default:
1015 /* stomp out anything we don't know about */
1016 if (0)
nethercote545fe672004-11-01 16:52:43 +00001017 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001018 auxv->a_type = AT_IGNORE;
1019 break;
1020
1021 }
1022 }
1023 *auxv = *orig_auxv;
1024 vg_assert(auxv->a_type == AT_NULL);
1025
njnc6168192004-11-29 13:54:10 +00001026// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1027// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001028#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001029 /* --- trampoline page --- */
1030 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1031 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001032#endif
nethercotef84f6952004-07-15 14:58:33 +00001033
nethercote71980f02004-01-24 18:18:54 +00001034 vg_assert((strtab-stringbase) == stringsize);
1035
nethercote5ee67ca2004-06-22 14:00:09 +00001036 /* We know the initial ESP is pointing at argc/argv */
1037 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001038 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001039
sewardj79048ce2005-02-18 08:28:32 +00001040 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001041 return cl_esp;
1042}
1043
1044/*====================================================================*/
1045/*=== Find executable ===*/
1046/*====================================================================*/
1047
thughes4ad52d02004-06-27 17:37:21 +00001048static const char* executable_name;
1049
1050static Bool match_executable(const char *entry) {
1051 char buf[strlen(entry) + strlen(executable_name) + 2];
1052
1053 /* empty PATH element means . */
1054 if (*entry == '\0')
1055 entry = ".";
1056
1057 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1058
1059 if (access(buf, R_OK|X_OK) == 0) {
1060 executable_name = strdup(buf);
1061 vg_assert(NULL != executable_name);
1062 return True;
1063 }
1064 return False;
1065}
1066
nethercote71980f02004-01-24 18:18:54 +00001067static const char* find_executable(const char* exec)
1068{
1069 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001070 executable_name = exec;
1071 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001072 /* no '/' - we need to search the path */
1073 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001074 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001075 }
thughes4ad52d02004-06-27 17:37:21 +00001076 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001077}
1078
1079
1080/*====================================================================*/
1081/*=== Loading tools ===*/
1082/*====================================================================*/
1083
1084static void list_tools(void)
1085{
1086 DIR *dir = opendir(VG_(libdir));
1087 struct dirent *de;
1088 int first = 1;
1089
1090 if (dir == NULL) {
1091 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001092 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001093 return;
1094 }
1095
nethercotef4928da2004-06-15 10:54:40 +00001096 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001097 int len = strlen(de->d_name);
1098
njn063c5402004-11-22 16:58:05 +00001099 /* look for vgtool_TOOL.so names */
1100 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1101 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001102 VG_STREQ(de->d_name + len - 3, ".so")) {
1103 if (first) {
1104 fprintf(stderr, "Available tools:\n");
1105 first = 0;
1106 }
1107 de->d_name[len-3] = '\0';
1108 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001109 }
1110 }
1111
1112 closedir(dir);
1113
1114 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001115 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1116 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001117}
1118
1119
1120/* Find and load a tool, and check it looks ok. Also looks to see if there's
1121 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001122static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001123 ToolInfo** toolinfo_out, char **preloadpath_out )
1124{
1125 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001126 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001127 char buf[len];
1128 void* handle;
1129 ToolInfo* toolinfo;
1130 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001131
1132 // XXX: allowing full paths for --tool option -- does it make sense?
1133 // Doesn't allow for vgpreload_<tool>.so.
1134
1135 if (strchr(toolname, '/') != 0) {
1136 /* toolname contains '/', and so must be a pathname */
1137 handle = dlopen(toolname, RTLD_NOW);
1138 } else {
1139 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001140 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001141 handle = dlopen(buf, RTLD_NOW);
1142
1143 if (handle != NULL) {
1144 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1145 if (access(buf, R_OK) == 0) {
1146 preloadpath = strdup(buf);
1147 vg_assert(NULL != preloadpath);
1148 }
1149 }
1150 }
1151
1152 ok = (NULL != handle);
1153 if (!ok) {
1154 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1155 goto bad_load;
1156 }
1157
njn51d827b2005-05-09 01:02:08 +00001158 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001159 ok = (NULL != toolinfo);
1160 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001161 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001162 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1163 goto bad_load;
1164 }
1165
1166 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001167 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1168 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001169 if (!ok) {
1170 fprintf(stderr, "Error:\n"
1171 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001172 " Interface version used by core is: %d (size %d)\n"
1173 " Interface version used by tool is: %d (size %d)\n"
1174 " The version numbers must match.\n",
1175 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001176 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001177 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001178 toolinfo->sizeof_ToolInfo);
1179 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001180 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001181 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001182 else
nethercote996901a2004-08-03 13:29:09 +00001183 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001184 goto bad_load;
1185 }
1186
njn8a97c6d2005-03-31 04:37:24 +00001187 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001188 *toolinfo_out = toolinfo;
1189 *preloadpath_out = preloadpath;
1190 return;
1191
1192
1193 bad_load:
1194 if (handle != NULL)
1195 dlclose(handle);
1196
nethercotef4928da2004-06-15 10:54:40 +00001197 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001198 list_tools();
1199 exit(127);
1200}
1201
nethercotef4928da2004-06-15 10:54:40 +00001202
1203/*====================================================================*/
1204/*=== Command line errors ===*/
1205/*====================================================================*/
1206
njnbe9b47b2005-05-15 16:22:58 +00001207static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001208{
njnbe9b47b2005-05-15 16:22:58 +00001209 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001210 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001211}
1212
1213void VG_(bad_option) ( Char* opt )
1214{
njnbe9b47b2005-05-15 16:22:58 +00001215 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001216 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001217 VG_(printf)("valgrind: Use --help for more information.\n");
1218 VG_(exit)(1);
1219}
1220
nethercotef4928da2004-06-15 10:54:40 +00001221static void missing_prog ( void )
1222{
njnbe9b47b2005-05-15 16:22:58 +00001223 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001224 VG_(printf)("valgrind: no program specified\n");
1225 VG_(printf)("valgrind: Use --help for more information.\n");
1226 VG_(exit)(1);
1227}
1228
1229static void config_error ( Char* msg )
1230{
njnbe9b47b2005-05-15 16:22:58 +00001231 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001232 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1233 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1234 VG_(exit)(1);
1235}
1236
1237
nethercote71980f02004-01-24 18:18:54 +00001238/*====================================================================*/
1239/*=== Loading the client ===*/
1240/*====================================================================*/
1241
nethercotef4928da2004-06-15 10:54:40 +00001242static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001243 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1244{
1245 // If they didn't specify an executable with --exec, and didn't specify
1246 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001247 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001248 if (cl_argv[0] == NULL ||
1249 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1250 {
nethercotef4928da2004-06-15 10:54:40 +00001251 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001252 }
1253 }
1254
1255 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001256 info->exe_base = VG_(client_base);
1257 info->exe_end = VG_(client_end);
1258 info->argv = cl_argv;
1259
nethercotef4928da2004-06-15 10:54:40 +00001260 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001261 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001262 // Totally zero 'info' before continuing.
1263 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001264 } else {
1265 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001266 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001267 ret = do_exec(exec, info);
1268 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001269 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1270 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001271 exit(127);
1272 }
1273 }
1274
1275 /* Copy necessary bits of 'info' that were filled in */
1276 *client_eip = info->init_eip;
1277 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1278}
1279
nethercote969ecf12004-10-13 17:29:01 +00001280/*====================================================================*/
1281/*=== Address space unpadding ===*/
1282/*====================================================================*/
1283
1284typedef struct {
1285 char* killpad_start;
1286 char* killpad_end;
1287 struct stat* killpad_padstat;
1288} killpad_extra;
1289
1290static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1291 int maj, int min, int ino, void* ex)
1292{
1293 killpad_extra* extra = ex;
1294 void *b, *e;
1295 int res;
1296
1297 vg_assert(NULL != extra->killpad_padstat);
1298
1299 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1300 extra->killpad_padstat->st_ino != ino)
1301 return 1;
1302
1303 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1304 return 1;
1305
1306 if (segstart <= extra->killpad_start)
1307 b = extra->killpad_start;
1308 else
1309 b = segstart;
1310
1311 if (segend >= extra->killpad_end)
1312 e = extra->killpad_end;
1313 else
1314 e = segend;
1315
1316 res = munmap(b, (char *)e-(char *)b);
1317 vg_assert(0 == res);
1318
1319 return 1;
1320}
1321
1322// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001323static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001324{
1325 static struct stat padstat;
1326 killpad_extra extra;
1327 int res;
1328
sewardjb5f6f512005-03-10 23:59:00 +00001329 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001330
1331 res = fstat(padfile, &padstat);
1332 vg_assert(0 == res);
1333 extra.killpad_padstat = &padstat;
1334 extra.killpad_start = start;
1335 extra.killpad_end = end;
1336 foreach_map(killpad, &extra);
1337}
1338
sewardj2c5ffbe2005-03-12 13:32:06 +00001339static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001340{
1341 int res = close(padfile);
1342 vg_assert(0 == res);
1343}
1344
sewardj71bc3cb2005-05-19 00:25:45 +00001345/*====================================================================*/
1346/*=== Command-line: variables, processing, etc ===*/
1347/*====================================================================*/
1348
1349// See pub_{core,tool}_options.h for explanations of all these.
1350
sewardj2c5ffbe2005-03-12 13:32:06 +00001351static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001352{
njn25e49d8e72002-09-23 09:36:25 +00001353 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001354"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001355"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001356" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001357" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001358" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001359" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001360" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001361" -q --quiet run silently; only print error msgs\n"
1362" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001363" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001364" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001365" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001366" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001367"\n"
1368" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001369" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001370" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001371" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001372" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001373" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001374"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001375" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001376" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1377" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001378" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001379" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001380" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001381" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001382" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1383" --show-below-main=no|yes continue stack traces below main() [no]\n"
1384" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001385" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001386" --db-attach=no|yes start debugger when errors detected? [no]\n"
1387" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1388" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001389" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1390" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001391"\n";
njn7cf0bd32002-06-08 13:36:03 +00001392
njn25e49d8e72002-09-23 09:36:25 +00001393 Char* usage2 =
1394"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001395" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001396" --sanity-level=<number> level of sanity checking to do [1]\n"
1397" --single-step=no|yes translate each instr separately? [no]\n"
1398" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001399" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001400" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001401" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1402" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001403" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001404" --trace-syscalls=no|yes show all system calls? [no]\n"
1405" --trace-signals=no|yes show signal handling details? [no]\n"
1406" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001407" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001408" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001409" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001410#if 0
1411" --model-pthreads=yes|no model the pthreads library [no]\n"
1412#endif
1413" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001414"\n"
1415" --vex-iropt-verbosity 0 .. 9 [0]\n"
1416" --vex-iropt-level 0 .. 2 [2]\n"
1417" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001418" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1419" --vex-guest-max-insns 1 .. 100 [50]\n"
1420" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1421"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001422" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001423" 1000 0000 show conversion into IR\n"
1424" 0100 0000 show after initial opt\n"
1425" 0010 0000 show after instrumentation\n"
1426" 0001 0000 show after second opt\n"
1427" 0000 1000 show after tree building\n"
1428" 0000 0100 show selecting insns\n"
1429" 0000 0010 show after reg-alloc\n"
1430" 0000 0001 show final assembly\n"
1431"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001432" debugging options for Valgrind tools that report errors\n"
1433" --dump-error=<number> show translation for basic block associated\n"
1434" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001435"\n";
njn3e884182003-04-15 13:03:23 +00001436
1437 Char* usage3 =
1438"\n"
nethercote71980f02004-01-24 18:18:54 +00001439" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001440"\n"
njn53612422005-03-12 16:22:54 +00001441" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001442" and licensed under the GNU General Public License, version 2.\n"
1443" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001444"\n"
nethercote137bc552003-11-14 17:47:54 +00001445" Tools are copyright and licensed by their authors. See each\n"
1446" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001447"\n";
njn7cf0bd32002-06-08 13:36:03 +00001448
njnbe9b47b2005-05-15 16:22:58 +00001449 // Ensure the message goes to stdout
1450 VG_(clo_log_fd) = 1;
1451 vg_assert( !VG_(logging_to_socket) );
1452
fitzhardinge98abfc72003-12-16 02:05:15 +00001453 VG_(printf)(usage1);
1454 if (VG_(details).name) {
1455 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001456 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001457 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001458 else
1459 VG_(printf)(" (none)\n");
1460 }
nethercote6c999f22004-01-31 22:55:15 +00001461 if (debug_help) {
1462 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001463
nethercote6c999f22004-01-31 22:55:15 +00001464 if (VG_(details).name) {
1465 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1466
1467 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001468 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001469 else
1470 VG_(printf)(" (none)\n");
1471 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001472 }
nethercote421281e2003-11-20 16:20:55 +00001473 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001474 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001475}
sewardjde4a1d02002-03-22 01:27:54 +00001476
nethercote71980f02004-01-24 18:18:54 +00001477static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001478 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001479{
nethercote71980f02004-01-24 18:18:54 +00001480 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001481
sewardj8b635a42004-11-22 19:01:47 +00001482 LibVEX_default_VexControl(& VG_(clo_vex_control));
1483
nethercote71980f02004-01-24 18:18:54 +00001484 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001485 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001486
nethercotef6a1d502004-08-09 12:21:57 +00001487 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001488 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001489 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001490
nethercotef6a1d502004-08-09 12:21:57 +00001491 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1492 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001493 *need_help = 1;
1494
nethercotef6a1d502004-08-09 12:21:57 +00001495 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001496 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001497
nethercotef6c99d72004-11-09 14:35:43 +00001498 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001499 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001500
nethercotef6a1d502004-08-09 12:21:57 +00001501 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1502 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001503 }
1504 }
nethercote71980f02004-01-24 18:18:54 +00001505}
1506
nethercote5ee67ca2004-06-22 14:00:09 +00001507static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001508{
nethercotef8548672004-06-21 12:42:35 +00001509 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001510 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001511 enum {
1512 VgLogTo_Fd,
1513 VgLogTo_File,
1514 VgLogTo_FileExactly,
1515 VgLogTo_Socket
1516 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001517
nethercotee1730692003-11-20 10:38:07 +00001518 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001519 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001520
sewardj19d81412002-06-03 01:10:40 +00001521 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001522 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001523 config_error("Please use absolute paths in "
1524 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001525
njnc6168192004-11-29 13:54:10 +00001526// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001527#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001528 {
sewardjb5f6f512005-03-10 23:59:00 +00001529 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001530 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1531 switch(auxp[0]) {
1532 case AT_SYSINFO:
1533 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1534 break;
1535 }
1536 }
1537 }
1538#endif
sewardjde4a1d02002-03-22 01:27:54 +00001539
nethercotef6a1d502004-08-09 12:21:57 +00001540 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001541
nethercotef6a1d502004-08-09 12:21:57 +00001542 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001543 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001544
thughes3bfd5a02004-07-18 08:05:44 +00001545 /* Look for a colon in the switch name */
1546 while (*colon && *colon != ':' && *colon != '=')
1547 colon++;
nethercote71980f02004-01-24 18:18:54 +00001548
1549 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001550 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001551 if (VG_CLO_STREQN(2, arg, "--") &&
1552 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1553 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1554 {
1555 // prefix matches, convert "--toolname:foo" to "--foo"
1556 if (0)
1557 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001558 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001559 arg[0] = '-';
1560 arg[1] = '-';
1561
1562 } else {
1563 // prefix doesn't match, skip to next arg
1564 continue;
1565 }
1566 }
1567
fitzhardinge98abfc72003-12-16 02:05:15 +00001568 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001569 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1570 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1571 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001572
njn45270a22005-03-27 01:00:11 +00001573 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001574
nethercote71980f02004-01-24 18:18:54 +00001575 else if (VG_CLO_STREQ(arg, "-v") ||
1576 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001577 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001578
nethercote71980f02004-01-24 18:18:54 +00001579 else if (VG_CLO_STREQ(arg, "-q") ||
1580 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001581 VG_(clo_verbosity)--;
1582
sewardj1cf558c2005-04-25 01:36:56 +00001583 else if (VG_CLO_STREQ(arg, "-d")) {
1584 /* do nothing */
1585 }
1586
sewardj71bc3cb2005-05-19 00:25:45 +00001587 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001588 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1589 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1590 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1591 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1592 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1593 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1594 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001595 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001596 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1597 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1598 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1599 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1600 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1601 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1602 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1603 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1604 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001605 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001606 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1607 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1608 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1609 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1610 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001611
njn45270a22005-03-27 01:00:11 +00001612 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1613 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001614
njn45270a22005-03-27 01:00:11 +00001615 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1616 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1617 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1618 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1619 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001620
njn45270a22005-03-27 01:00:11 +00001621 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001622 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001623 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001624 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001625 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001626 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001627 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001628 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001629 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001630 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001631 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001632 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1633
nethercotef8548672004-06-21 12:42:35 +00001634 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001635 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001636 VG_(clo_log_name) = NULL;
1637 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001638 }
1639
nethercotef8548672004-06-21 12:42:35 +00001640 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001641 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001642 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001643 }
njnd6bc3c32005-03-27 00:44:31 +00001644
sewardj603d4102005-01-11 14:01:02 +00001645 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001646 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001647 VG_(clo_log_name) = &arg[19];
1648 }
sewardjde4a1d02002-03-22 01:27:54 +00001649
nethercotef8548672004-06-21 12:42:35 +00001650 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001651 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001652 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001653 }
1654
nethercote71980f02004-01-24 18:18:54 +00001655 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001656 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001657 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001658 VG_(message)(Vg_UserMsg,
1659 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001660 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001661 }
nethercote71980f02004-01-24 18:18:54 +00001662 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001663 VG_(clo_n_suppressions)++;
1664 }
sewardjde4a1d02002-03-22 01:27:54 +00001665
sewardjfa8ec112005-01-19 11:55:34 +00001666 /* "stuvwxyz" --> stuvwxyz (binary) */
1667 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1668 Int j;
1669 char* opt = & arg[14];
1670
1671 if (8 != VG_(strlen)(opt)) {
1672 VG_(message)(Vg_UserMsg,
1673 "--trace-flags argument must have 8 digits");
1674 VG_(bad_option)(arg);
1675 }
1676 for (j = 0; j < 8; j++) {
1677 if ('0' == opt[j]) { /* do nothing */ }
1678 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1679 else {
1680 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1681 "contain 0s and 1s");
1682 VG_(bad_option)(arg);
1683 }
1684 }
1685 }
1686
1687 /* "stuvwxyz" --> stuvwxyz (binary) */
1688 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001689 Int j;
nethercote71980f02004-01-24 18:18:54 +00001690 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001691
sewardj2a99cf62004-11-24 10:44:19 +00001692 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001693 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001694 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001695 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001696 }
sewardj8b635a42004-11-22 19:01:47 +00001697 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001698 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001699 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001700 else {
sewardjfa8ec112005-01-19 11:55:34 +00001701 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001702 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001703 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001704 }
1705 }
1706 }
sewardjde4a1d02002-03-22 01:27:54 +00001707
njn45270a22005-03-27 01:00:11 +00001708 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001709
sewardjd153fae2005-01-10 17:24:47 +00001710 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1711 VG_(clo_gen_suppressions) = 0;
1712 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1713 VG_(clo_gen_suppressions) = 1;
1714 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1715 VG_(clo_gen_suppressions) = 2;
1716
nethercote71980f02004-01-24 18:18:54 +00001717 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001718 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001719 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001720 }
njn8c0b3bb2005-03-12 21:20:39 +00001721 skip_arg:
1722 if (arg != vg_argv[i])
1723 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001724 }
1725
sewardj998d40d2004-12-06 14:24:52 +00001726 /* Make VEX control parameters sane */
1727
1728 if (VG_(clo_vex_control).guest_chase_thresh
1729 >= VG_(clo_vex_control).guest_max_insns)
1730 VG_(clo_vex_control).guest_chase_thresh
1731 = VG_(clo_vex_control).guest_max_insns - 1;
1732
1733 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1734 VG_(clo_vex_control).guest_chase_thresh = 0;
1735
1736 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001737
njnf9ebf672003-05-12 21:41:30 +00001738 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001739 VG_(clo_verbosity) = 0;
1740
nethercote04d0fbc2004-01-26 16:48:06 +00001741 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001742 VG_(message)(Vg_UserMsg, "");
1743 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001744 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001745 VG_(message)(Vg_UserMsg,
1746 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001747 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001748 }
1749
njnbe9b47b2005-05-15 16:22:58 +00001750 if (VG_(clo_gen_suppressions) > 0 &&
1751 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1752 VG_(message)(Vg_UserMsg,
1753 "Can't use --gen-suppressions= with this tool,");
1754 VG_(message)(Vg_UserMsg,
1755 "as it doesn't generate errors.");
1756 VG_(bad_option)("--gen-suppressions=");
1757 }
1758
sewardj71bc3cb2005-05-19 00:25:45 +00001759 /* If we've been asked to emit XML, mash around various other
1760 options so as to constrain the output somewhat, and to remove
1761 any need for user input during the run. */
1762 if (VG_(clo_xml)) {
1763 /* Disable suppression generation (requires user input) */
1764 VG_(clo_gen_suppressions) = 0;
1765 /* Disable attaching to GDB (requires user input) */
1766 VG_(clo_db_attach) = False;
1767 /* Set a known verbosity level */
1768 VG_(clo_verbosity) = 1;
1769 /* Disable error limits (this might be a bad idea!) */
1770 VG_(clo_error_limit) = False;
1771 /* Disable emulation warnings */
1772 VG_(clo_show_emwarns) = False;
1773 /* Disable waiting for GDB to debug Valgrind */
1774 VG_(clo_wait_for_gdb) = False;
1775 /* No file-descriptor leak checking yet */
1776 VG_(clo_track_fds) = False;
1777 /* Also, we want to set options for the leak checker, but that
1778 will have to be done in Memcheck's flag-handling code, not
1779 here. */
1780 }
1781
njnbe9b47b2005-05-15 16:22:58 +00001782 /* All non-logging-related options have been checked. If the logging
1783 option specified is ok, we can switch to it, as we know we won't
1784 have to generate any other command-line-related error messages.
1785 (So far we should be still attached to stderr, so we can show on
1786 the terminal any problems to do with processing command line
1787 opts.)
1788
1789 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001790 should be connected to whatever sink has been selected, and we
1791 indiscriminately chuck stuff into it without worrying what the
1792 nature of it is. Oh the wonder of Unix streams. */
1793
njnbe9b47b2005-05-15 16:22:58 +00001794 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1795 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001796
njnbe9b47b2005-05-15 16:22:58 +00001797 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001798
sewardj4cf05692002-10-27 20:28:29 +00001799 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001800 vg_assert(VG_(clo_log_name) == NULL);
1801 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001802 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001803
sewardj4cf05692002-10-27 20:28:29 +00001804 case VgLogTo_File: {
1805 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001806 Int seq = 0;
1807 Int pid = VG_(getpid)();
1808
nethercotef8548672004-06-21 12:42:35 +00001809 vg_assert(VG_(clo_log_name) != NULL);
1810 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001811
nethercote71980f02004-01-24 18:18:54 +00001812 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001813 if (seq == 0)
1814 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001815 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001816 else
1817 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001818 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001819 seq++;
1820
njnbe9b47b2005-05-15 16:22:58 +00001821 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001822 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001823 = VG_(open)(logfilename,
1824 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1825 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001826 if (eventually_log_fd >= 0) {
1827 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001828 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001829 } else {
njnbe9b47b2005-05-15 16:22:58 +00001830 // If the file already existed, we try the next name. If it
1831 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001832 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001833 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001834 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001835 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001836 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001837 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001838 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001839 }
1840 }
1841 }
sewardj603d4102005-01-11 14:01:02 +00001842 break; /* switch (VG_(clo_log_to)) */
1843 }
1844
1845 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001846 vg_assert(VG_(clo_log_name) != NULL);
1847 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001848
1849 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001850 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001851 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1852 VKI_S_IRUSR|VKI_S_IWUSR);
1853 if (eventually_log_fd >= 0) {
1854 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001855 } else {
sewardj603d4102005-01-11 14:01:02 +00001856 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001857 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001858 VG_(clo_log_name));
1859 VG_(bad_option)(
1860 "--log-file-exactly=<file> (didn't work out for some reason.)");
1861 /*NOTREACHED*/
1862 }
1863 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001864 }
1865
1866 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001867 vg_assert(VG_(clo_log_name) != NULL);
1868 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1869 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1870 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001871 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001872 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001873 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001874 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001875 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001876 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001877 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001878 }
nethercotef8548672004-06-21 12:42:35 +00001879 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001880 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001881 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001882 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001883 VG_(message)(Vg_UserMsg,
1884 "Log messages will sent to stderr instead." );
1885 VG_(message)(Vg_UserMsg,
1886 "" );
1887 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001888 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001889 } else {
nethercotef8548672004-06-21 12:42:35 +00001890 vg_assert(eventually_log_fd > 0);
1891 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001892 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001893 }
sewardj73cf3bc2002-11-03 03:20:15 +00001894 break;
1895 }
sewardj4cf05692002-10-27 20:28:29 +00001896 }
1897
sewardj71bc3cb2005-05-19 00:25:45 +00001898
1899 /* Check that the requested tool actually supports XML output. */
1900 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1901 VG_(clo_xml) = False;
1902 VG_(message)(Vg_UserMsg,
1903 "Currently only Memcheck supports XML output.");
1904 VG_(bad_option)("--xml=yes");
1905 /*NOTREACHED*/
1906 }
1907
njnbe9b47b2005-05-15 16:22:58 +00001908 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1909 // XXX: this is more or less duplicating the behaviour of the calls to
1910 // VG_(safe_fd)() above, although this does not close the original fd.
1911 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1912 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001913 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001914 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001915 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1916 else {
nethercotef8548672004-06-21 12:42:35 +00001917 VG_(clo_log_fd) = eventually_log_fd;
1918 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001919 }
1920
sewardj4cf05692002-10-27 20:28:29 +00001921 /* Ok, the logging sink is running now. Print a suitable preamble.
1922 If logging to file or a socket, write details of parent PID and
1923 command line args, to help people trying to interpret the
1924 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001925
sewardj71bc3cb2005-05-19 00:25:45 +00001926 if (VG_(clo_xml)) {
1927 VG_(message)(Vg_UserMsg, "");
sewardj8665d8e2005-06-01 17:35:23 +00001928 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1929 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001930 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1931 VG_(message)(Vg_UserMsg, "");
1932 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1933 VG_(message)(Vg_UserMsg, "");
1934 }
1935
1936 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1937 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1938
sewardj83adf412002-05-01 01:25:45 +00001939 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001940 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001941 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1942 xpre,
njnd04b7c62002-10-03 14:05:52 +00001943 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001944 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001945 NULL == VG_(details).version
1946 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001947 VG_(details).description,
1948 xpost);
1949 VG_(message)(Vg_UserMsg, "%s%s%s",
1950 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001951
njnd04b7c62002-10-03 14:05:52 +00001952 /* Core details */
1953 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001954 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1955 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001956 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001957 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1958 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001959 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001960 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1961 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001962 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001963 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1964 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00001965 }
1966
njnbe9b47b2005-05-15 16:22:58 +00001967 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001968 VG_(message)(Vg_UserMsg, "");
1969 VG_(message)(Vg_UserMsg,
1970 "My PID = %d, parent PID = %d. Prog and args are:",
1971 VG_(getpid)(), VG_(getppid)() );
1972 for (i = 0; i < VG_(client_argc); i++)
1973 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1974 }
sewardj71bc3cb2005-05-19 00:25:45 +00001975 else
1976 if (VG_(clo_xml)) {
1977 VG_(message)(Vg_UserMsg, "");
1978 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1979 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00001980 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00001981 VG_(message)(Vg_UserMsg, "");
1982 VG_(message)(Vg_UserMsg, "<argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001983 for (i = 0; i < VG_(client_argc); i++) {
1984 HChar* tag = i==0 ? "exe" : "arg";
1985 VG_(message)(Vg_UserMsg, " <%s>%s</%s>",
1986 tag, VG_(client_argv)[i], tag);
1987 }
sewardj71bc3cb2005-05-19 00:25:45 +00001988 VG_(message)(Vg_UserMsg, "</argv>");
1989 }
sewardj4cf05692002-10-27 20:28:29 +00001990
sewardjde4a1d02002-03-22 01:27:54 +00001991 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001992 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001993 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001994 VG_(message)(Vg_DebugMsg, "");
1995 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1996 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001997 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001998 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001999
njn1fd5eb22005-03-13 05:43:23 +00002000 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002001 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002002 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002003 }
nethercotea70f7352004-04-18 12:08:46 +00002004
njn1fd5eb22005-03-13 05:43:23 +00002005 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002006 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2007 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002008 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002009 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002010# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002011 Char version_buf[BUF_LEN];
2012 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002013 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002014 if (n > 0) {
2015 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002016 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002017 } else {
njn1fd5eb22005-03-13 05:43:23 +00002018 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002019 }
2020 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002021# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002022 }
sewardjde4a1d02002-03-22 01:27:54 +00002023 }
2024
fitzhardinge98abfc72003-12-16 02:05:15 +00002025 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002026 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002027 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002028 needs one, load the default */
2029 static const Char default_supp[] = "default.supp";
2030 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2031 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2032 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2033 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2034 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
2036}
2037
nethercotef6a1d502004-08-09 12:21:57 +00002038// Build the string for VALGRINDCLO.
2039Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2040{
2041 /* If we're tracing the children, then we need to start it
2042 with our starter+arguments, which are copied into VALGRINDCLO,
2043 except the --exec= option is changed if present.
2044 */
2045 Int i;
2046 Char *exec;
2047 Char *cp;
2048 Char *optvar;
2049 Int optlen, execlen;
2050
2051 // All these allocated blocks are not free - because we're either
2052 // going to exec, or panic when we fail.
2053
2054 // Create --exec= option: "--exec=<exename>"
2055 exec = VG_(arena_malloc)(VG_AR_CORE,
2056 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2057 vg_assert(NULL != exec);
2058 VG_(sprintf)(exec, "--exec=%s", exename);
2059
2060 // Allocate space for optvar (may overestimate by counting --exec twice,
2061 // no matter)
2062 optlen = 1;
2063 for (i = 0; i < vg_argc; i++)
2064 optlen += VG_(strlen)(vg_argv[i]) + 1;
2065 optlen += VG_(strlen)(exec)+1;
2066 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2067
2068 // Copy all valgrind args except the old --exec (if present)
2069 // VG_CLO_SEP is the separator.
2070 cp = optvar;
2071 for (i = 1; i < vg_argc; i++) {
2072 Char *arg = vg_argv[i];
2073
2074 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2075 // don't copy existing --exec= arg
2076 } else if (VG_(strcmp)(arg, "--") == 0) {
2077 // stop at "--"
2078 break;
2079 } else {
2080 // copy non "--exec" arg
2081 Int len = VG_(strlen)(arg);
2082 VG_(memcpy)(cp, arg, len);
2083 cp += len;
2084 *cp++ = VG_CLO_SEP;
2085 }
2086 }
2087 // Add the new --exec= option
2088 execlen = VG_(strlen)(exec);
2089 VG_(memcpy)(cp, exec, execlen);
2090 cp += execlen;
2091 *cp++ = VG_CLO_SEP;
2092
2093 *cp = '\0';
2094
2095 return optvar;
2096}
2097
2098// Build "/proc/self/fd/<execfd>".
2099Char* VG_(build_child_exename)( void )
2100{
2101 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2102 vg_assert(NULL != exename);
2103 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2104 return exename;
2105}
2106
sewardjde4a1d02002-03-22 01:27:54 +00002107
nethercote71980f02004-01-24 18:18:54 +00002108/*====================================================================*/
2109/*=== File descriptor setup ===*/
2110/*====================================================================*/
2111
2112static void setup_file_descriptors(void)
2113{
2114 struct vki_rlimit rl;
2115
2116 /* Get the current file descriptor limits. */
2117 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2118 rl.rlim_cur = 1024;
2119 rl.rlim_max = 1024;
2120 }
2121
2122 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002123 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2124 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002125 } else {
2126 rl.rlim_cur = rl.rlim_max;
2127 }
2128
2129 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002130 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2131 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002132
2133 /* Update the soft limit. */
2134 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2135
nethercotef6a1d502004-08-09 12:21:57 +00002136 if (vgexecfd != -1)
2137 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002138 if (VG_(clexecfd) != -1)
2139 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2140}
2141
nethercote71980f02004-01-24 18:18:54 +00002142/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002143/*=== Initialise program data/text, etc. ===*/
2144/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002145
sewardjb5f6f512005-03-10 23:59:00 +00002146static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2147 UInt dev, UInt ino, ULong foffset,
2148 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002149{
nethercote71980f02004-01-24 18:18:54 +00002150 /* Only record valgrind mappings for now, without loading any
2151 symbols. This is so we know where the free space is before we
2152 start allocating more memory (note: heap is OK, it's just mmap
2153 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002154 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002155 VG_(debugLog)(2, "main",
2156 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002157 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002158 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002159 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2160 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002161 /* update VG_(valgrind_last) if it looks wrong */
2162 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002163 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002164 }
sewardjde4a1d02002-03-22 01:27:54 +00002165}
2166
nethercote71980f02004-01-24 18:18:54 +00002167// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002168Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002169
sewardjb5f6f512005-03-10 23:59:00 +00002170/*
2171 This second pass adds in client mappings, and loads symbol tables
2172 for all interesting mappings. The trouble is that things can
2173 change as we go, because we're calling the Tool to track memory as
2174 we find it.
2175
2176 So for Valgrind mappings, we don't replace any mappings which
2177 aren't still identical (which will include the .so mappings, so we
2178 will load their symtabs)>
2179 */
2180static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2181 UInt dev, UInt ino, ULong foffset,
2182 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002183{
nethercote71980f02004-01-24 18:18:54 +00002184 UInt flags;
2185 Bool is_stack_segment;
2186 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002187
nethercote71980f02004-01-24 18:18:54 +00002188 is_stack_segment
2189 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002190
sewardj8c615892005-04-25 02:38:28 +00002191 VG_(debugLog)(2, "main",
2192 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002193 (void*)start, (void*)(start+size), prot, is_stack_segment,
2194 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002195
nethercote71980f02004-01-24 18:18:54 +00002196 if (is_stack_segment)
2197 flags = SF_STACK | SF_GROWDOWN;
2198 else
2199 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002200
nethercote71980f02004-01-24 18:18:54 +00002201 if (filename != NULL)
2202 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002203
sewardjb5f6f512005-03-10 23:59:00 +00002204#if 0
2205 // This needs to be fixed properly. jrs 20050307
2206 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2207 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002208
sewardjb5f6f512005-03-10 23:59:00 +00002209 /* We have to be a bit careful about inserting new mappings into
2210 the Valgrind part of the address space. We're actively
2211 changing things as we parse these mappings, particularly in
2212 shadow memory, and so we don't want to overwrite those
2213 changes. Therefore, we only insert/update a mapping if it is
2214 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
sewardjb5f6f512005-03-10 23:59:00 +00002216 NOTE: we're only talking about the Segment list mapping
2217 metadata; this doesn't actually mmap anything more. */
2218 if (filename || (s && s->addr == start && s->len == size)) {
2219 flags |= SF_VALGRIND;
2220 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2221 } else {
2222 /* assert range is already mapped */
2223 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2224 }
2225 } else
2226#endif
2227 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2228
2229 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2230 VG_TRACK( new_mem_startup, start, size,
2231 !!(prot & VKI_PROT_READ),
2232 !!(prot & VKI_PROT_WRITE),
2233 !!(prot & VKI_PROT_EXEC));
2234 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002235
nethercote71980f02004-01-24 18:18:54 +00002236 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002237 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002238 vg_assert(0 != r_esp);
2239 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002240 if (0) {
2241 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002242 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002243 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2244 r_esp, start+size);
2245 }
nethercote71980f02004-01-24 18:18:54 +00002246 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002247 // what's this for?
2248 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002249 }
sewardjde4a1d02002-03-22 01:27:54 +00002250}
2251
2252
nethercote71980f02004-01-24 18:18:54 +00002253/*====================================================================*/
2254/*=== Sanity check machinery (permanently engaged) ===*/
2255/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002256
2257/* A fast sanity check -- suitable for calling circa once per
2258 millisecond. */
2259
nethercote885dd912004-08-03 23:14:00 +00002260void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002261{
sewardjb5f6f512005-03-10 23:59:00 +00002262 ThreadId tid;
2263
njn37cea302002-09-30 11:24:00 +00002264 VGP_PUSHCC(VgpCoreCheapSanity);
2265
nethercote27fec902004-06-16 21:26:32 +00002266 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002267
2268 /* --- First do all the tests that we can do quickly. ---*/
2269
nethercote297effd2004-08-02 15:07:57 +00002270 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002271
njn25e49d8e72002-09-23 09:36:25 +00002272 /* Check stuff pertaining to the memory check system. */
2273
2274 /* Check that nobody has spuriously claimed that the first or
2275 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002276 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002277 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002278 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002279 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002280 }
njn25e49d8e72002-09-23 09:36:25 +00002281
2282 /* --- Now some more expensive checks. ---*/
2283
2284 /* Once every 25 times, check some more expensive stuff. */
2285 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002286 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002287 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002288
njn37cea302002-09-30 11:24:00 +00002289 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002290 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002291
2292# if 0
2293 { void zzzmemscan(void); zzzmemscan(); }
2294# endif
2295
nethercote297effd2004-08-02 15:07:57 +00002296 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002297 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002298
2299 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002300 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002301 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002302 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002303 }
sewardjb5f6f512005-03-10 23:59:00 +00002304
2305 /* Check that Segments and /proc/self/maps match up */
2306 //vg_assert(VG_(sanity_check_memory)());
2307
2308 /* Look for stack overruns. Visit all threads. */
2309 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002310 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002311
2312 if (VG_(threads)[tid].status == VgTs_Empty ||
2313 VG_(threads)[tid].status == VgTs_Zombie)
2314 continue;
2315
2316 remains = VGA_(stack_unused)(tid);
2317 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002318 VG_(message)(Vg_DebugMsg,
2319 "WARNING: Thread %d is within %d bytes "
2320 "of running out of stack!",
2321 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002322 }
2323
njn25e49d8e72002-09-23 09:36:25 +00002324 /*
nethercote297effd2004-08-02 15:07:57 +00002325 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002326 */
njn37cea302002-09-30 11:24:00 +00002327 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002328 }
2329
nethercote27fec902004-06-16 21:26:32 +00002330 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002331 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002332 /* Check sanity of the low-level memory manager. Note that bugs
2333 in the client's code can cause this to fail, so we don't do
2334 this check unless specially asked for. And because it's
2335 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002336 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002337 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002338 }
njn37cea302002-09-30 11:24:00 +00002339 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002340}
nethercote71980f02004-01-24 18:18:54 +00002341
2342
2343/*====================================================================*/
2344/*=== main() ===*/
2345/*====================================================================*/
2346
nethercotec314eba2004-07-15 12:59:41 +00002347/*
2348 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002349 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002350 loads the client executable (and the dynamic linker, if necessary)
2351 into the client part, and calls into Valgrind proper.
2352
2353 The code is careful not to allow spurious mappings to appear in the
2354 wrong parts of the address space. In particular, to make sure
2355 dlopen puts things in the right place, it will pad out the forbidden
2356 chunks of address space so that dlopen is forced to put things where
2357 we want them.
2358
2359 The memory map it creates is:
2360
njn311c5d82005-05-15 21:03:42 +00002361 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002362 | client address space |
2363 : :
2364 : :
2365 | client stack |
2366 client_end +-------------------------+
2367 | redzone |
2368 shadow_base +-------------------------+
2369 | |
nethercote996901a2004-08-03 13:29:09 +00002370 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002371 | (may be 0 sized) |
2372 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002373 valgrind_base +-------------------------+
2374 | kickstart executable |
2375 | valgrind heap vvvvvvvvv| (barely used)
2376 - -
2377 | valgrind .so files |
2378 | and mappings |
2379 - -
2380 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002381 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002382 : kernel :
2383
2384 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2385 VG_(mmap)(), we need to build the segment skip-list, so we know where
2386 we can put things. However, building that structure requires
2387 allocating memory. So we need to a bootstrapping process. It's done
2388 by making VG_(arena_malloc)() have a special static superblock that's
2389 used for the first 1MB's worth of allocations. This is enough to
2390 build the segment skip-list.
2391*/
2392
thughes4ad52d02004-06-27 17:37:21 +00002393
sewardj1cf558c2005-04-25 01:36:56 +00002394/* This may be needed before m_mylibc is OK to run. */
2395static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2396{
2397 while (True) {
2398 if (*s1 == 0 && *s2 == 0) return 0;
2399 if (*s1 == 0) return -1;
2400 if (*s2 == 0) return 1;
2401
2402 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2403 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2404
2405 s1++; s2++;
2406 }
2407}
2408
2409
sewardjb5f6f512005-03-10 23:59:00 +00002410int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002411{
2412 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002413 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002414 const char *exec = NULL;
2415 char *preload; /* tool-specific LD_PRELOAD .so */
2416 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002417 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002418 struct exeinfo info;
2419 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002420 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002421 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002422 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002423 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002424 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002425
2426 //============================================================
2427 // Nb: startup is complex. Prerequisites are shown at every step.
2428 //
2429 // *** Be very careful when messing with the order ***
2430 //============================================================
2431
sewardj1cf558c2005-04-25 01:36:56 +00002432 //--------------------------------------------------------------
2433 // Start up the logging mechanism
2434 // p: none
2435 //--------------------------------------------------------------
2436 /* Start the debugging-log system ASAP. First find out how many
2437 "-d"s were specified. This is a pre-scan of the command line. */
2438 loglevel = 0;
2439 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002440 if (argv[i][0] != '-')
2441 break;
2442 if (0 == local_strcmp(argv[i], "--"))
2443 break;
2444 if (0 == local_strcmp(argv[i], "-d"))
2445 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002446 }
2447
2448 /* ... and start the debug logger. Now we can safely emit logging
2449 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002450 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002451
nethercotef4928da2004-06-15 10:54:40 +00002452 //============================================================
2453 // Command line argument handling order:
2454 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002455 // (including the tool-specific usage)
2456 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002457 // * Then, if client is missing, abort with error msg
2458 // * Then, if any cmdline args are bad, abort with error msg
2459 //============================================================
2460
fitzhardingeb50068f2004-02-24 23:42:55 +00002461 // Get the current process datasize rlimit, and set it to zero.
2462 // This prevents any internal uses of brk() from having any effect.
2463 // We remember the old value so we can restore it on exec, so that
2464 // child processes will have a reasonable brk value.
2465 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2466 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2467 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002468
2469 // Get the current process stack rlimit.
2470 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2471
nethercote71980f02004-01-24 18:18:54 +00002472 //--------------------------------------------------------------
2473 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002474 // p: none
nethercote71980f02004-01-24 18:18:54 +00002475 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002476 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002477 {
sewardj1fbc1a52005-04-25 02:05:54 +00002478 void* init_sp = argv - 1;
2479 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002480 }
2481
2482 //--------------------------------------------------------------
2483 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002484 // p: none
nethercote71980f02004-01-24 18:18:54 +00002485 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002486 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002487 if (cp != NULL)
2488 VG_(libdir) = cp;
2489 }
2490
2491 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002492 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2493 // Pre-process the command line.
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", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002497 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002498 pre_process_cmd_line_options(&need_help, &tool, &exec);
2499
sewardj10759312005-05-30 23:52:47 +00002500 /* If this process was created by exec done by another Valgrind
2501 process, the arguments will only show up at this point. Hence
2502 we need to also snoop around in vg_argv to see if anyone is
2503 asking for debug logging. */
2504 if (loglevel == 0) {
2505 for (i = 1; i < vg_argc; i++) {
2506 if (vg_argv[i][0] != '-')
2507 break;
2508 if (0 == local_strcmp(vg_argv[i], "--"))
2509 break;
2510 if (0 == local_strcmp(vg_argv[i], "-d"))
2511 loglevel++;
2512 }
2513 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2514 }
2515
nethercote71980f02004-01-24 18:18:54 +00002516 //==============================================================
2517 // Nb: once a tool is specified, the tool.so must be loaded even if
2518 // they specified --help or didn't specify a client program.
2519 //==============================================================
2520
2521 //--------------------------------------------------------------
2522 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002523 // p: set-libdir [for VG_(libdir)]
2524 // p: pre_process_cmd_line_options() [for 'tool']
2525 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002526 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002527 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002528
2529 //==============================================================
2530 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002531 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002532 //==============================================================
2533
2534 //--------------------------------------------------------------
2535 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002536 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002537 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002539 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002540
2541 //--------------------------------------------------------------
2542 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002543 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2544 // p: layout_remaining_space [so there's space]
2545 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002546 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002547 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002548
2549 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002550 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002551 // p: layout_remaining_space() [everything must be mapped in before now]
2552 // p: load_client() [ditto]
2553 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002554 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2555 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002556
2557 //--------------------------------------------------------------
2558 // Set up client's environment
2559 // p: set-libdir [for VG_(libdir)]
2560 // p: load_tool() [for 'preload']
2561 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002562 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002563 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002564
2565 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002566 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002567 // p: load_client() [for 'info']
2568 // p: fix_environment() [for 'env']
2569 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002570 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002571 {
sewardj1fbc1a52005-04-25 02:05:54 +00002572 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002573
sewardj1fbc1a52005-04-25 02:05:54 +00002574 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2575 &client_auxv);
2576 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002577 }
nethercote71980f02004-01-24 18:18:54 +00002578
sewardj1fbc1a52005-04-25 02:05:54 +00002579 VG_(debugLog)(2, "main",
2580 "Client info: "
2581 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2582 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2583 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002584
2585 //==============================================================
2586 // Finished setting up operating environment. Now initialise
2587 // Valgrind. (This is where the old VG_(main)() started.)
2588 //==============================================================
2589
2590 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002591 // setup file descriptors
2592 // p: n/a
2593 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002594 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002595 setup_file_descriptors();
2596
2597 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002598 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002599 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002600 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002601 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002602 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2603
2604 //==============================================================
2605 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2606 //==============================================================
2607
2608 //--------------------------------------------------------------
2609 // Init tool: pre_clo_init, process cmd line, post_clo_init
2610 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002611 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002612 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2613 // p: parse_procselfmaps [so VG segments are setup so tool can
2614 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002615 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002616 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002617 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002618 VG_(sanity_check_needs)();
2619
nethercotef4928da2004-06-15 10:54:40 +00002620 // If --tool and --help/--help-debug was given, now give the core+tool
2621 // help message
nethercotef4928da2004-06-15 10:54:40 +00002622 if (need_help) {
2623 usage(/*--help-debug?*/2 == need_help);
2624 }
nethercotec314eba2004-07-15 12:59:41 +00002625 process_cmd_line_options(client_auxv, tool);
2626
njn51d827b2005-05-09 01:02:08 +00002627 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002628
2629 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002630 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002631 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002632 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002633 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002634 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002635 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002636 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002637 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002638 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002639
sewardj21c6d0f2005-05-02 10:33:44 +00002640#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002641 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002642 // Protect client trampoline page (which is also sysinfo stuff)
2643 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002644 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002645 {
2646 Segment *seg;
2647 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2648 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002649
sewardjb5f6f512005-03-10 23:59:00 +00002650 /* Make sure this segment isn't treated as stack */
2651 seg = VG_(find_segment)(VG_(client_trampoline_code));
2652 if (seg)
2653 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2654 }
sewardj21c6d0f2005-05-02 10:33:44 +00002655#endif
sewardjb5f6f512005-03-10 23:59:00 +00002656
nethercotec314eba2004-07-15 12:59:41 +00002657 //==============================================================
2658 // Can use VG_(map)() after segments set up
2659 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002660
2661 //--------------------------------------------------------------
2662 // Allow GDB attach
2663 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2664 //--------------------------------------------------------------
2665 /* Hook to delay things long enough so we can get the pid and
2666 attach GDB in another shell. */
2667 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002668 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002669 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2670 /* jrs 20050206: I don't understand why this works on x86. On
2671 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2672 work. */
2673 /* do "jump *$eip" to skip this in gdb (x86) */
2674 //VG_(do_syscall0)(__NR_pause);
2675 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002676 }
2677
sewardjb5d320c2005-03-13 18:57:15 +00002678 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002679 // Search for file descriptors that are inherited from our parent
2680 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2681 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002682 if (VG_(clo_track_fds)) {
2683 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002684 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002685 }
nethercote71980f02004-01-24 18:18:54 +00002686
2687 //--------------------------------------------------------------
2688 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002689 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2690 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002691 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002692 VG_(scheduler_init)();
2693
2694 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002695 // Initialise the pthread model
2696 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002697 // load_client() [for 'client_eip']
2698 // setup_client_stack() [for 'sp_at_startup']
2699 // setup_scheduler() [for the rest of state 1 stuff]
2700 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002701 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002702 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002703
2704 // Tell the tool that we just wrote to the registers.
2705 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2706 sizeof(VexGuestArchState));
2707
sewardj2a99cf62004-11-24 10:44:19 +00002708 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002709 // Initialise the pthread model
2710 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002711 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002712 //if (VG_(clo_model_pthreads))
2713 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002714
2715 //--------------------------------------------------------------
2716 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002717 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002718 //--------------------------------------------------------------
2719 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002720 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002721 VG_(sigstartup_actions)();
2722
2723 //--------------------------------------------------------------
2724 // Perhaps we're profiling Valgrind?
2725 // p: process_cmd_line_options() [for VG_(clo_profile)]
2726 // p: others?
2727 //
2728 // XXX: this seems to be broken? It always says the tool wasn't built
2729 // for profiling; vg_profile.c's functions don't seem to be overriding
2730 // vg_dummy_profile.c's?
2731 //
2732 // XXX: want this as early as possible. Looking for --profile
2733 // in pre_process_cmd_line_options() could get it earlier.
2734 //--------------------------------------------------------------
2735 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002736 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002737
2738 VGP_PUSHCC(VgpStartup);
2739
2740 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002741 // Read suppression file
2742 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2743 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002744 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2745 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002746 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002747 }
nethercote71980f02004-01-24 18:18:54 +00002748
2749 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002750 // Initialise translation table and translation cache
2751 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2752 // aren't identified as part of the client, which would waste
2753 // > 20M of virtual address space.]
2754 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002755 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002756 VG_(init_tt_tc)();
2757
2758 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002759 // Read debug info to find glibc entry points to intercept
2760 // p: parse_procselfmaps? [XXX for debug info?]
2761 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2762 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002763 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002764 VG_(setup_code_redirect_table)();
2765
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 // Verbosity message
2768 // p: end_rdtsc_calibration [so startup message is printed first]
2769 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002770 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002771 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2772 if (VG_(clo_verbosity) > 0)
2773 VG_(message)(Vg_UserMsg, "");
2774
2775 //--------------------------------------------------------------
2776 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002777 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002778 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2779 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002780 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002781 VG_(clo_pointercheck) =
2782 VGA_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002783
nethercote71980f02004-01-24 18:18:54 +00002784 //--------------------------------------------------------------
2785 // Run!
2786 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002787 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002788
sewardj71bc3cb2005-05-19 00:25:45 +00002789 if (VG_(clo_xml)) {
2790 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2791 VG_(message)(Vg_UserMsg, "");
2792 }
2793
sewardj1fbc1a52005-04-25 02:05:54 +00002794 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002795 /* As a result of the following call, the last thread standing
2796 eventually winds up running VG_(shutdown_actions_NORETURN) just
2797 below. */
2798 VGP_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002799
sewardj1d887112005-05-30 21:44:08 +00002800 /*NOTREACHED*/
2801 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002802}
2803
2804
2805/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002806void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2807 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002808{
sewardj1d887112005-05-30 21:44:08 +00002809 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2810
2811 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002812 vg_assert(VG_(is_running_thread)(tid));
2813
2814 // Wait for all other threads to exit.
2815 VGA_(reap_threads)(tid);
2816
2817 VG_(clo_model_pthreads) = False;
2818
2819 // Clean the client up before the final report
2820 VGA_(final_tidyup)(tid);
2821
2822 // OK, done
2823 VG_(exit_thread)(tid);
2824
2825 /* should be no threads left */
2826 vg_assert(VG_(count_living_threads)() == 0);
2827
2828 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002829 //--------------------------------------------------------------
2830 // Finalisation: cleanup, messages, etc. Order no so important, only
2831 // affects what order the messages come.
2832 //--------------------------------------------------------------
2833 if (VG_(clo_verbosity) > 0)
2834 VG_(message)(Vg_UserMsg, "");
2835
sewardj71bc3cb2005-05-19 00:25:45 +00002836 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002837 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2838 VG_(show_error_counts_as_XML)();
2839 VG_(message)(Vg_UserMsg, "");
2840 }
sewardj71bc3cb2005-05-19 00:25:45 +00002841 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2842 VG_(message)(Vg_UserMsg, "");
2843 }
2844
nethercote71980f02004-01-24 18:18:54 +00002845 /* Print out file descriptor summary and stats. */
2846 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002847 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002848
njn95ec8702004-11-22 16:46:13 +00002849 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002850 VG_(show_all_errors)();
2851
njn51d827b2005-05-09 01:02:08 +00002852 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002853
sewardj71bc3cb2005-05-19 00:25:45 +00002854 if (VG_(clo_xml)) {
2855 VG_(message)(Vg_UserMsg, "");
2856 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2857 VG_(message)(Vg_UserMsg, "");
2858 }
2859
nethercote885dd912004-08-03 23:14:00 +00002860 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002861
2862 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002863 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002864
nethercote71980f02004-01-24 18:18:54 +00002865 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002866 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002867 if (VG_(clo_profile_flags) > 0)
2868 VG_(show_BB_profile)();
2869
sewardj8b635a42004-11-22 19:01:47 +00002870 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002871 if (0)
2872 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002873
2874 /* Ok, finally exit in the os-specific way. In short, if the
2875 (last) thread exited by calling sys_exit, do likewise; if the
2876 (last) thread stopped due to a fatal signal, terminate the
2877 entire system with that same fatal signal. */
2878 VGO_(terminate_NORETURN)( tid, tids_schedretcode );
njne96be672005-05-08 19:08:54 +00002879}
sewardj8b635a42004-11-22 19:01:47 +00002880
sewardjde4a1d02002-03-22 01:27:54 +00002881/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002882/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002883/*--------------------------------------------------------------------*/