blob: dac1c15f5e7edf9ac77d581ca2353cc3cfb4dcc5 [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"
njn04e16982005-05-31 00:23:43 +000039#include "pub_core_main.h"
njn20242342005-05-16 23:31:24 +000040#include "pub_core_options.h"
njnd1af0032005-05-29 17:01:48 +000041#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000042#include "pub_core_signals.h"
njn2521d322005-05-08 14:45:13 +000043#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000044#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000045#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000046
47#include <dirent.h>
48#include <dlfcn.h>
49#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000050#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000051#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000052#include <string.h>
53#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000054#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000055#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000056#include <sys/wait.h>
57#include <unistd.h>
58
sewardjb5f6f512005-03-10 23:59:00 +000059#include "memcheck/memcheck.h"
60
thughes74b8de22004-04-22 18:12:31 +000061#ifndef AT_DCACHEBSIZE
62#define AT_DCACHEBSIZE 19
63#endif /* AT_DCACHEBSIZE */
64
65#ifndef AT_ICACHEBSIZE
66#define AT_ICACHEBSIZE 20
67#endif /* AT_ICACHEBSIZE */
68
69#ifndef AT_UCACHEBSIZE
70#define AT_UCACHEBSIZE 21
71#endif /* AT_UCACHEBSIZE */
72
nethercote71980f02004-01-24 18:18:54 +000073#ifndef AT_SYSINFO
74#define AT_SYSINFO 32
75#endif /* AT_SYSINFO */
76
77#ifndef AT_SYSINFO_EHDR
78#define AT_SYSINFO_EHDR 33
79#endif /* AT_SYSINFO_EHDR */
80
81#ifndef AT_SECURE
82#define AT_SECURE 23 /* secure mode boolean */
83#endif /* AT_SECURE */
84
nethercote71980f02004-01-24 18:18:54 +000085/* redzone gap between client address space and shadow */
86#define REDZONE_SIZE (1 * 1024*1024)
87
88/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000089#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000090
nethercotee2097312004-06-27 12:29:56 +000091/* Proportion of client space for its heap (rest is for mmaps + stack) */
92#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000093
njn14319cc2005-03-13 06:26:22 +000094/* Number of file descriptors that Valgrind tries to reserve for
95 it's own use - just a small constant. */
96#define N_RESERVED_FDS (10)
97
nethercote71980f02004-01-24 18:18:54 +000098/*====================================================================*/
99/*=== Global entities not referenced from generated code ===*/
100/*====================================================================*/
101
sewardjde4a1d02002-03-22 01:27:54 +0000102/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000103 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000104 ------------------------------------------------------------------ */
105
nethercote73b526f2004-10-31 18:48:21 +0000106struct vki_rlimit VG_(client_rlimit_data);
107struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000108
fitzhardinge98abfc72003-12-16 02:05:15 +0000109/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000110static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000111
112/* client executable */
113Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000114
115/* Path to library directory */
116const Char *VG_(libdir) = VG_LIBDIR;
117
118/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000119static Int vg_argc;
120static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000121
thughesad1c9562004-06-26 11:27:52 +0000122/* Application-visible file descriptor limits */
123Int VG_(fd_soft_limit) = -1;
124Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000125
nethercote4ad74312004-10-26 09:59:49 +0000126/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000127 envp[] as extracted from the client's stack at startup-time. */
128Int VG_(client_argc);
129Char** VG_(client_argv);
130Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000131
sewardj51ac0872004-12-21 01:20:49 +0000132
sewardjde4a1d02002-03-22 01:27:54 +0000133/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000134 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000135 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000136
sewardjde4a1d02002-03-22 01:27:54 +0000137/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000138ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000139
sewardj73cf3bc2002-11-03 03:20:15 +0000140
nethercote71980f02004-01-24 18:18:54 +0000141/*====================================================================*/
142/*=== Counters, for profiling purposes only ===*/
143/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000144
sewardjde4a1d02002-03-22 01:27:54 +0000145/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000146static UInt sanity_fast_count = 0;
147static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000148
nethercote3a42fb82004-08-03 18:08:50 +0000149static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000150{
nethercote3a42fb82004-08-03 18:08:50 +0000151 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000152 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000153 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000154 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000155
nethercote3a42fb82004-08-03 18:08:50 +0000156 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000157 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159 VG_(message)(Vg_DebugMsg,
160 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000161 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000162
njn9271cbc2005-03-13 05:38:25 +0000163 VG_(print_ExeContext_stats)();
164
nethercote3a42fb82004-08-03 18:08:50 +0000165 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000166 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000167 VG_(message)(Vg_DebugMsg, "");
168 VG_(message)(Vg_DebugMsg,
169 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000170 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000171 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000172 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000173 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000174 }
nethercote71980f02004-01-24 18:18:54 +0000175}
176
177
178/*====================================================================*/
179/*=== Miscellaneous global functions ===*/
180/*====================================================================*/
181
nethercotecf97ffb2004-09-09 13:40:31 +0000182static Int ptrace_setregs(Int pid, ThreadId tid)
183{
sewardj2a99cf62004-11-24 10:44:19 +0000184 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000185}
186
nethercote04d0fbc2004-01-26 16:48:06 +0000187/* Start debugger and get it to attach to this process. Called if the
188 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000189 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000190 meaningfully get the debugger to continue the program, though; to
191 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000192void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000193{
194 Int pid;
195
196 if ((pid = fork()) == 0) {
197 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000198 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000199
200 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000201 Int status;
202 Int res;
203
nethercote71980f02004-01-24 18:18:54 +0000204 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
205 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000206 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000207 kill(pid, SIGSTOP) == 0 &&
208 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000209 Char pidbuf[15];
210 Char file[30];
211 Char buf[100];
212 Char *bufptr;
213 Char *cmdptr;
214
215 VG_(sprintf)(pidbuf, "%d", pid);
216 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
217
218 bufptr = buf;
219 cmdptr = VG_(clo_db_command);
220
221 while (*cmdptr) {
222 switch (*cmdptr) {
223 case '%':
224 switch (*++cmdptr) {
225 case 'f':
226 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
227 bufptr += VG_(strlen)(file);
228 cmdptr++;
229 break;
230 case 'p':
231 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
232 bufptr += VG_(strlen)(pidbuf);
233 cmdptr++;
234 break;
235 default:
236 *bufptr++ = *cmdptr++;
237 break;
238 }
239 break;
240 default:
241 *bufptr++ = *cmdptr++;
242 break;
243 }
244 }
245
246 *bufptr++ = '\0';
247
248 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000249 res = VG_(system)(buf);
250 if (res == 0) {
251 VG_(message)(Vg_UserMsg, "");
252 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000253 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000254 } else {
255 VG_(message)(Vg_UserMsg, "Apparently failed!");
256 VG_(message)(Vg_UserMsg, "");
257 }
258 }
259
nethercote73b526f2004-10-31 18:48:21 +0000260 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000261 VG_(waitpid)(pid, &status, 0);
262 }
263}
264
265
sewardj2a99cf62004-11-24 10:44:19 +0000266/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000267Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000268{
njncf45fd42004-11-24 16:30:22 +0000269 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000270}
271
njn67516132005-03-22 04:02:43 +0000272Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000273{
274 return INSTR_PTR( VG_(threads)[tid].arch );
275}
276
njnea4b28c2004-11-30 16:04:58 +0000277
nethercote71980f02004-01-24 18:18:54 +0000278/*====================================================================*/
279/*=== Check we were launched by stage 1 ===*/
280/*====================================================================*/
281
282/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000283static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000284{
nethercoteebf1d862004-11-01 18:22:05 +0000285 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000286 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000287
288 for (; auxv->a_type != AT_NULL; auxv++)
289 switch(auxv->a_type) {
290 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000291 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000292 found |= 1;
293 break;
294
295 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000296 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000297 found |= 2;
298 break;
nethercote7f390022004-10-25 17:18:24 +0000299
300 case AT_PHDR:
301 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
302 break;
nethercote71980f02004-01-24 18:18:54 +0000303 }
304
nethercote361a14e2004-07-26 11:11:56 +0000305 if ( found != (1|2) ) {
306 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000307 exit(127);
308 }
nethercote31779c72004-07-30 21:50:15 +0000309 vg_assert(padfile >= 0);
310 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000311}
312
313
314/*====================================================================*/
315/*=== Address space determination ===*/
316/*====================================================================*/
317
nethercote7f390022004-10-25 17:18:24 +0000318extern char _start[];
319
nethercote31779c72004-07-30 21:50:15 +0000320static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000321{
nethercotea3c3cf22004-11-01 18:38:00 +0000322 Int ires;
323 void* vres;
324 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000325
nethercote7f390022004-10-25 17:18:24 +0000326 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
327 // this is a workable approximation
328 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000329 VG_(valgrind_base) = PGROUNDDN(&_start);
330 }
331
nethercote820bd8c2004-09-07 23:04:49 +0000332 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000333
nethercote31779c72004-07-30 21:50:15 +0000334 // This gives the client the largest possible address space while
335 // taking into account the tool's shadow needs.
336 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000337 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000338 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000339 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000340 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000341 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000342 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000343
nethercote31779c72004-07-30 21:50:15 +0000344 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000345 VG_(shadow_end) = VG_(valgrind_base);
346 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000347
nethercotee2097312004-06-27 12:29:56 +0000348#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
349
nethercote71980f02004-01-24 18:18:54 +0000350 if (0)
nethercotee2097312004-06-27 12:29:56 +0000351 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000352 "client_base %p (%dMB)\n"
353 "client_mapbase %p (%dMB)\n"
354 "client_end %p (%dMB)\n"
355 "shadow_base %p (%dMB)\n"
356 "shadow_end %p\n"
357 "valgrind_base %p (%dMB)\n"
358 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000359 VG_(client_base), SEGSIZE(client_base, client_mapbase),
360 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
361 VG_(client_end), SEGSIZE(client_end, shadow_base),
362 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000363 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000364 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
365 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000366 );
367
368#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000369
370 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000371 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000372 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000373 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000374
375 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000376 ires = munmap((void*)VG_(client_base), client_size);
377 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000378
379 // Map shadow memory.
380 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000381 if (shadow_size != 0) {
382 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000383 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000384 if ((void*)-1 == vres) {
385 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000386 "valgrind: Could not allocate address space (%p bytes)\n"
387 "valgrind: for shadow memory\n"
388 "valgrind: Possible causes:\n"
389 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
390 "valgrind: needs at least 1.5GB swap space.\n"
391 "valgrind: - Or, your virtual memory size may be limited (check\n"
392 "valgrind: with 'ulimit -v').\n"
393 "valgrind: - Or, your system may use a kernel that provides only a\n"
394 "valgrind: too-small (eg. 2GB) user address space.\n"
395 , (void*)shadow_size
396 );
nethercoted4722622004-08-30 19:36:42 +0000397 exit(1);
398 }
nethercotee567e702004-07-10 17:49:17 +0000399 }
nethercote71980f02004-01-24 18:18:54 +0000400}
401
402/*====================================================================*/
403/*=== Command line setup ===*/
404/*====================================================================*/
405
nethercote71980f02004-01-24 18:18:54 +0000406static char* get_file_clo(char* dir)
407{
408# define FLEN 512
409 Int fd, n;
410 struct stat s1;
411 char* f_clo = NULL;
412 char filename[FLEN];
413
414 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
415 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
416 if ( fd > 0 ) {
417 if ( 0 == fstat(fd, &s1) ) {
418 f_clo = malloc(s1.st_size+1);
419 vg_assert(f_clo);
420 n = read(fd, f_clo, s1.st_size);
421 if (n == -1) n = 0;
422 f_clo[n] = '\0';
423 }
424 close(fd);
425 }
426 return f_clo;
427# undef FLEN
428}
429
430static Int count_args(char* s)
431{
432 Int n = 0;
433 if (s) {
434 char* cp = s;
435 while (True) {
436 // We have alternating sequences: blanks, non-blanks, blanks...
437 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000438 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000439 if ( !*cp ) break;
440 n++;
njn0c0f32a2005-03-26 04:14:01 +0000441 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000442 }
443 }
444 return n;
445}
446
447/* add args out of environment, skipping multiple spaces and -- args */
448static char** copy_args( char* s, char** to )
449{
450 if (s) {
451 char* cp = s;
452 while (True) {
453 // We have alternating sequences: blanks, non-blanks, blanks...
454 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000455 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000456 if ( !*cp ) break;
457 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000458 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000459 if ( *cp ) *cp++ = '\0'; // terminate if necessary
460 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
461 }
462 }
463 return to;
464}
465
466// Augment command line with arguments from environment and .valgrindrc
467// files.
468static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
469{
nethercotef6a1d502004-08-09 12:21:57 +0000470 int vg_argc0 = *vg_argc_inout;
471 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000472
473 char* env_clo = getenv(VALGRINDOPTS);
474 char* f1_clo = get_file_clo( getenv("HOME") );
475 char* f2_clo = get_file_clo(".");
476
477 /* copy any extra args from file or environment, if present */
478 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
479 /* ' ' separated extra options */
480 char **from;
481 char **to;
thughescaca0022004-09-13 10:20:34 +0000482 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
483
484 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
485
nethercote71980f02004-01-24 18:18:54 +0000486 env_arg_count = count_args(env_clo);
487 f1_arg_count = count_args(f1_clo);
488 f2_arg_count = count_args(f2_clo);
489
490 if (0)
491 printf("extra-argc=%d %d %d\n",
492 env_arg_count, f1_arg_count, f2_arg_count);
493
494 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000495 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000496 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000497 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000498 vg_assert(vg_argv0);
499 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000500
501 /* copy argv[0] */
502 *to++ = *from++;
503
504 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
505 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
506 * to override less local ones. */
507 to = copy_args(f1_clo, to);
508 to = copy_args(env_clo, to);
509 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000510
511 // Free memory
512 free(f1_clo);
513 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000514
515 /* copy original arguments, stopping at command or -- */
516 while (*from) {
517 if (**from != '-')
518 break;
519 if (VG_STREQ(*from, "--")) {
520 from++; /* skip -- */
521 break;
522 }
523 *to++ = *from++;
524 }
525
526 /* add -- */
527 *to++ = "--";
528
nethercotef6a1d502004-08-09 12:21:57 +0000529 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000530
531 /* copy rest of original command line, then NULL */
532 while (*from) *to++ = *from++;
533 *to = NULL;
534 }
535
nethercotef6a1d502004-08-09 12:21:57 +0000536 *vg_argc_inout = vg_argc0;
537 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000538}
539
nethercotef6a1d502004-08-09 12:21:57 +0000540#define VG_CLO_SEP '\01'
541
nethercote71980f02004-01-24 18:18:54 +0000542static void get_command_line( int argc, char** argv,
543 Int* vg_argc_out, Char*** vg_argv_out,
544 char*** cl_argv_out )
545{
nethercotef6a1d502004-08-09 12:21:57 +0000546 int vg_argc0;
547 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000548 char** cl_argv;
549 char* env_clo = getenv(VALGRINDCLO);
550
551 if (env_clo != NULL && *env_clo != '\0') {
552 char *cp;
553 char **cpp;
554
nethercotef6a1d502004-08-09 12:21:57 +0000555 /* OK, VALGRINDCLO is set, which means we must be a child of another
556 Valgrind process using --trace-children, so we're getting all our
557 arguments from VALGRINDCLO, and the entire command line belongs to
558 the client (including argv[0]) */
559 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000560 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000561 if (*cp == VG_CLO_SEP)
562 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000563
nethercotef6a1d502004-08-09 12:21:57 +0000564 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
565 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000566
nethercotef6a1d502004-08-09 12:21:57 +0000567 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000568
569 *cpp++ = "valgrind"; /* nominal argv[0] */
570 *cpp++ = env_clo;
571
nethercotef6a1d502004-08-09 12:21:57 +0000572 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000573 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000574 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000575 *cp++ = '\0'; /* chop it up in place */
576 *cpp++ = cp;
577 }
578 }
579 *cpp = NULL;
580 cl_argv = argv;
581
582 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000583 Bool noaugment = False;
584
nethercote71980f02004-01-24 18:18:54 +0000585 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000586 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000587
nethercotef6a1d502004-08-09 12:21:57 +0000588 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000589 Char* arg = argv[vg_argc0];
590 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000591 break;
sewardjb5f6f512005-03-10 23:59:00 +0000592 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000593 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000594 break;
595 }
njn45270a22005-03-27 01:00:11 +0000596 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000597 }
nethercotef6a1d502004-08-09 12:21:57 +0000598 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000599
600 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000601 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000602 those extra args will already be present in VALGRINDCLO.
603 (We also don't do it when --command-line-only=yes.) */
604 if (!noaugment)
605 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000606 }
607
608 if (0) {
609 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000610 for (i = 0; i < vg_argc0; i++)
611 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000612 }
613
nethercotef6a1d502004-08-09 12:21:57 +0000614 *vg_argc_out = vg_argc0;
615 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000616 *cl_argv_out = cl_argv;
617}
618
619
620/*====================================================================*/
621/*=== Environment and stack setup ===*/
622/*====================================================================*/
623
624/* Scan a colon-separated list, and call a function on each element.
625 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000626 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000627 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000628
629 This routine will return True if (*func) returns True and False if
630 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000631*/
thughes4ad52d02004-06-27 17:37:21 +0000632static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000633{
634 char *cp, *entry;
635 int end;
636
637 if (colsep == NULL ||
638 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000639 return False;
nethercote71980f02004-01-24 18:18:54 +0000640
641 entry = cp = colsep;
642
643 do {
644 end = (*cp == '\0');
645
646 if (*cp == ':' || *cp == '\0') {
647 char save = *cp;
648
649 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000650 if ((*func)(entry)) {
651 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000652 return True;
thughes21942d92004-07-12 09:35:37 +0000653 }
nethercote71980f02004-01-24 18:18:54 +0000654 *cp = save;
655 entry = cp+1;
656 }
657 cp++;
658 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000659
660 return False;
661}
662
nethercote71980f02004-01-24 18:18:54 +0000663/* Prepare the client's environment. This is basically a copy of our
664 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000665 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000666
sewardjb5f6f512005-03-10 23:59:00 +0000667 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000668
669 Yummy. String hacking in C.
670
671 If this needs to handle any more variables it should be hacked
672 into something table driven.
673 */
674static char **fix_environment(char **origenv, const char *preload)
675{
676 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000677 static const char ld_preload[] = "LD_PRELOAD=";
678 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000679 static const int ld_preload_len = sizeof(ld_preload)-1;
680 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
681 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000682 char *inject_path;
683 int inject_path_len;
684 int vgliblen = strlen(VG_(libdir));
685 char **cpp;
686 char **ret;
687 int envc;
688 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
689
690 /* Find the vg_inject.so; also make room for the tool preload
691 library */
692 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
693 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000694 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000695
696 if (preload)
697 snprintf(inject_path, inject_path_len, "%s/%s:%s",
698 VG_(libdir), inject_so, preload);
699 else
700 snprintf(inject_path, inject_path_len, "%s/%s",
701 VG_(libdir), inject_so);
702
703 /* Count the original size of the env */
704 envc = 0; /* trailing NULL */
705 for (cpp = origenv; cpp && *cpp; cpp++)
706 envc++;
707
708 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000709 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000710 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000711
712 /* copy it over */
713 for (cpp = ret; *origenv; )
714 *cpp++ = *origenv++;
715 *cpp = NULL;
716
717 vg_assert(envc == (cpp - ret));
718
719 /* Walk over the new environment, mashing as we go */
720 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000721 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000722 int len = strlen(*cpp) + inject_path_len;
723 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000724 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000725
726 snprintf(cp, len, "%s%s:%s",
727 ld_preload, inject_path, (*cpp)+ld_preload_len);
728
729 *cpp = cp;
730
731 ld_preload_done = 1;
732 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
733 *cpp = "";
734 }
735 }
736
737 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000738 if (!ld_preload_done) {
739 int len = ld_preload_len + inject_path_len;
740 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000741 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000742
743 snprintf(cp, len, "%s%s",
744 ld_preload, inject_path);
745
746 ret[envc++] = cp;
747 }
748
sewardjb5f6f512005-03-10 23:59:00 +0000749 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000750 ret[envc] = NULL;
751
752 return ret;
753}
754
755extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000756
757/* Add a string onto the string table, and return its address */
758static char *copy_str(char **tab, const char *str)
759{
760 char *cp = *tab;
761 char *orig = cp;
762
763 while(*str)
764 *cp++ = *str++;
765 *cp++ = '\0';
766
767 if (0)
nethercote545fe672004-11-01 16:52:43 +0000768 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000769
770 *tab = cp;
771
772 return orig;
773}
774
775/*
776 This sets up the client's initial stack, containing the args,
777 environment and aux vector.
778
779 The format of the stack is:
780
781 higher address +-----------------+
782 | Trampoline code |
783 +-----------------+
784 | |
785 : string table :
786 | |
787 +-----------------+
788 | AT_NULL |
789 - -
790 | auxv |
791 +-----------------+
792 | NULL |
793 - -
794 | envp |
795 +-----------------+
796 | NULL |
797 - -
798 | argv |
799 +-----------------+
800 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000801 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000802 | undefined |
803 : :
804 */
nethercotec25c4492004-10-18 11:52:17 +0000805static Addr setup_client_stack(void* init_sp,
806 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000807 const struct exeinfo *info,
808 UInt** client_auxv)
809{
nethercotee567e702004-07-10 17:49:17 +0000810 void* res;
nethercote71980f02004-01-24 18:18:54 +0000811 char **cpp;
812 char *strtab; /* string table */
813 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000814 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000815 struct ume_auxv *auxv;
816 const struct ume_auxv *orig_auxv;
817 const struct ume_auxv *cauxv;
818 unsigned stringsize; /* total size of strings in bytes */
819 unsigned auxsize; /* total size of auxv in bytes */
820 int argc; /* total argc */
821 int envc; /* total number of env vars */
822 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000823 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000824
825 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000826 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000827
828 /* ==================== compute sizes ==================== */
829
830 /* first of all, work out how big the client stack will be */
831 stringsize = 0;
832
833 /* paste on the extra args if the loader needs them (ie, the #!
834 interpreter and its argument) */
835 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000836 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000837 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000838 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000839 }
nethercoted6a56872004-07-26 15:32:47 +0000840 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000841 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000842 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000843 }
844
845 /* now scan the args we're given... */
846 for (cpp = orig_argv; *cpp; cpp++) {
847 argc++;
848 stringsize += strlen(*cpp) + 1;
849 }
850
851 /* ...and the environment */
852 envc = 0;
853 for (cpp = orig_envp; cpp && *cpp; cpp++) {
854 envc++;
855 stringsize += strlen(*cpp) + 1;
856 }
857
858 /* now, how big is the auxv? */
859 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
860 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
861 if (cauxv->a_type == AT_PLATFORM)
862 stringsize += strlen(cauxv->u.a_ptr) + 1;
863 auxsize += sizeof(*cauxv);
864 }
865
866 /* OK, now we know how big the client stack is */
867 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000868 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000869 sizeof(char **)*argc + /* argv */
870 sizeof(char **) + /* terminal NULL */
871 sizeof(char **)*envc + /* envp */
872 sizeof(char **) + /* terminal NULL */
873 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000874 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000875 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000876
sewardj79048ce2005-02-18 08:28:32 +0000877 if (0) VG_(printf)("stacksize = %d\n", stacksize);
878
nethercotef84f6952004-07-15 14:58:33 +0000879 // decide where stack goes!
880 VG_(clstk_end) = VG_(client_end);
881
nethercote73b526f2004-10-31 18:48:21 +0000882 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000883
nethercote71980f02004-01-24 18:18:54 +0000884 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000885 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000886 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
887
nethercote71980f02004-01-24 18:18:54 +0000888 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000889 stringbase = strtab = (char *)(VG_(client_trampoline_code)
890 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000891
892 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000893
sewardj79048ce2005-02-18 08:28:32 +0000894 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000895 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000896 "clstk_base %p\n"
897 "clstk_end %p\n",
898 stringsize, auxsize, stacksize,
899 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000900
nethercote71980f02004-01-24 18:18:54 +0000901 /* ==================== allocate space ==================== */
902
903 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000904 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000905 PROT_READ | PROT_WRITE | PROT_EXEC,
906 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
907 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000908
909 /* ==================== copy client stack ==================== */
910
nethercotea3c3cf22004-11-01 18:38:00 +0000911 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000912
913 /* --- argc --- */
914 *ptr++ = argc; /* client argc */
915
916 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000917 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000918 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000919 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000920 }
nethercoted6a56872004-07-26 15:32:47 +0000921 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000922 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000923 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000924 }
925 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000926 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000927 }
928 *ptr++ = 0;
929
930 /* --- envp --- */
931 VG_(client_envp) = (Char **)ptr;
932 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000933 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000934 *ptr++ = 0;
935
936 /* --- auxv --- */
937 auxv = (struct ume_auxv *)ptr;
938 *client_auxv = (UInt *)auxv;
939
940 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
941 /* copy the entry... */
942 *auxv = *orig_auxv;
943
944 /* ...and fix up the copy */
945 switch(auxv->a_type) {
946 case AT_PHDR:
947 if (info->phdr == 0)
948 auxv->a_type = AT_IGNORE;
949 else
950 auxv->u.a_val = info->phdr;
951 break;
952
953 case AT_PHNUM:
954 if (info->phdr == 0)
955 auxv->a_type = AT_IGNORE;
956 else
957 auxv->u.a_val = info->phnum;
958 break;
959
960 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000961 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000962 break;
963
964 case AT_PLATFORM: /* points to a platform description string */
965 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
966 break;
967
968 case AT_ENTRY:
969 auxv->u.a_val = info->entry;
970 break;
971
972 case AT_IGNORE:
973 case AT_EXECFD:
974 case AT_PHENT:
975 case AT_PAGESZ:
976 case AT_FLAGS:
977 case AT_NOTELF:
978 case AT_UID:
979 case AT_EUID:
980 case AT_GID:
981 case AT_EGID:
982 case AT_CLKTCK:
983 case AT_HWCAP:
984 case AT_FPUCW:
985 case AT_DCACHEBSIZE:
986 case AT_ICACHEBSIZE:
987 case AT_UCACHEBSIZE:
988 /* All these are pointerless, so we don't need to do anything
989 about them. */
990 break;
991
992 case AT_SECURE:
993 /* If this is 1, then it means that this program is running
994 suid, and therefore the dynamic linker should be careful
995 about LD_PRELOAD, etc. However, since stage1 (the thing
996 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000997 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000998 set AT_SECURE to 0. */
999 auxv->u.a_val = 0;
1000 break;
1001
1002 case AT_SYSINFO:
1003 /* Leave this unmolested for now, but we'll update it later
1004 when we set up the client trampoline code page */
1005 break;
1006
1007 case AT_SYSINFO_EHDR:
1008 /* Trash this, because we don't reproduce it */
1009 auxv->a_type = AT_IGNORE;
1010 break;
1011
1012 default:
1013 /* stomp out anything we don't know about */
1014 if (0)
nethercote545fe672004-11-01 16:52:43 +00001015 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001016 auxv->a_type = AT_IGNORE;
1017 break;
1018
1019 }
1020 }
1021 *auxv = *orig_auxv;
1022 vg_assert(auxv->a_type == AT_NULL);
1023
njnc6168192004-11-29 13:54:10 +00001024// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1025// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001026#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001027 /* --- trampoline page --- */
1028 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1029 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001030#endif
nethercotef84f6952004-07-15 14:58:33 +00001031
nethercote71980f02004-01-24 18:18:54 +00001032 vg_assert((strtab-stringbase) == stringsize);
1033
nethercote5ee67ca2004-06-22 14:00:09 +00001034 /* We know the initial ESP is pointing at argc/argv */
1035 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001036 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001037
sewardj79048ce2005-02-18 08:28:32 +00001038 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001039 return cl_esp;
1040}
1041
1042/*====================================================================*/
1043/*=== Find executable ===*/
1044/*====================================================================*/
1045
thughes4ad52d02004-06-27 17:37:21 +00001046static const char* executable_name;
1047
1048static Bool match_executable(const char *entry) {
1049 char buf[strlen(entry) + strlen(executable_name) + 2];
1050
1051 /* empty PATH element means . */
1052 if (*entry == '\0')
1053 entry = ".";
1054
1055 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1056
1057 if (access(buf, R_OK|X_OK) == 0) {
1058 executable_name = strdup(buf);
1059 vg_assert(NULL != executable_name);
1060 return True;
1061 }
1062 return False;
1063}
1064
nethercote71980f02004-01-24 18:18:54 +00001065static const char* find_executable(const char* exec)
1066{
1067 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001068 executable_name = exec;
1069 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001070 /* no '/' - we need to search the path */
1071 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001072 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001073 }
thughes4ad52d02004-06-27 17:37:21 +00001074 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001075}
1076
1077
1078/*====================================================================*/
1079/*=== Loading tools ===*/
1080/*====================================================================*/
1081
1082static void list_tools(void)
1083{
1084 DIR *dir = opendir(VG_(libdir));
1085 struct dirent *de;
1086 int first = 1;
1087
1088 if (dir == NULL) {
1089 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001090 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001091 return;
1092 }
1093
nethercotef4928da2004-06-15 10:54:40 +00001094 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001095 int len = strlen(de->d_name);
1096
njn063c5402004-11-22 16:58:05 +00001097 /* look for vgtool_TOOL.so names */
1098 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1099 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001100 VG_STREQ(de->d_name + len - 3, ".so")) {
1101 if (first) {
1102 fprintf(stderr, "Available tools:\n");
1103 first = 0;
1104 }
1105 de->d_name[len-3] = '\0';
1106 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001107 }
1108 }
1109
1110 closedir(dir);
1111
1112 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001113 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1114 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001115}
1116
1117
1118/* Find and load a tool, and check it looks ok. Also looks to see if there's
1119 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001120static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001121 ToolInfo** toolinfo_out, char **preloadpath_out )
1122{
1123 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001124 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001125 char buf[len];
1126 void* handle;
1127 ToolInfo* toolinfo;
1128 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001129
1130 // XXX: allowing full paths for --tool option -- does it make sense?
1131 // Doesn't allow for vgpreload_<tool>.so.
1132
1133 if (strchr(toolname, '/') != 0) {
1134 /* toolname contains '/', and so must be a pathname */
1135 handle = dlopen(toolname, RTLD_NOW);
1136 } else {
1137 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001138 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001139 handle = dlopen(buf, RTLD_NOW);
1140
1141 if (handle != NULL) {
1142 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1143 if (access(buf, R_OK) == 0) {
1144 preloadpath = strdup(buf);
1145 vg_assert(NULL != preloadpath);
1146 }
1147 }
1148 }
1149
1150 ok = (NULL != handle);
1151 if (!ok) {
1152 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1153 goto bad_load;
1154 }
1155
njn51d827b2005-05-09 01:02:08 +00001156 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001157 ok = (NULL != toolinfo);
1158 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001159 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001160 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1161 goto bad_load;
1162 }
1163
1164 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001165 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1166 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001167 if (!ok) {
1168 fprintf(stderr, "Error:\n"
1169 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001170 " Interface version used by core is: %d (size %d)\n"
1171 " Interface version used by tool is: %d (size %d)\n"
1172 " The version numbers must match.\n",
1173 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001174 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001175 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001176 toolinfo->sizeof_ToolInfo);
1177 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001178 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001179 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001180 else
nethercote996901a2004-08-03 13:29:09 +00001181 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001182 goto bad_load;
1183 }
1184
njn8a97c6d2005-03-31 04:37:24 +00001185 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001186 *toolinfo_out = toolinfo;
1187 *preloadpath_out = preloadpath;
1188 return;
1189
1190
1191 bad_load:
1192 if (handle != NULL)
1193 dlclose(handle);
1194
nethercotef4928da2004-06-15 10:54:40 +00001195 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001196 list_tools();
1197 exit(127);
1198}
1199
nethercotef4928da2004-06-15 10:54:40 +00001200
1201/*====================================================================*/
1202/*=== Command line errors ===*/
1203/*====================================================================*/
1204
njnbe9b47b2005-05-15 16:22:58 +00001205static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001206{
njnbe9b47b2005-05-15 16:22:58 +00001207 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001208 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001209}
1210
1211void VG_(bad_option) ( Char* opt )
1212{
njnbe9b47b2005-05-15 16:22:58 +00001213 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001214 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001215 VG_(printf)("valgrind: Use --help for more information.\n");
1216 VG_(exit)(1);
1217}
1218
nethercotef4928da2004-06-15 10:54:40 +00001219static void missing_prog ( void )
1220{
njnbe9b47b2005-05-15 16:22:58 +00001221 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001222 VG_(printf)("valgrind: no program specified\n");
1223 VG_(printf)("valgrind: Use --help for more information.\n");
1224 VG_(exit)(1);
1225}
1226
1227static void config_error ( Char* msg )
1228{
njnbe9b47b2005-05-15 16:22:58 +00001229 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001230 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1231 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1232 VG_(exit)(1);
1233}
1234
1235
nethercote71980f02004-01-24 18:18:54 +00001236/*====================================================================*/
1237/*=== Loading the client ===*/
1238/*====================================================================*/
1239
nethercotef4928da2004-06-15 10:54:40 +00001240static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001241 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1242{
1243 // If they didn't specify an executable with --exec, and didn't specify
1244 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001245 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001246 if (cl_argv[0] == NULL ||
1247 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1248 {
nethercotef4928da2004-06-15 10:54:40 +00001249 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001250 }
1251 }
1252
1253 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001254 info->exe_base = VG_(client_base);
1255 info->exe_end = VG_(client_end);
1256 info->argv = cl_argv;
1257
nethercotef4928da2004-06-15 10:54:40 +00001258 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001259 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001260 // Totally zero 'info' before continuing.
1261 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001262 } else {
1263 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001264 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001265 ret = do_exec(exec, info);
1266 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001267 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1268 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001269 exit(127);
1270 }
1271 }
1272
1273 /* Copy necessary bits of 'info' that were filled in */
1274 *client_eip = info->init_eip;
1275 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1276}
1277
nethercote969ecf12004-10-13 17:29:01 +00001278/*====================================================================*/
1279/*=== Address space unpadding ===*/
1280/*====================================================================*/
1281
1282typedef struct {
1283 char* killpad_start;
1284 char* killpad_end;
1285 struct stat* killpad_padstat;
1286} killpad_extra;
1287
1288static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1289 int maj, int min, int ino, void* ex)
1290{
1291 killpad_extra* extra = ex;
1292 void *b, *e;
1293 int res;
1294
1295 vg_assert(NULL != extra->killpad_padstat);
1296
1297 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1298 extra->killpad_padstat->st_ino != ino)
1299 return 1;
1300
1301 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1302 return 1;
1303
1304 if (segstart <= extra->killpad_start)
1305 b = extra->killpad_start;
1306 else
1307 b = segstart;
1308
1309 if (segend >= extra->killpad_end)
1310 e = extra->killpad_end;
1311 else
1312 e = segend;
1313
1314 res = munmap(b, (char *)e-(char *)b);
1315 vg_assert(0 == res);
1316
1317 return 1;
1318}
1319
1320// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001321static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001322{
1323 static struct stat padstat;
1324 killpad_extra extra;
1325 int res;
1326
sewardjb5f6f512005-03-10 23:59:00 +00001327 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001328
1329 res = fstat(padfile, &padstat);
1330 vg_assert(0 == res);
1331 extra.killpad_padstat = &padstat;
1332 extra.killpad_start = start;
1333 extra.killpad_end = end;
1334 foreach_map(killpad, &extra);
1335}
1336
sewardj2c5ffbe2005-03-12 13:32:06 +00001337static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001338{
1339 int res = close(padfile);
1340 vg_assert(0 == res);
1341}
1342
sewardj71bc3cb2005-05-19 00:25:45 +00001343/*====================================================================*/
1344/*=== Command-line: variables, processing, etc ===*/
1345/*====================================================================*/
1346
1347// See pub_{core,tool}_options.h for explanations of all these.
1348
sewardj2c5ffbe2005-03-12 13:32:06 +00001349static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001350{
njn25e49d8e72002-09-23 09:36:25 +00001351 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001352"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001353"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001354" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001355" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001356" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001357" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001358" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001359" -q --quiet run silently; only print error msgs\n"
1360" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001361" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001362" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001363" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001364" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001365"\n"
1366" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001367" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001368" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001369" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001370" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001371" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001372"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001373" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001374" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1375" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001376" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001377" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001378" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001379" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001380" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1381" --show-below-main=no|yes continue stack traces below main() [no]\n"
1382" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001383" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001384" --db-attach=no|yes start debugger when errors detected? [no]\n"
1385" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1386" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001387" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1388" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001389"\n";
njn7cf0bd32002-06-08 13:36:03 +00001390
njn25e49d8e72002-09-23 09:36:25 +00001391 Char* usage2 =
1392"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001393" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001394" --sanity-level=<number> level of sanity checking to do [1]\n"
1395" --single-step=no|yes translate each instr separately? [no]\n"
1396" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001397" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001398" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001399" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1400" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001401" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001402" --trace-syscalls=no|yes show all system calls? [no]\n"
1403" --trace-signals=no|yes show signal handling details? [no]\n"
1404" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001405" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001406" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001407" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001408#if 0
1409" --model-pthreads=yes|no model the pthreads library [no]\n"
1410#endif
1411" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001412"\n"
1413" --vex-iropt-verbosity 0 .. 9 [0]\n"
1414" --vex-iropt-level 0 .. 2 [2]\n"
1415" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001416" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1417" --vex-guest-max-insns 1 .. 100 [50]\n"
1418" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1419"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001420" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001421" 1000 0000 show conversion into IR\n"
1422" 0100 0000 show after initial opt\n"
1423" 0010 0000 show after instrumentation\n"
1424" 0001 0000 show after second opt\n"
1425" 0000 1000 show after tree building\n"
1426" 0000 0100 show selecting insns\n"
1427" 0000 0010 show after reg-alloc\n"
1428" 0000 0001 show final assembly\n"
1429"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001430" debugging options for Valgrind tools that report errors\n"
1431" --dump-error=<number> show translation for basic block associated\n"
1432" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001433"\n";
njn3e884182003-04-15 13:03:23 +00001434
1435 Char* usage3 =
1436"\n"
nethercote71980f02004-01-24 18:18:54 +00001437" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001438"\n"
njn53612422005-03-12 16:22:54 +00001439" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001440" and licensed under the GNU General Public License, version 2.\n"
1441" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001442"\n"
nethercote137bc552003-11-14 17:47:54 +00001443" Tools are copyright and licensed by their authors. See each\n"
1444" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001445"\n";
njn7cf0bd32002-06-08 13:36:03 +00001446
njnbe9b47b2005-05-15 16:22:58 +00001447 // Ensure the message goes to stdout
1448 VG_(clo_log_fd) = 1;
1449 vg_assert( !VG_(logging_to_socket) );
1450
fitzhardinge98abfc72003-12-16 02:05:15 +00001451 VG_(printf)(usage1);
1452 if (VG_(details).name) {
1453 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001454 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001455 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001456 else
1457 VG_(printf)(" (none)\n");
1458 }
nethercote6c999f22004-01-31 22:55:15 +00001459 if (debug_help) {
1460 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001461
nethercote6c999f22004-01-31 22:55:15 +00001462 if (VG_(details).name) {
1463 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1464
1465 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001466 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001467 else
1468 VG_(printf)(" (none)\n");
1469 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001470 }
nethercote421281e2003-11-20 16:20:55 +00001471 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001472 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001473}
sewardjde4a1d02002-03-22 01:27:54 +00001474
nethercote71980f02004-01-24 18:18:54 +00001475static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001476 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001477{
nethercote71980f02004-01-24 18:18:54 +00001478 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001479
sewardj8b635a42004-11-22 19:01:47 +00001480 LibVEX_default_VexControl(& VG_(clo_vex_control));
1481
nethercote71980f02004-01-24 18:18:54 +00001482 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001483 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001484
nethercotef6a1d502004-08-09 12:21:57 +00001485 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001486 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001487 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001488
nethercotef6a1d502004-08-09 12:21:57 +00001489 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1490 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001491 *need_help = 1;
1492
nethercotef6a1d502004-08-09 12:21:57 +00001493 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001494 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001495
nethercotef6c99d72004-11-09 14:35:43 +00001496 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001497 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001498
nethercotef6a1d502004-08-09 12:21:57 +00001499 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1500 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001501 }
1502 }
nethercote71980f02004-01-24 18:18:54 +00001503}
1504
nethercote5ee67ca2004-06-22 14:00:09 +00001505static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001506{
nethercotef8548672004-06-21 12:42:35 +00001507 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001508 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001509 enum {
1510 VgLogTo_Fd,
1511 VgLogTo_File,
1512 VgLogTo_FileExactly,
1513 VgLogTo_Socket
1514 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001515
nethercotee1730692003-11-20 10:38:07 +00001516 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001517 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001518
sewardj19d81412002-06-03 01:10:40 +00001519 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001520 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001521 config_error("Please use absolute paths in "
1522 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001523
njnc6168192004-11-29 13:54:10 +00001524// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001525#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001526 {
sewardjb5f6f512005-03-10 23:59:00 +00001527 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001528 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1529 switch(auxp[0]) {
1530 case AT_SYSINFO:
1531 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1532 break;
1533 }
1534 }
1535 }
1536#endif
sewardjde4a1d02002-03-22 01:27:54 +00001537
nethercotef6a1d502004-08-09 12:21:57 +00001538 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001539
nethercotef6a1d502004-08-09 12:21:57 +00001540 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001541 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001542
thughes3bfd5a02004-07-18 08:05:44 +00001543 /* Look for a colon in the switch name */
1544 while (*colon && *colon != ':' && *colon != '=')
1545 colon++;
nethercote71980f02004-01-24 18:18:54 +00001546
1547 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001548 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001549 if (VG_CLO_STREQN(2, arg, "--") &&
1550 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1551 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1552 {
1553 // prefix matches, convert "--toolname:foo" to "--foo"
1554 if (0)
1555 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001556 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001557 arg[0] = '-';
1558 arg[1] = '-';
1559
1560 } else {
1561 // prefix doesn't match, skip to next arg
1562 continue;
1563 }
1564 }
1565
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001567 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1568 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1569 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001570
njn45270a22005-03-27 01:00:11 +00001571 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001572
nethercote71980f02004-01-24 18:18:54 +00001573 else if (VG_CLO_STREQ(arg, "-v") ||
1574 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001575 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001576
nethercote71980f02004-01-24 18:18:54 +00001577 else if (VG_CLO_STREQ(arg, "-q") ||
1578 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001579 VG_(clo_verbosity)--;
1580
sewardj1cf558c2005-04-25 01:36:56 +00001581 else if (VG_CLO_STREQ(arg, "-d")) {
1582 /* do nothing */
1583 }
1584
sewardj71bc3cb2005-05-19 00:25:45 +00001585 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001586 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1587 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1588 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1589 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1590 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1591 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1592 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001593 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001594 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1595 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1596 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1597 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1598 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1599 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1600 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1601 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1602 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001603 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001604 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1605 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1606 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1607 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1608 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001609
njn45270a22005-03-27 01:00:11 +00001610 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1611 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001612
njn45270a22005-03-27 01:00:11 +00001613 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1614 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1615 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1616 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1617 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001618
njn45270a22005-03-27 01:00:11 +00001619 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001620 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001621 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001622 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001623 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001624 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001625 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001626 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001627 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001628 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001629 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001630 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1631
nethercotef8548672004-06-21 12:42:35 +00001632 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001633 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001634 VG_(clo_log_name) = NULL;
1635 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001636 }
1637
nethercotef8548672004-06-21 12:42:35 +00001638 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001639 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001640 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001641 }
njnd6bc3c32005-03-27 00:44:31 +00001642
sewardj603d4102005-01-11 14:01:02 +00001643 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001644 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001645 VG_(clo_log_name) = &arg[19];
1646 }
sewardjde4a1d02002-03-22 01:27:54 +00001647
nethercotef8548672004-06-21 12:42:35 +00001648 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001649 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001650 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001651 }
1652
nethercote71980f02004-01-24 18:18:54 +00001653 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001654 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001655 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001656 VG_(message)(Vg_UserMsg,
1657 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001658 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001659 }
nethercote71980f02004-01-24 18:18:54 +00001660 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001661 VG_(clo_n_suppressions)++;
1662 }
sewardjde4a1d02002-03-22 01:27:54 +00001663
sewardjfa8ec112005-01-19 11:55:34 +00001664 /* "stuvwxyz" --> stuvwxyz (binary) */
1665 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1666 Int j;
1667 char* opt = & arg[14];
1668
1669 if (8 != VG_(strlen)(opt)) {
1670 VG_(message)(Vg_UserMsg,
1671 "--trace-flags argument must have 8 digits");
1672 VG_(bad_option)(arg);
1673 }
1674 for (j = 0; j < 8; j++) {
1675 if ('0' == opt[j]) { /* do nothing */ }
1676 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1677 else {
1678 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1679 "contain 0s and 1s");
1680 VG_(bad_option)(arg);
1681 }
1682 }
1683 }
1684
1685 /* "stuvwxyz" --> stuvwxyz (binary) */
1686 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001687 Int j;
nethercote71980f02004-01-24 18:18:54 +00001688 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001689
sewardj2a99cf62004-11-24 10:44:19 +00001690 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001691 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001692 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001693 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001694 }
sewardj8b635a42004-11-22 19:01:47 +00001695 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001696 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001697 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001698 else {
sewardjfa8ec112005-01-19 11:55:34 +00001699 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001700 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001701 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001702 }
1703 }
1704 }
sewardjde4a1d02002-03-22 01:27:54 +00001705
njn45270a22005-03-27 01:00:11 +00001706 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001707
sewardjd153fae2005-01-10 17:24:47 +00001708 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1709 VG_(clo_gen_suppressions) = 0;
1710 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1711 VG_(clo_gen_suppressions) = 1;
1712 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1713 VG_(clo_gen_suppressions) = 2;
1714
nethercote71980f02004-01-24 18:18:54 +00001715 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001716 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001717 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001718 }
njn8c0b3bb2005-03-12 21:20:39 +00001719 skip_arg:
1720 if (arg != vg_argv[i])
1721 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001722 }
1723
sewardj998d40d2004-12-06 14:24:52 +00001724 /* Make VEX control parameters sane */
1725
1726 if (VG_(clo_vex_control).guest_chase_thresh
1727 >= VG_(clo_vex_control).guest_max_insns)
1728 VG_(clo_vex_control).guest_chase_thresh
1729 = VG_(clo_vex_control).guest_max_insns - 1;
1730
1731 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1732 VG_(clo_vex_control).guest_chase_thresh = 0;
1733
1734 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001735
njnf9ebf672003-05-12 21:41:30 +00001736 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001737 VG_(clo_verbosity) = 0;
1738
nethercote04d0fbc2004-01-26 16:48:06 +00001739 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001740 VG_(message)(Vg_UserMsg, "");
1741 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001742 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001743 VG_(message)(Vg_UserMsg,
1744 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001745 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001746 }
1747
njnbe9b47b2005-05-15 16:22:58 +00001748 if (VG_(clo_gen_suppressions) > 0 &&
1749 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1750 VG_(message)(Vg_UserMsg,
1751 "Can't use --gen-suppressions= with this tool,");
1752 VG_(message)(Vg_UserMsg,
1753 "as it doesn't generate errors.");
1754 VG_(bad_option)("--gen-suppressions=");
1755 }
1756
sewardj71bc3cb2005-05-19 00:25:45 +00001757 /* If we've been asked to emit XML, mash around various other
1758 options so as to constrain the output somewhat, and to remove
1759 any need for user input during the run. */
1760 if (VG_(clo_xml)) {
1761 /* Disable suppression generation (requires user input) */
1762 VG_(clo_gen_suppressions) = 0;
1763 /* Disable attaching to GDB (requires user input) */
1764 VG_(clo_db_attach) = False;
1765 /* Set a known verbosity level */
1766 VG_(clo_verbosity) = 1;
1767 /* Disable error limits (this might be a bad idea!) */
1768 VG_(clo_error_limit) = False;
1769 /* Disable emulation warnings */
1770 VG_(clo_show_emwarns) = False;
1771 /* Disable waiting for GDB to debug Valgrind */
1772 VG_(clo_wait_for_gdb) = False;
1773 /* No file-descriptor leak checking yet */
1774 VG_(clo_track_fds) = False;
1775 /* Also, we want to set options for the leak checker, but that
1776 will have to be done in Memcheck's flag-handling code, not
1777 here. */
1778 }
1779
njnbe9b47b2005-05-15 16:22:58 +00001780 /* All non-logging-related options have been checked. If the logging
1781 option specified is ok, we can switch to it, as we know we won't
1782 have to generate any other command-line-related error messages.
1783 (So far we should be still attached to stderr, so we can show on
1784 the terminal any problems to do with processing command line
1785 opts.)
1786
1787 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001788 should be connected to whatever sink has been selected, and we
1789 indiscriminately chuck stuff into it without worrying what the
1790 nature of it is. Oh the wonder of Unix streams. */
1791
njnbe9b47b2005-05-15 16:22:58 +00001792 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1793 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001794
njnbe9b47b2005-05-15 16:22:58 +00001795 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001796
sewardj4cf05692002-10-27 20:28:29 +00001797 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001798 vg_assert(VG_(clo_log_name) == NULL);
1799 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001800 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001801
sewardj4cf05692002-10-27 20:28:29 +00001802 case VgLogTo_File: {
1803 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001804 Int seq = 0;
1805 Int pid = VG_(getpid)();
1806
nethercotef8548672004-06-21 12:42:35 +00001807 vg_assert(VG_(clo_log_name) != NULL);
1808 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001809
nethercote71980f02004-01-24 18:18:54 +00001810 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001811 if (seq == 0)
1812 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001813 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001814 else
1815 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001816 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001817 seq++;
1818
njnbe9b47b2005-05-15 16:22:58 +00001819 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001820 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001821 = VG_(open)(logfilename,
1822 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1823 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001824 if (eventually_log_fd >= 0) {
1825 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001826 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001827 } else {
njnbe9b47b2005-05-15 16:22:58 +00001828 // If the file already existed, we try the next name. If it
1829 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001830 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001831 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001832 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001833 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001834 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001835 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001836 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001837 }
1838 }
1839 }
sewardj603d4102005-01-11 14:01:02 +00001840 break; /* switch (VG_(clo_log_to)) */
1841 }
1842
1843 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001844 vg_assert(VG_(clo_log_name) != NULL);
1845 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001846
1847 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001848 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001849 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1850 VKI_S_IRUSR|VKI_S_IWUSR);
1851 if (eventually_log_fd >= 0) {
1852 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001853 } else {
sewardj603d4102005-01-11 14:01:02 +00001854 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001855 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001856 VG_(clo_log_name));
1857 VG_(bad_option)(
1858 "--log-file-exactly=<file> (didn't work out for some reason.)");
1859 /*NOTREACHED*/
1860 }
1861 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001862 }
1863
1864 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001865 vg_assert(VG_(clo_log_name) != NULL);
1866 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1867 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1868 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001869 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001870 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001871 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001872 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001873 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001874 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001875 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001876 }
nethercotef8548672004-06-21 12:42:35 +00001877 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001878 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001879 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001880 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001881 VG_(message)(Vg_UserMsg,
1882 "Log messages will sent to stderr instead." );
1883 VG_(message)(Vg_UserMsg,
1884 "" );
1885 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001886 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001887 } else {
nethercotef8548672004-06-21 12:42:35 +00001888 vg_assert(eventually_log_fd > 0);
1889 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001890 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001891 }
sewardj73cf3bc2002-11-03 03:20:15 +00001892 break;
1893 }
sewardj4cf05692002-10-27 20:28:29 +00001894 }
1895
sewardj71bc3cb2005-05-19 00:25:45 +00001896
1897 /* Check that the requested tool actually supports XML output. */
1898 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1899 VG_(clo_xml) = False;
1900 VG_(message)(Vg_UserMsg,
1901 "Currently only Memcheck supports XML output.");
1902 VG_(bad_option)("--xml=yes");
1903 /*NOTREACHED*/
1904 }
1905
njnbe9b47b2005-05-15 16:22:58 +00001906 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1907 // XXX: this is more or less duplicating the behaviour of the calls to
1908 // VG_(safe_fd)() above, although this does not close the original fd.
1909 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1910 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001911 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001912 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001913 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1914 else {
nethercotef8548672004-06-21 12:42:35 +00001915 VG_(clo_log_fd) = eventually_log_fd;
1916 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001917 }
1918
sewardj4cf05692002-10-27 20:28:29 +00001919 /* Ok, the logging sink is running now. Print a suitable preamble.
1920 If logging to file or a socket, write details of parent PID and
1921 command line args, to help people trying to interpret the
1922 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001923
sewardj71bc3cb2005-05-19 00:25:45 +00001924 if (VG_(clo_xml)) {
1925 VG_(message)(Vg_UserMsg, "");
1926 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1927 VG_(message)(Vg_UserMsg, "");
1928 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1929 VG_(message)(Vg_UserMsg, "");
1930 }
1931
1932 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1933 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1934
sewardj83adf412002-05-01 01:25:45 +00001935 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001936 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001937 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1938 xpre,
njnd04b7c62002-10-03 14:05:52 +00001939 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001940 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001941 NULL == VG_(details).version
1942 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001943 VG_(details).description,
1944 xpost);
1945 VG_(message)(Vg_UserMsg, "%s%s%s",
1946 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001947
njnd04b7c62002-10-03 14:05:52 +00001948 /* Core details */
1949 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001950 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1951 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001952 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001953 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1954 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001955 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001956 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1957 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001958 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001959 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1960 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00001961 }
1962
njnbe9b47b2005-05-15 16:22:58 +00001963 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001964 VG_(message)(Vg_UserMsg, "");
1965 VG_(message)(Vg_UserMsg,
1966 "My PID = %d, parent PID = %d. Prog and args are:",
1967 VG_(getpid)(), VG_(getppid)() );
1968 for (i = 0; i < VG_(client_argc); i++)
1969 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1970 }
sewardj71bc3cb2005-05-19 00:25:45 +00001971 else
1972 if (VG_(clo_xml)) {
1973 VG_(message)(Vg_UserMsg, "");
1974 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1975 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00001976 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00001977 VG_(message)(Vg_UserMsg, "");
1978 VG_(message)(Vg_UserMsg, "<argv>");
1979 for (i = 0; i < VG_(client_argc); i++)
1980 VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
1981 VG_(message)(Vg_UserMsg, "</argv>");
1982 }
sewardj4cf05692002-10-27 20:28:29 +00001983
sewardjde4a1d02002-03-22 01:27:54 +00001984 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001985 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001986 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001987 VG_(message)(Vg_DebugMsg, "");
1988 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1989 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001990 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001991 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001992
njn1fd5eb22005-03-13 05:43:23 +00001993 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001994 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001995 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001996 }
nethercotea70f7352004-04-18 12:08:46 +00001997
njn1fd5eb22005-03-13 05:43:23 +00001998 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001999 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2000 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002001 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002002 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002003# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002004 Char version_buf[BUF_LEN];
2005 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002006 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002007 if (n > 0) {
2008 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002009 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002010 } else {
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002012 }
2013 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002014# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002015 }
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
2017
fitzhardinge98abfc72003-12-16 02:05:15 +00002018 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002019 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002020 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002021 needs one, load the default */
2022 static const Char default_supp[] = "default.supp";
2023 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2024 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2025 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2026 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2027 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002028 }
2029}
2030
nethercotef6a1d502004-08-09 12:21:57 +00002031// Build the string for VALGRINDCLO.
2032Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2033{
2034 /* If we're tracing the children, then we need to start it
2035 with our starter+arguments, which are copied into VALGRINDCLO,
2036 except the --exec= option is changed if present.
2037 */
2038 Int i;
2039 Char *exec;
2040 Char *cp;
2041 Char *optvar;
2042 Int optlen, execlen;
2043
2044 // All these allocated blocks are not free - because we're either
2045 // going to exec, or panic when we fail.
2046
2047 // Create --exec= option: "--exec=<exename>"
2048 exec = VG_(arena_malloc)(VG_AR_CORE,
2049 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2050 vg_assert(NULL != exec);
2051 VG_(sprintf)(exec, "--exec=%s", exename);
2052
2053 // Allocate space for optvar (may overestimate by counting --exec twice,
2054 // no matter)
2055 optlen = 1;
2056 for (i = 0; i < vg_argc; i++)
2057 optlen += VG_(strlen)(vg_argv[i]) + 1;
2058 optlen += VG_(strlen)(exec)+1;
2059 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2060
2061 // Copy all valgrind args except the old --exec (if present)
2062 // VG_CLO_SEP is the separator.
2063 cp = optvar;
2064 for (i = 1; i < vg_argc; i++) {
2065 Char *arg = vg_argv[i];
2066
2067 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2068 // don't copy existing --exec= arg
2069 } else if (VG_(strcmp)(arg, "--") == 0) {
2070 // stop at "--"
2071 break;
2072 } else {
2073 // copy non "--exec" arg
2074 Int len = VG_(strlen)(arg);
2075 VG_(memcpy)(cp, arg, len);
2076 cp += len;
2077 *cp++ = VG_CLO_SEP;
2078 }
2079 }
2080 // Add the new --exec= option
2081 execlen = VG_(strlen)(exec);
2082 VG_(memcpy)(cp, exec, execlen);
2083 cp += execlen;
2084 *cp++ = VG_CLO_SEP;
2085
2086 *cp = '\0';
2087
2088 return optvar;
2089}
2090
2091// Build "/proc/self/fd/<execfd>".
2092Char* VG_(build_child_exename)( void )
2093{
2094 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2095 vg_assert(NULL != exename);
2096 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2097 return exename;
2098}
2099
sewardjde4a1d02002-03-22 01:27:54 +00002100
nethercote71980f02004-01-24 18:18:54 +00002101/*====================================================================*/
2102/*=== File descriptor setup ===*/
2103/*====================================================================*/
2104
2105static void setup_file_descriptors(void)
2106{
2107 struct vki_rlimit rl;
2108
2109 /* Get the current file descriptor limits. */
2110 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2111 rl.rlim_cur = 1024;
2112 rl.rlim_max = 1024;
2113 }
2114
2115 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002116 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2117 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002118 } else {
2119 rl.rlim_cur = rl.rlim_max;
2120 }
2121
2122 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002123 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2124 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002125
2126 /* Update the soft limit. */
2127 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2128
nethercotef6a1d502004-08-09 12:21:57 +00002129 if (vgexecfd != -1)
2130 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002131 if (VG_(clexecfd) != -1)
2132 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2133}
2134
nethercote71980f02004-01-24 18:18:54 +00002135/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002136/*=== Initialise program data/text, etc. ===*/
2137/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002138
sewardjb5f6f512005-03-10 23:59:00 +00002139static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2140 UInt dev, UInt ino, ULong foffset,
2141 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002142{
nethercote71980f02004-01-24 18:18:54 +00002143 /* Only record valgrind mappings for now, without loading any
2144 symbols. This is so we know where the free space is before we
2145 start allocating more memory (note: heap is OK, it's just mmap
2146 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002147 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002148 VG_(debugLog)(2, "main",
2149 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002150 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002151 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002152 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2153 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002154 /* update VG_(valgrind_last) if it looks wrong */
2155 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002156 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002157 }
sewardjde4a1d02002-03-22 01:27:54 +00002158}
2159
nethercote71980f02004-01-24 18:18:54 +00002160// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002161Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002162
sewardjb5f6f512005-03-10 23:59:00 +00002163/*
2164 This second pass adds in client mappings, and loads symbol tables
2165 for all interesting mappings. The trouble is that things can
2166 change as we go, because we're calling the Tool to track memory as
2167 we find it.
2168
2169 So for Valgrind mappings, we don't replace any mappings which
2170 aren't still identical (which will include the .so mappings, so we
2171 will load their symtabs)>
2172 */
2173static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2174 UInt dev, UInt ino, ULong foffset,
2175 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002176{
nethercote71980f02004-01-24 18:18:54 +00002177 UInt flags;
2178 Bool is_stack_segment;
2179 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002180
nethercote71980f02004-01-24 18:18:54 +00002181 is_stack_segment
2182 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002183
sewardj8c615892005-04-25 02:38:28 +00002184 VG_(debugLog)(2, "main",
2185 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002186 (void*)start, (void*)(start+size), prot, is_stack_segment,
2187 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002188
nethercote71980f02004-01-24 18:18:54 +00002189 if (is_stack_segment)
2190 flags = SF_STACK | SF_GROWDOWN;
2191 else
2192 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002193
nethercote71980f02004-01-24 18:18:54 +00002194 if (filename != NULL)
2195 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002196
sewardjb5f6f512005-03-10 23:59:00 +00002197#if 0
2198 // This needs to be fixed properly. jrs 20050307
2199 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2200 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002201
sewardjb5f6f512005-03-10 23:59:00 +00002202 /* We have to be a bit careful about inserting new mappings into
2203 the Valgrind part of the address space. We're actively
2204 changing things as we parse these mappings, particularly in
2205 shadow memory, and so we don't want to overwrite those
2206 changes. Therefore, we only insert/update a mapping if it is
2207 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002208
sewardjb5f6f512005-03-10 23:59:00 +00002209 NOTE: we're only talking about the Segment list mapping
2210 metadata; this doesn't actually mmap anything more. */
2211 if (filename || (s && s->addr == start && s->len == size)) {
2212 flags |= SF_VALGRIND;
2213 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2214 } else {
2215 /* assert range is already mapped */
2216 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2217 }
2218 } else
2219#endif
2220 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2221
2222 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2223 VG_TRACK( new_mem_startup, start, size,
2224 !!(prot & VKI_PROT_READ),
2225 !!(prot & VKI_PROT_WRITE),
2226 !!(prot & VKI_PROT_EXEC));
2227 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002228
nethercote71980f02004-01-24 18:18:54 +00002229 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002230 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002231 vg_assert(0 != r_esp);
2232 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002233 if (0) {
2234 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002235 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002236 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2237 r_esp, start+size);
2238 }
nethercote71980f02004-01-24 18:18:54 +00002239 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002240 // what's this for?
2241 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002242 }
sewardjde4a1d02002-03-22 01:27:54 +00002243}
2244
2245
nethercote71980f02004-01-24 18:18:54 +00002246/*====================================================================*/
2247/*=== Sanity check machinery (permanently engaged) ===*/
2248/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002249
2250/* A fast sanity check -- suitable for calling circa once per
2251 millisecond. */
2252
nethercote885dd912004-08-03 23:14:00 +00002253void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002254{
sewardjb5f6f512005-03-10 23:59:00 +00002255 ThreadId tid;
2256
njn37cea302002-09-30 11:24:00 +00002257 VGP_PUSHCC(VgpCoreCheapSanity);
2258
nethercote27fec902004-06-16 21:26:32 +00002259 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002260
2261 /* --- First do all the tests that we can do quickly. ---*/
2262
nethercote297effd2004-08-02 15:07:57 +00002263 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002264
njn25e49d8e72002-09-23 09:36:25 +00002265 /* Check stuff pertaining to the memory check system. */
2266
2267 /* Check that nobody has spuriously claimed that the first or
2268 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002269 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002270 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002271 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002272 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002273 }
njn25e49d8e72002-09-23 09:36:25 +00002274
2275 /* --- Now some more expensive checks. ---*/
2276
2277 /* Once every 25 times, check some more expensive stuff. */
2278 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002279 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002280 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002281
njn37cea302002-09-30 11:24:00 +00002282 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002283 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002284
2285# if 0
2286 { void zzzmemscan(void); zzzmemscan(); }
2287# endif
2288
nethercote297effd2004-08-02 15:07:57 +00002289 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002290 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002291
2292 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002293 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002294 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002295 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002296 }
sewardjb5f6f512005-03-10 23:59:00 +00002297
2298 /* Check that Segments and /proc/self/maps match up */
2299 //vg_assert(VG_(sanity_check_memory)());
2300
2301 /* Look for stack overruns. Visit all threads. */
2302 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002303 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002304
2305 if (VG_(threads)[tid].status == VgTs_Empty ||
2306 VG_(threads)[tid].status == VgTs_Zombie)
2307 continue;
2308
2309 remains = VGA_(stack_unused)(tid);
2310 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002311 VG_(message)(Vg_DebugMsg,
2312 "WARNING: Thread %d is within %d bytes "
2313 "of running out of stack!",
2314 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002315 }
2316
njn25e49d8e72002-09-23 09:36:25 +00002317 /*
nethercote297effd2004-08-02 15:07:57 +00002318 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002319 */
njn37cea302002-09-30 11:24:00 +00002320 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002321 }
2322
nethercote27fec902004-06-16 21:26:32 +00002323 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002324 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002325 /* Check sanity of the low-level memory manager. Note that bugs
2326 in the client's code can cause this to fail, so we don't do
2327 this check unless specially asked for. And because it's
2328 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002329 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002330 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002331 }
njn37cea302002-09-30 11:24:00 +00002332 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002333}
nethercote71980f02004-01-24 18:18:54 +00002334
2335
2336/*====================================================================*/
2337/*=== main() ===*/
2338/*====================================================================*/
2339
nethercotec314eba2004-07-15 12:59:41 +00002340/*
2341 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002342 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002343 loads the client executable (and the dynamic linker, if necessary)
2344 into the client part, and calls into Valgrind proper.
2345
2346 The code is careful not to allow spurious mappings to appear in the
2347 wrong parts of the address space. In particular, to make sure
2348 dlopen puts things in the right place, it will pad out the forbidden
2349 chunks of address space so that dlopen is forced to put things where
2350 we want them.
2351
2352 The memory map it creates is:
2353
njn311c5d82005-05-15 21:03:42 +00002354 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002355 | client address space |
2356 : :
2357 : :
2358 | client stack |
2359 client_end +-------------------------+
2360 | redzone |
2361 shadow_base +-------------------------+
2362 | |
nethercote996901a2004-08-03 13:29:09 +00002363 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002364 | (may be 0 sized) |
2365 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002366 valgrind_base +-------------------------+
2367 | kickstart executable |
2368 | valgrind heap vvvvvvvvv| (barely used)
2369 - -
2370 | valgrind .so files |
2371 | and mappings |
2372 - -
2373 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002374 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002375 : kernel :
2376
2377 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2378 VG_(mmap)(), we need to build the segment skip-list, so we know where
2379 we can put things. However, building that structure requires
2380 allocating memory. So we need to a bootstrapping process. It's done
2381 by making VG_(arena_malloc)() have a special static superblock that's
2382 used for the first 1MB's worth of allocations. This is enough to
2383 build the segment skip-list.
2384*/
2385
thughes4ad52d02004-06-27 17:37:21 +00002386
sewardj1cf558c2005-04-25 01:36:56 +00002387/* This may be needed before m_mylibc is OK to run. */
2388static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2389{
2390 while (True) {
2391 if (*s1 == 0 && *s2 == 0) return 0;
2392 if (*s1 == 0) return -1;
2393 if (*s2 == 0) return 1;
2394
2395 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2396 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2397
2398 s1++; s2++;
2399 }
2400}
2401
2402
sewardjb5f6f512005-03-10 23:59:00 +00002403int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002404{
2405 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002406 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002407 const char *exec = NULL;
2408 char *preload; /* tool-specific LD_PRELOAD .so */
2409 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002410 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002411 struct exeinfo info;
2412 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002413 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002414 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002415 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002416 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002417 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002418
2419 //============================================================
2420 // Nb: startup is complex. Prerequisites are shown at every step.
2421 //
2422 // *** Be very careful when messing with the order ***
2423 //============================================================
2424
sewardj1cf558c2005-04-25 01:36:56 +00002425 //--------------------------------------------------------------
2426 // Start up the logging mechanism
2427 // p: none
2428 //--------------------------------------------------------------
2429 /* Start the debugging-log system ASAP. First find out how many
2430 "-d"s were specified. This is a pre-scan of the command line. */
2431 loglevel = 0;
2432 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002433 if (argv[i][0] != '-')
2434 break;
2435 if (0 == local_strcmp(argv[i], "--"))
2436 break;
2437 if (0 == local_strcmp(argv[i], "-d"))
2438 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002439 }
2440
2441 /* ... and start the debug logger. Now we can safely emit logging
2442 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002443 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002444
nethercotef4928da2004-06-15 10:54:40 +00002445 //============================================================
2446 // Command line argument handling order:
2447 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002448 // (including the tool-specific usage)
2449 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002450 // * Then, if client is missing, abort with error msg
2451 // * Then, if any cmdline args are bad, abort with error msg
2452 //============================================================
2453
fitzhardingeb50068f2004-02-24 23:42:55 +00002454 // Get the current process datasize rlimit, and set it to zero.
2455 // This prevents any internal uses of brk() from having any effect.
2456 // We remember the old value so we can restore it on exec, so that
2457 // child processes will have a reasonable brk value.
2458 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2459 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2460 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002461
2462 // Get the current process stack rlimit.
2463 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2464
nethercote71980f02004-01-24 18:18:54 +00002465 //--------------------------------------------------------------
2466 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002467 // p: none
nethercote71980f02004-01-24 18:18:54 +00002468 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002469 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002470 {
sewardj1fbc1a52005-04-25 02:05:54 +00002471 void* init_sp = argv - 1;
2472 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002473 }
2474
2475 //--------------------------------------------------------------
2476 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002477 // p: none
nethercote71980f02004-01-24 18:18:54 +00002478 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002479 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002480 if (cp != NULL)
2481 VG_(libdir) = cp;
2482 }
2483
2484 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002485 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2486 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002487 // p: none
nethercote71980f02004-01-24 18:18:54 +00002488 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002489 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002490 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002491 pre_process_cmd_line_options(&need_help, &tool, &exec);
2492
sewardj10759312005-05-30 23:52:47 +00002493 /* If this process was created by exec done by another Valgrind
2494 process, the arguments will only show up at this point. Hence
2495 we need to also snoop around in vg_argv to see if anyone is
2496 asking for debug logging. */
2497 if (loglevel == 0) {
2498 for (i = 1; i < vg_argc; i++) {
2499 if (vg_argv[i][0] != '-')
2500 break;
2501 if (0 == local_strcmp(vg_argv[i], "--"))
2502 break;
2503 if (0 == local_strcmp(vg_argv[i], "-d"))
2504 loglevel++;
2505 }
2506 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2507 }
2508
nethercote71980f02004-01-24 18:18:54 +00002509 //==============================================================
2510 // Nb: once a tool is specified, the tool.so must be loaded even if
2511 // they specified --help or didn't specify a client program.
2512 //==============================================================
2513
2514 //--------------------------------------------------------------
2515 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002516 // p: set-libdir [for VG_(libdir)]
2517 // p: pre_process_cmd_line_options() [for 'tool']
2518 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002519 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002520 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002521
2522 //==============================================================
2523 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002524 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002525 //==============================================================
2526
2527 //--------------------------------------------------------------
2528 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002529 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002530 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002531 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002532 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002533
2534 //--------------------------------------------------------------
2535 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002536 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2537 // p: layout_remaining_space [so there's space]
2538 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002539 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002540 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002541
2542 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002543 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002544 // p: layout_remaining_space() [everything must be mapped in before now]
2545 // p: load_client() [ditto]
2546 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002547 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2548 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002549
2550 //--------------------------------------------------------------
2551 // Set up client's environment
2552 // p: set-libdir [for VG_(libdir)]
2553 // p: load_tool() [for 'preload']
2554 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002555 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002556 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002559 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002560 // p: load_client() [for 'info']
2561 // p: fix_environment() [for 'env']
2562 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002563 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002564 {
sewardj1fbc1a52005-04-25 02:05:54 +00002565 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002566
sewardj1fbc1a52005-04-25 02:05:54 +00002567 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2568 &client_auxv);
2569 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002570 }
nethercote71980f02004-01-24 18:18:54 +00002571
sewardj1fbc1a52005-04-25 02:05:54 +00002572 VG_(debugLog)(2, "main",
2573 "Client info: "
2574 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2575 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2576 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002577
2578 //==============================================================
2579 // Finished setting up operating environment. Now initialise
2580 // Valgrind. (This is where the old VG_(main)() started.)
2581 //==============================================================
2582
2583 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002584 // setup file descriptors
2585 // p: n/a
2586 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002587 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002588 setup_file_descriptors();
2589
2590 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002591 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002592 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002593 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002594 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002595 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2596
2597 //==============================================================
2598 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2599 //==============================================================
2600
2601 //--------------------------------------------------------------
2602 // Init tool: pre_clo_init, process cmd line, post_clo_init
2603 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002604 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002605 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2606 // p: parse_procselfmaps [so VG segments are setup so tool can
2607 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002608 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002609 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002610 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002611 VG_(sanity_check_needs)();
2612
nethercotef4928da2004-06-15 10:54:40 +00002613 // If --tool and --help/--help-debug was given, now give the core+tool
2614 // help message
nethercotef4928da2004-06-15 10:54:40 +00002615 if (need_help) {
2616 usage(/*--help-debug?*/2 == need_help);
2617 }
nethercotec314eba2004-07-15 12:59:41 +00002618 process_cmd_line_options(client_auxv, tool);
2619
njn51d827b2005-05-09 01:02:08 +00002620 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002621
2622 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002623 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002624 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002625 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002626 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002628 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002629 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002630 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002631 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002632
sewardj21c6d0f2005-05-02 10:33:44 +00002633#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002634 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002635 // Protect client trampoline page (which is also sysinfo stuff)
2636 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002637 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002638 {
2639 Segment *seg;
2640 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2641 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002642
sewardjb5f6f512005-03-10 23:59:00 +00002643 /* Make sure this segment isn't treated as stack */
2644 seg = VG_(find_segment)(VG_(client_trampoline_code));
2645 if (seg)
2646 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2647 }
sewardj21c6d0f2005-05-02 10:33:44 +00002648#endif
sewardjb5f6f512005-03-10 23:59:00 +00002649
nethercotec314eba2004-07-15 12:59:41 +00002650 //==============================================================
2651 // Can use VG_(map)() after segments set up
2652 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002653
2654 //--------------------------------------------------------------
2655 // Allow GDB attach
2656 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2657 //--------------------------------------------------------------
2658 /* Hook to delay things long enough so we can get the pid and
2659 attach GDB in another shell. */
2660 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002661 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002662 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2663 /* jrs 20050206: I don't understand why this works on x86. On
2664 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2665 work. */
2666 /* do "jump *$eip" to skip this in gdb (x86) */
2667 //VG_(do_syscall0)(__NR_pause);
2668 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002669 }
2670
sewardjb5d320c2005-03-13 18:57:15 +00002671 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002672 // Search for file descriptors that are inherited from our parent
2673 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2674 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002675 if (VG_(clo_track_fds)) {
2676 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002677 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002678 }
nethercote71980f02004-01-24 18:18:54 +00002679
2680 //--------------------------------------------------------------
2681 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002682 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2683 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002684 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002685 VG_(scheduler_init)();
2686
2687 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002688 // Initialise the pthread model
2689 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002690 // load_client() [for 'client_eip']
2691 // setup_client_stack() [for 'sp_at_startup']
2692 // setup_scheduler() [for the rest of state 1 stuff]
2693 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002694 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002695 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002696
2697 // Tell the tool that we just wrote to the registers.
2698 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2699 sizeof(VexGuestArchState));
2700
sewardj2a99cf62004-11-24 10:44:19 +00002701 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002702 // Initialise the pthread model
2703 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002704 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002705 //if (VG_(clo_model_pthreads))
2706 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002707
2708 //--------------------------------------------------------------
2709 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002710 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002711 //--------------------------------------------------------------
2712 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002713 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002714 VG_(sigstartup_actions)();
2715
2716 //--------------------------------------------------------------
2717 // Perhaps we're profiling Valgrind?
2718 // p: process_cmd_line_options() [for VG_(clo_profile)]
2719 // p: others?
2720 //
2721 // XXX: this seems to be broken? It always says the tool wasn't built
2722 // for profiling; vg_profile.c's functions don't seem to be overriding
2723 // vg_dummy_profile.c's?
2724 //
2725 // XXX: want this as early as possible. Looking for --profile
2726 // in pre_process_cmd_line_options() could get it earlier.
2727 //--------------------------------------------------------------
2728 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002729 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002730
2731 VGP_PUSHCC(VgpStartup);
2732
2733 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002734 // Read suppression file
2735 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2736 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002737 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2738 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002739 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002740 }
nethercote71980f02004-01-24 18:18:54 +00002741
2742 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002743 // Initialise translation table and translation cache
2744 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2745 // aren't identified as part of the client, which would waste
2746 // > 20M of virtual address space.]
2747 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002748 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002749 VG_(init_tt_tc)();
2750
2751 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002752 // Read debug info to find glibc entry points to intercept
2753 // p: parse_procselfmaps? [XXX for debug info?]
2754 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2755 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002756 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002757 VG_(setup_code_redirect_table)();
2758
2759 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002760 // Verbosity message
2761 // p: end_rdtsc_calibration [so startup message is printed first]
2762 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002763 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002764 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2765 if (VG_(clo_verbosity) > 0)
2766 VG_(message)(Vg_UserMsg, "");
2767
2768 //--------------------------------------------------------------
2769 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002770 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002771 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2772 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002773 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002774 VG_(clo_pointercheck) =
2775 VGA_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002776
nethercote71980f02004-01-24 18:18:54 +00002777 //--------------------------------------------------------------
2778 // Run!
2779 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002780 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002781
sewardj71bc3cb2005-05-19 00:25:45 +00002782 if (VG_(clo_xml)) {
2783 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2784 VG_(message)(Vg_UserMsg, "");
2785 }
2786
sewardj1fbc1a52005-04-25 02:05:54 +00002787 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002788 /* As a result of the following call, the last thread standing
2789 eventually winds up running VG_(shutdown_actions_NORETURN) just
2790 below. */
2791 VGP_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002792
sewardj1d887112005-05-30 21:44:08 +00002793 /*NOTREACHED*/
2794 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002795}
2796
2797
2798/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002799void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2800 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002801{
sewardj1d887112005-05-30 21:44:08 +00002802 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2803
2804 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002805 vg_assert(VG_(is_running_thread)(tid));
2806
2807 // Wait for all other threads to exit.
2808 VGA_(reap_threads)(tid);
2809
2810 VG_(clo_model_pthreads) = False;
2811
2812 // Clean the client up before the final report
2813 VGA_(final_tidyup)(tid);
2814
2815 // OK, done
2816 VG_(exit_thread)(tid);
2817
2818 /* should be no threads left */
2819 vg_assert(VG_(count_living_threads)() == 0);
2820
2821 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002822 //--------------------------------------------------------------
2823 // Finalisation: cleanup, messages, etc. Order no so important, only
2824 // affects what order the messages come.
2825 //--------------------------------------------------------------
2826 if (VG_(clo_verbosity) > 0)
2827 VG_(message)(Vg_UserMsg, "");
2828
sewardj71bc3cb2005-05-19 00:25:45 +00002829 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002830 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2831 VG_(show_error_counts_as_XML)();
2832 VG_(message)(Vg_UserMsg, "");
2833 }
sewardj71bc3cb2005-05-19 00:25:45 +00002834 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2835 VG_(message)(Vg_UserMsg, "");
2836 }
2837
nethercote71980f02004-01-24 18:18:54 +00002838 /* Print out file descriptor summary and stats. */
2839 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002840 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002841
njn95ec8702004-11-22 16:46:13 +00002842 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002843 VG_(show_all_errors)();
2844
njn51d827b2005-05-09 01:02:08 +00002845 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002846
sewardj71bc3cb2005-05-19 00:25:45 +00002847 if (VG_(clo_xml)) {
2848 VG_(message)(Vg_UserMsg, "");
2849 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2850 VG_(message)(Vg_UserMsg, "");
2851 }
2852
nethercote885dd912004-08-03 23:14:00 +00002853 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002854
2855 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002856 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002857
nethercote71980f02004-01-24 18:18:54 +00002858 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002859 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002860 if (VG_(clo_profile_flags) > 0)
2861 VG_(show_BB_profile)();
2862
sewardj8b635a42004-11-22 19:01:47 +00002863 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002864 if (0)
2865 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002866
2867 /* Ok, finally exit in the os-specific way. In short, if the
2868 (last) thread exited by calling sys_exit, do likewise; if the
2869 (last) thread stopped due to a fatal signal, terminate the
2870 entire system with that same fatal signal. */
2871 VGO_(terminate_NORETURN)( tid, tids_schedretcode );
njne96be672005-05-08 19:08:54 +00002872}
sewardj8b635a42004-11-22 19:01:47 +00002873
sewardjde4a1d02002-03-22 01:27:54 +00002874/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002875/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002876/*--------------------------------------------------------------------*/