blob: 0709cd36d88c7f389c1db05ad6d69e1776bcc13f [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"
njn2521d322005-05-08 14:45:13 +000042#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000043#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000044#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000045
46#include <dirent.h>
47#include <dlfcn.h>
48#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000049#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000050#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000051#include <string.h>
52#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000053#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000054#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000055#include <sys/wait.h>
56#include <unistd.h>
57
sewardjb5f6f512005-03-10 23:59:00 +000058#include "memcheck/memcheck.h"
59
thughes74b8de22004-04-22 18:12:31 +000060#ifndef AT_DCACHEBSIZE
61#define AT_DCACHEBSIZE 19
62#endif /* AT_DCACHEBSIZE */
63
64#ifndef AT_ICACHEBSIZE
65#define AT_ICACHEBSIZE 20
66#endif /* AT_ICACHEBSIZE */
67
68#ifndef AT_UCACHEBSIZE
69#define AT_UCACHEBSIZE 21
70#endif /* AT_UCACHEBSIZE */
71
nethercote71980f02004-01-24 18:18:54 +000072#ifndef AT_SYSINFO
73#define AT_SYSINFO 32
74#endif /* AT_SYSINFO */
75
76#ifndef AT_SYSINFO_EHDR
77#define AT_SYSINFO_EHDR 33
78#endif /* AT_SYSINFO_EHDR */
79
80#ifndef AT_SECURE
81#define AT_SECURE 23 /* secure mode boolean */
82#endif /* AT_SECURE */
83
nethercote71980f02004-01-24 18:18:54 +000084/* redzone gap between client address space and shadow */
85#define REDZONE_SIZE (1 * 1024*1024)
86
87/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000088#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000089
nethercotee2097312004-06-27 12:29:56 +000090/* Proportion of client space for its heap (rest is for mmaps + stack) */
91#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000092
njn14319cc2005-03-13 06:26:22 +000093/* Number of file descriptors that Valgrind tries to reserve for
94 it's own use - just a small constant. */
95#define N_RESERVED_FDS (10)
96
nethercote71980f02004-01-24 18:18:54 +000097/*====================================================================*/
98/*=== Global entities not referenced from generated code ===*/
99/*====================================================================*/
100
sewardjde4a1d02002-03-22 01:27:54 +0000101/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000102 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000103 ------------------------------------------------------------------ */
104
nethercote73b526f2004-10-31 18:48:21 +0000105struct vki_rlimit VG_(client_rlimit_data);
106struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000107
fitzhardinge98abfc72003-12-16 02:05:15 +0000108/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000109static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000110
111/* client executable */
112Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000113
114/* Path to library directory */
115const Char *VG_(libdir) = VG_LIBDIR;
116
117/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000118static Int vg_argc;
119static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000120
thughesad1c9562004-06-26 11:27:52 +0000121/* Application-visible file descriptor limits */
122Int VG_(fd_soft_limit) = -1;
123Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000124
nethercote4ad74312004-10-26 09:59:49 +0000125/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000126 envp[] as extracted from the client's stack at startup-time. */
127Int VG_(client_argc);
128Char** VG_(client_argv);
129Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000130
sewardj51ac0872004-12-21 01:20:49 +0000131
sewardjde4a1d02002-03-22 01:27:54 +0000132/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000133 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000134 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000135
sewardjde4a1d02002-03-22 01:27:54 +0000136/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000137ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000138
sewardj73cf3bc2002-11-03 03:20:15 +0000139
nethercote71980f02004-01-24 18:18:54 +0000140/*====================================================================*/
141/*=== Counters, for profiling purposes only ===*/
142/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000143
sewardjde4a1d02002-03-22 01:27:54 +0000144/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000145static UInt sanity_fast_count = 0;
146static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000147
nethercote3a42fb82004-08-03 18:08:50 +0000148static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000149{
nethercote3a42fb82004-08-03 18:08:50 +0000150 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000151 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000152 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000153 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000154
nethercote3a42fb82004-08-03 18:08:50 +0000155 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000156 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000157
nethercote71980f02004-01-24 18:18:54 +0000158 VG_(message)(Vg_DebugMsg,
159 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000160 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000161
njn9271cbc2005-03-13 05:38:25 +0000162 VG_(print_ExeContext_stats)();
163
nethercote3a42fb82004-08-03 18:08:50 +0000164 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000165 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000166 VG_(message)(Vg_DebugMsg, "");
167 VG_(message)(Vg_DebugMsg,
168 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000169 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000170 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000171 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000172 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000173 }
nethercote71980f02004-01-24 18:18:54 +0000174}
175
176
177/*====================================================================*/
178/*=== Miscellaneous global functions ===*/
179/*====================================================================*/
180
nethercotecf97ffb2004-09-09 13:40:31 +0000181static Int ptrace_setregs(Int pid, ThreadId tid)
182{
sewardj2a99cf62004-11-24 10:44:19 +0000183 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000184}
185
nethercote04d0fbc2004-01-26 16:48:06 +0000186/* Start debugger and get it to attach to this process. Called if the
187 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000188 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000189 meaningfully get the debugger to continue the program, though; to
190 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000191void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000192{
193 Int pid;
194
195 if ((pid = fork()) == 0) {
196 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000197 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000198
199 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000200 Int status;
201 Int res;
202
nethercote71980f02004-01-24 18:18:54 +0000203 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
204 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000205 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000206 kill(pid, SIGSTOP) == 0 &&
207 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000208 Char pidbuf[15];
209 Char file[30];
210 Char buf[100];
211 Char *bufptr;
212 Char *cmdptr;
213
214 VG_(sprintf)(pidbuf, "%d", pid);
215 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
216
217 bufptr = buf;
218 cmdptr = VG_(clo_db_command);
219
220 while (*cmdptr) {
221 switch (*cmdptr) {
222 case '%':
223 switch (*++cmdptr) {
224 case 'f':
225 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
226 bufptr += VG_(strlen)(file);
227 cmdptr++;
228 break;
229 case 'p':
230 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
231 bufptr += VG_(strlen)(pidbuf);
232 cmdptr++;
233 break;
234 default:
235 *bufptr++ = *cmdptr++;
236 break;
237 }
238 break;
239 default:
240 *bufptr++ = *cmdptr++;
241 break;
242 }
243 }
244
245 *bufptr++ = '\0';
246
247 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000248 res = VG_(system)(buf);
249 if (res == 0) {
250 VG_(message)(Vg_UserMsg, "");
251 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000252 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000253 } else {
254 VG_(message)(Vg_UserMsg, "Apparently failed!");
255 VG_(message)(Vg_UserMsg, "");
256 }
257 }
258
nethercote73b526f2004-10-31 18:48:21 +0000259 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000260 VG_(waitpid)(pid, &status, 0);
261 }
262}
263
264
sewardj2a99cf62004-11-24 10:44:19 +0000265/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000266Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000267{
njncf45fd42004-11-24 16:30:22 +0000268 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000269}
270
njn67516132005-03-22 04:02:43 +0000271Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000272{
273 return INSTR_PTR( VG_(threads)[tid].arch );
274}
275
njnea4b28c2004-11-30 16:04:58 +0000276
nethercote71980f02004-01-24 18:18:54 +0000277/*====================================================================*/
278/*=== Check we were launched by stage 1 ===*/
279/*====================================================================*/
280
281/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000282static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000283{
nethercoteebf1d862004-11-01 18:22:05 +0000284 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000285 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000286
287 for (; auxv->a_type != AT_NULL; auxv++)
288 switch(auxv->a_type) {
289 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000290 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000291 found |= 1;
292 break;
293
294 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000295 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000296 found |= 2;
297 break;
nethercote7f390022004-10-25 17:18:24 +0000298
299 case AT_PHDR:
300 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
301 break;
nethercote71980f02004-01-24 18:18:54 +0000302 }
303
nethercote361a14e2004-07-26 11:11:56 +0000304 if ( found != (1|2) ) {
305 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000306 exit(127);
307 }
nethercote31779c72004-07-30 21:50:15 +0000308 vg_assert(padfile >= 0);
309 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000310}
311
312
313/*====================================================================*/
314/*=== Address space determination ===*/
315/*====================================================================*/
316
nethercote7f390022004-10-25 17:18:24 +0000317extern char _start[];
318
nethercote31779c72004-07-30 21:50:15 +0000319static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000320{
nethercotea3c3cf22004-11-01 18:38:00 +0000321 Int ires;
322 void* vres;
323 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000324
nethercote7f390022004-10-25 17:18:24 +0000325 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
326 // this is a workable approximation
327 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000328 VG_(valgrind_base) = PGROUNDDN(&_start);
329 }
330
nethercote820bd8c2004-09-07 23:04:49 +0000331 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000332
nethercote31779c72004-07-30 21:50:15 +0000333 // This gives the client the largest possible address space while
334 // taking into account the tool's shadow needs.
335 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000336 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000337 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000338 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000339 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000340 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000341 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000342
nethercote31779c72004-07-30 21:50:15 +0000343 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000344 VG_(shadow_end) = VG_(valgrind_base);
345 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000346
nethercotee2097312004-06-27 12:29:56 +0000347#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
348
nethercote71980f02004-01-24 18:18:54 +0000349 if (0)
nethercotee2097312004-06-27 12:29:56 +0000350 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000351 "client_base %p (%dMB)\n"
352 "client_mapbase %p (%dMB)\n"
353 "client_end %p (%dMB)\n"
354 "shadow_base %p (%dMB)\n"
355 "shadow_end %p\n"
356 "valgrind_base %p (%dMB)\n"
357 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000358 VG_(client_base), SEGSIZE(client_base, client_mapbase),
359 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
360 VG_(client_end), SEGSIZE(client_end, shadow_base),
361 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000362 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000363 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
364 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000365 );
366
367#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000368
369 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000370 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000371 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000372 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000373
374 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000375 ires = munmap((void*)VG_(client_base), client_size);
376 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000377
378 // Map shadow memory.
379 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000380 if (shadow_size != 0) {
381 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000382 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000383 if ((void*)-1 == vres) {
384 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000385 "valgrind: Could not allocate address space (%p bytes)\n"
386 "valgrind: for shadow memory\n"
387 "valgrind: Possible causes:\n"
388 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
389 "valgrind: needs at least 1.5GB swap space.\n"
390 "valgrind: - Or, your virtual memory size may be limited (check\n"
391 "valgrind: with 'ulimit -v').\n"
392 "valgrind: - Or, your system may use a kernel that provides only a\n"
393 "valgrind: too-small (eg. 2GB) user address space.\n"
394 , (void*)shadow_size
395 );
nethercoted4722622004-08-30 19:36:42 +0000396 exit(1);
397 }
nethercotee567e702004-07-10 17:49:17 +0000398 }
nethercote71980f02004-01-24 18:18:54 +0000399}
400
401/*====================================================================*/
402/*=== Command line setup ===*/
403/*====================================================================*/
404
nethercote71980f02004-01-24 18:18:54 +0000405static char* get_file_clo(char* dir)
406{
407# define FLEN 512
408 Int fd, n;
409 struct stat s1;
410 char* f_clo = NULL;
411 char filename[FLEN];
412
413 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
414 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
415 if ( fd > 0 ) {
416 if ( 0 == fstat(fd, &s1) ) {
417 f_clo = malloc(s1.st_size+1);
418 vg_assert(f_clo);
419 n = read(fd, f_clo, s1.st_size);
420 if (n == -1) n = 0;
421 f_clo[n] = '\0';
422 }
423 close(fd);
424 }
425 return f_clo;
426# undef FLEN
427}
428
429static Int count_args(char* s)
430{
431 Int n = 0;
432 if (s) {
433 char* cp = s;
434 while (True) {
435 // We have alternating sequences: blanks, non-blanks, blanks...
436 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000437 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000438 if ( !*cp ) break;
439 n++;
njn0c0f32a2005-03-26 04:14:01 +0000440 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000441 }
442 }
443 return n;
444}
445
446/* add args out of environment, skipping multiple spaces and -- args */
447static char** copy_args( char* s, char** to )
448{
449 if (s) {
450 char* cp = s;
451 while (True) {
452 // We have alternating sequences: blanks, non-blanks, blanks...
453 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000454 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000455 if ( !*cp ) break;
456 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000457 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000458 if ( *cp ) *cp++ = '\0'; // terminate if necessary
459 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
460 }
461 }
462 return to;
463}
464
465// Augment command line with arguments from environment and .valgrindrc
466// files.
467static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
468{
nethercotef6a1d502004-08-09 12:21:57 +0000469 int vg_argc0 = *vg_argc_inout;
470 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000471
472 char* env_clo = getenv(VALGRINDOPTS);
473 char* f1_clo = get_file_clo( getenv("HOME") );
474 char* f2_clo = get_file_clo(".");
475
476 /* copy any extra args from file or environment, if present */
477 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
478 /* ' ' separated extra options */
479 char **from;
480 char **to;
thughescaca0022004-09-13 10:20:34 +0000481 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
482
483 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
484
nethercote71980f02004-01-24 18:18:54 +0000485 env_arg_count = count_args(env_clo);
486 f1_arg_count = count_args(f1_clo);
487 f2_arg_count = count_args(f2_clo);
488
489 if (0)
490 printf("extra-argc=%d %d %d\n",
491 env_arg_count, f1_arg_count, f2_arg_count);
492
493 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000494 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000495 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000496 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000497 vg_assert(vg_argv0);
498 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000499
500 /* copy argv[0] */
501 *to++ = *from++;
502
503 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
504 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
505 * to override less local ones. */
506 to = copy_args(f1_clo, to);
507 to = copy_args(env_clo, to);
508 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000509
510 // Free memory
511 free(f1_clo);
512 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000513
514 /* copy original arguments, stopping at command or -- */
515 while (*from) {
516 if (**from != '-')
517 break;
518 if (VG_STREQ(*from, "--")) {
519 from++; /* skip -- */
520 break;
521 }
522 *to++ = *from++;
523 }
524
525 /* add -- */
526 *to++ = "--";
527
nethercotef6a1d502004-08-09 12:21:57 +0000528 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000529
530 /* copy rest of original command line, then NULL */
531 while (*from) *to++ = *from++;
532 *to = NULL;
533 }
534
nethercotef6a1d502004-08-09 12:21:57 +0000535 *vg_argc_inout = vg_argc0;
536 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000537}
538
nethercotef6a1d502004-08-09 12:21:57 +0000539#define VG_CLO_SEP '\01'
540
nethercote71980f02004-01-24 18:18:54 +0000541static void get_command_line( int argc, char** argv,
542 Int* vg_argc_out, Char*** vg_argv_out,
543 char*** cl_argv_out )
544{
nethercotef6a1d502004-08-09 12:21:57 +0000545 int vg_argc0;
546 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000547 char** cl_argv;
548 char* env_clo = getenv(VALGRINDCLO);
549
550 if (env_clo != NULL && *env_clo != '\0') {
551 char *cp;
552 char **cpp;
553
nethercotef6a1d502004-08-09 12:21:57 +0000554 /* OK, VALGRINDCLO is set, which means we must be a child of another
555 Valgrind process using --trace-children, so we're getting all our
556 arguments from VALGRINDCLO, and the entire command line belongs to
557 the client (including argv[0]) */
558 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000559 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000560 if (*cp == VG_CLO_SEP)
561 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000562
nethercotef6a1d502004-08-09 12:21:57 +0000563 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
564 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000565
nethercotef6a1d502004-08-09 12:21:57 +0000566 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000567
568 *cpp++ = "valgrind"; /* nominal argv[0] */
569 *cpp++ = env_clo;
570
nethercotef6a1d502004-08-09 12:21:57 +0000571 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000572 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000573 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000574 *cp++ = '\0'; /* chop it up in place */
575 *cpp++ = cp;
576 }
577 }
578 *cpp = NULL;
579 cl_argv = argv;
580
581 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000582 Bool noaugment = False;
583
nethercote71980f02004-01-24 18:18:54 +0000584 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000585 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000586
nethercotef6a1d502004-08-09 12:21:57 +0000587 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000588 Char* arg = argv[vg_argc0];
589 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000590 break;
sewardjb5f6f512005-03-10 23:59:00 +0000591 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000592 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000593 break;
594 }
njn45270a22005-03-27 01:00:11 +0000595 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000596 }
nethercotef6a1d502004-08-09 12:21:57 +0000597 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000598
599 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000600 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000601 those extra args will already be present in VALGRINDCLO.
602 (We also don't do it when --command-line-only=yes.) */
603 if (!noaugment)
604 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000605 }
606
607 if (0) {
608 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000609 for (i = 0; i < vg_argc0; i++)
610 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000611 }
612
nethercotef6a1d502004-08-09 12:21:57 +0000613 *vg_argc_out = vg_argc0;
614 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000615 *cl_argv_out = cl_argv;
616}
617
618
619/*====================================================================*/
620/*=== Environment and stack setup ===*/
621/*====================================================================*/
622
623/* Scan a colon-separated list, and call a function on each element.
624 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000625 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000626 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000627
628 This routine will return True if (*func) returns True and False if
629 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000630*/
thughes4ad52d02004-06-27 17:37:21 +0000631static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000632{
633 char *cp, *entry;
634 int end;
635
636 if (colsep == NULL ||
637 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000638 return False;
nethercote71980f02004-01-24 18:18:54 +0000639
640 entry = cp = colsep;
641
642 do {
643 end = (*cp == '\0');
644
645 if (*cp == ':' || *cp == '\0') {
646 char save = *cp;
647
648 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000649 if ((*func)(entry)) {
650 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000651 return True;
thughes21942d92004-07-12 09:35:37 +0000652 }
nethercote71980f02004-01-24 18:18:54 +0000653 *cp = save;
654 entry = cp+1;
655 }
656 cp++;
657 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000658
659 return False;
660}
661
nethercote71980f02004-01-24 18:18:54 +0000662/* Prepare the client's environment. This is basically a copy of our
663 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000664 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000665
sewardjb5f6f512005-03-10 23:59:00 +0000666 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000667
668 Yummy. String hacking in C.
669
670 If this needs to handle any more variables it should be hacked
671 into something table driven.
672 */
673static char **fix_environment(char **origenv, const char *preload)
674{
675 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000676 static const char ld_preload[] = "LD_PRELOAD=";
677 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000678 static const int ld_preload_len = sizeof(ld_preload)-1;
679 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
680 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000681 char *inject_path;
682 int inject_path_len;
683 int vgliblen = strlen(VG_(libdir));
684 char **cpp;
685 char **ret;
686 int envc;
687 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
688
689 /* Find the vg_inject.so; also make room for the tool preload
690 library */
691 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
692 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000693 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000694
695 if (preload)
696 snprintf(inject_path, inject_path_len, "%s/%s:%s",
697 VG_(libdir), inject_so, preload);
698 else
699 snprintf(inject_path, inject_path_len, "%s/%s",
700 VG_(libdir), inject_so);
701
702 /* Count the original size of the env */
703 envc = 0; /* trailing NULL */
704 for (cpp = origenv; cpp && *cpp; cpp++)
705 envc++;
706
707 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000708 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000709 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000710
711 /* copy it over */
712 for (cpp = ret; *origenv; )
713 *cpp++ = *origenv++;
714 *cpp = NULL;
715
716 vg_assert(envc == (cpp - ret));
717
718 /* Walk over the new environment, mashing as we go */
719 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000720 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000721 int len = strlen(*cpp) + inject_path_len;
722 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000723 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000724
725 snprintf(cp, len, "%s%s:%s",
726 ld_preload, inject_path, (*cpp)+ld_preload_len);
727
728 *cpp = cp;
729
730 ld_preload_done = 1;
731 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
732 *cpp = "";
733 }
734 }
735
736 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000737 if (!ld_preload_done) {
738 int len = ld_preload_len + inject_path_len;
739 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000740 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000741
742 snprintf(cp, len, "%s%s",
743 ld_preload, inject_path);
744
745 ret[envc++] = cp;
746 }
747
sewardjb5f6f512005-03-10 23:59:00 +0000748 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000749 ret[envc] = NULL;
750
751 return ret;
752}
753
754extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000755
756/* Add a string onto the string table, and return its address */
757static char *copy_str(char **tab, const char *str)
758{
759 char *cp = *tab;
760 char *orig = cp;
761
762 while(*str)
763 *cp++ = *str++;
764 *cp++ = '\0';
765
766 if (0)
nethercote545fe672004-11-01 16:52:43 +0000767 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000768
769 *tab = cp;
770
771 return orig;
772}
773
774/*
775 This sets up the client's initial stack, containing the args,
776 environment and aux vector.
777
778 The format of the stack is:
779
780 higher address +-----------------+
781 | Trampoline code |
782 +-----------------+
783 | |
784 : string table :
785 | |
786 +-----------------+
787 | AT_NULL |
788 - -
789 | auxv |
790 +-----------------+
791 | NULL |
792 - -
793 | envp |
794 +-----------------+
795 | NULL |
796 - -
797 | argv |
798 +-----------------+
799 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000800 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000801 | undefined |
802 : :
803 */
nethercotec25c4492004-10-18 11:52:17 +0000804static Addr setup_client_stack(void* init_sp,
805 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000806 const struct exeinfo *info,
807 UInt** client_auxv)
808{
nethercotee567e702004-07-10 17:49:17 +0000809 void* res;
nethercote71980f02004-01-24 18:18:54 +0000810 char **cpp;
811 char *strtab; /* string table */
812 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000813 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000814 struct ume_auxv *auxv;
815 const struct ume_auxv *orig_auxv;
816 const struct ume_auxv *cauxv;
817 unsigned stringsize; /* total size of strings in bytes */
818 unsigned auxsize; /* total size of auxv in bytes */
819 int argc; /* total argc */
820 int envc; /* total number of env vars */
821 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000822 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000823
824 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000825 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000826
827 /* ==================== compute sizes ==================== */
828
829 /* first of all, work out how big the client stack will be */
830 stringsize = 0;
831
832 /* paste on the extra args if the loader needs them (ie, the #!
833 interpreter and its argument) */
834 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000835 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000836 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000837 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000838 }
nethercoted6a56872004-07-26 15:32:47 +0000839 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000840 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000841 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000842 }
843
844 /* now scan the args we're given... */
845 for (cpp = orig_argv; *cpp; cpp++) {
846 argc++;
847 stringsize += strlen(*cpp) + 1;
848 }
849
850 /* ...and the environment */
851 envc = 0;
852 for (cpp = orig_envp; cpp && *cpp; cpp++) {
853 envc++;
854 stringsize += strlen(*cpp) + 1;
855 }
856
857 /* now, how big is the auxv? */
858 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
859 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
860 if (cauxv->a_type == AT_PLATFORM)
861 stringsize += strlen(cauxv->u.a_ptr) + 1;
862 auxsize += sizeof(*cauxv);
863 }
864
865 /* OK, now we know how big the client stack is */
866 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000867 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000868 sizeof(char **)*argc + /* argv */
869 sizeof(char **) + /* terminal NULL */
870 sizeof(char **)*envc + /* envp */
871 sizeof(char **) + /* terminal NULL */
872 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000873 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000874 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000875
sewardj79048ce2005-02-18 08:28:32 +0000876 if (0) VG_(printf)("stacksize = %d\n", stacksize);
877
nethercotef84f6952004-07-15 14:58:33 +0000878 // decide where stack goes!
879 VG_(clstk_end) = VG_(client_end);
880
nethercote73b526f2004-10-31 18:48:21 +0000881 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000882
nethercote71980f02004-01-24 18:18:54 +0000883 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000884 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000885 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
886
nethercote71980f02004-01-24 18:18:54 +0000887 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000888 stringbase = strtab = (char *)(VG_(client_trampoline_code)
889 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000890
891 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000892
sewardj79048ce2005-02-18 08:28:32 +0000893 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000894 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000895 "clstk_base %p\n"
896 "clstk_end %p\n",
897 stringsize, auxsize, stacksize,
898 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000899
nethercote71980f02004-01-24 18:18:54 +0000900 /* ==================== allocate space ==================== */
901
902 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000903 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000904 PROT_READ | PROT_WRITE | PROT_EXEC,
905 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
906 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000907
908 /* ==================== copy client stack ==================== */
909
nethercotea3c3cf22004-11-01 18:38:00 +0000910 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000911
912 /* --- argc --- */
913 *ptr++ = argc; /* client argc */
914
915 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000916 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000917 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000918 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000919 }
nethercoted6a56872004-07-26 15:32:47 +0000920 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000921 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000922 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000923 }
924 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000925 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000926 }
927 *ptr++ = 0;
928
929 /* --- envp --- */
930 VG_(client_envp) = (Char **)ptr;
931 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000932 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000933 *ptr++ = 0;
934
935 /* --- auxv --- */
936 auxv = (struct ume_auxv *)ptr;
937 *client_auxv = (UInt *)auxv;
938
939 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
940 /* copy the entry... */
941 *auxv = *orig_auxv;
942
943 /* ...and fix up the copy */
944 switch(auxv->a_type) {
945 case AT_PHDR:
946 if (info->phdr == 0)
947 auxv->a_type = AT_IGNORE;
948 else
949 auxv->u.a_val = info->phdr;
950 break;
951
952 case AT_PHNUM:
953 if (info->phdr == 0)
954 auxv->a_type = AT_IGNORE;
955 else
956 auxv->u.a_val = info->phnum;
957 break;
958
959 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000960 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000961 break;
962
963 case AT_PLATFORM: /* points to a platform description string */
964 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
965 break;
966
967 case AT_ENTRY:
968 auxv->u.a_val = info->entry;
969 break;
970
971 case AT_IGNORE:
972 case AT_EXECFD:
973 case AT_PHENT:
974 case AT_PAGESZ:
975 case AT_FLAGS:
976 case AT_NOTELF:
977 case AT_UID:
978 case AT_EUID:
979 case AT_GID:
980 case AT_EGID:
981 case AT_CLKTCK:
982 case AT_HWCAP:
983 case AT_FPUCW:
984 case AT_DCACHEBSIZE:
985 case AT_ICACHEBSIZE:
986 case AT_UCACHEBSIZE:
987 /* All these are pointerless, so we don't need to do anything
988 about them. */
989 break;
990
991 case AT_SECURE:
992 /* If this is 1, then it means that this program is running
993 suid, and therefore the dynamic linker should be careful
994 about LD_PRELOAD, etc. However, since stage1 (the thing
995 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +0000996 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +0000997 set AT_SECURE to 0. */
998 auxv->u.a_val = 0;
999 break;
1000
1001 case AT_SYSINFO:
1002 /* Leave this unmolested for now, but we'll update it later
1003 when we set up the client trampoline code page */
1004 break;
1005
1006 case AT_SYSINFO_EHDR:
1007 /* Trash this, because we don't reproduce it */
1008 auxv->a_type = AT_IGNORE;
1009 break;
1010
1011 default:
1012 /* stomp out anything we don't know about */
1013 if (0)
nethercote545fe672004-11-01 16:52:43 +00001014 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001015 auxv->a_type = AT_IGNORE;
1016 break;
1017
1018 }
1019 }
1020 *auxv = *orig_auxv;
1021 vg_assert(auxv->a_type == AT_NULL);
1022
njnc6168192004-11-29 13:54:10 +00001023// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1024// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001025#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001026 /* --- trampoline page --- */
1027 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1028 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001029#endif
nethercotef84f6952004-07-15 14:58:33 +00001030
nethercote71980f02004-01-24 18:18:54 +00001031 vg_assert((strtab-stringbase) == stringsize);
1032
nethercote5ee67ca2004-06-22 14:00:09 +00001033 /* We know the initial ESP is pointing at argc/argv */
1034 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001035 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001036
sewardj79048ce2005-02-18 08:28:32 +00001037 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001038 return cl_esp;
1039}
1040
1041/*====================================================================*/
1042/*=== Find executable ===*/
1043/*====================================================================*/
1044
thughes4ad52d02004-06-27 17:37:21 +00001045static const char* executable_name;
1046
1047static Bool match_executable(const char *entry) {
1048 char buf[strlen(entry) + strlen(executable_name) + 2];
1049
1050 /* empty PATH element means . */
1051 if (*entry == '\0')
1052 entry = ".";
1053
1054 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1055
1056 if (access(buf, R_OK|X_OK) == 0) {
1057 executable_name = strdup(buf);
1058 vg_assert(NULL != executable_name);
1059 return True;
1060 }
1061 return False;
1062}
1063
nethercote71980f02004-01-24 18:18:54 +00001064static const char* find_executable(const char* exec)
1065{
1066 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001067 executable_name = exec;
1068 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001069 /* no '/' - we need to search the path */
1070 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001071 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001072 }
thughes4ad52d02004-06-27 17:37:21 +00001073 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001074}
1075
1076
1077/*====================================================================*/
1078/*=== Loading tools ===*/
1079/*====================================================================*/
1080
1081static void list_tools(void)
1082{
1083 DIR *dir = opendir(VG_(libdir));
1084 struct dirent *de;
1085 int first = 1;
1086
1087 if (dir == NULL) {
1088 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001089 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001090 return;
1091 }
1092
nethercotef4928da2004-06-15 10:54:40 +00001093 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001094 int len = strlen(de->d_name);
1095
njn063c5402004-11-22 16:58:05 +00001096 /* look for vgtool_TOOL.so names */
1097 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1098 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001099 VG_STREQ(de->d_name + len - 3, ".so")) {
1100 if (first) {
1101 fprintf(stderr, "Available tools:\n");
1102 first = 0;
1103 }
1104 de->d_name[len-3] = '\0';
1105 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001106 }
1107 }
1108
1109 closedir(dir);
1110
1111 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001112 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1113 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001114}
1115
1116
1117/* Find and load a tool, and check it looks ok. Also looks to see if there's
1118 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001119static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001120 ToolInfo** toolinfo_out, char **preloadpath_out )
1121{
1122 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001123 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001124 char buf[len];
1125 void* handle;
1126 ToolInfo* toolinfo;
1127 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001128
1129 // XXX: allowing full paths for --tool option -- does it make sense?
1130 // Doesn't allow for vgpreload_<tool>.so.
1131
1132 if (strchr(toolname, '/') != 0) {
1133 /* toolname contains '/', and so must be a pathname */
1134 handle = dlopen(toolname, RTLD_NOW);
1135 } else {
1136 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001137 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001138 handle = dlopen(buf, RTLD_NOW);
1139
1140 if (handle != NULL) {
1141 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1142 if (access(buf, R_OK) == 0) {
1143 preloadpath = strdup(buf);
1144 vg_assert(NULL != preloadpath);
1145 }
1146 }
1147 }
1148
1149 ok = (NULL != handle);
1150 if (!ok) {
1151 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1152 goto bad_load;
1153 }
1154
njn51d827b2005-05-09 01:02:08 +00001155 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001156 ok = (NULL != toolinfo);
1157 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001158 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001159 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1160 goto bad_load;
1161 }
1162
1163 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001164 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1165 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001166 if (!ok) {
1167 fprintf(stderr, "Error:\n"
1168 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001169 " Interface version used by core is: %d (size %d)\n"
1170 " Interface version used by tool is: %d (size %d)\n"
1171 " The version numbers must match.\n",
1172 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001173 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001174 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001175 toolinfo->sizeof_ToolInfo);
1176 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001177 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001178 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001179 else
nethercote996901a2004-08-03 13:29:09 +00001180 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001181 goto bad_load;
1182 }
1183
njn8a97c6d2005-03-31 04:37:24 +00001184 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001185 *toolinfo_out = toolinfo;
1186 *preloadpath_out = preloadpath;
1187 return;
1188
1189
1190 bad_load:
1191 if (handle != NULL)
1192 dlclose(handle);
1193
nethercotef4928da2004-06-15 10:54:40 +00001194 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001195 list_tools();
1196 exit(127);
1197}
1198
nethercotef4928da2004-06-15 10:54:40 +00001199
1200/*====================================================================*/
1201/*=== Command line errors ===*/
1202/*====================================================================*/
1203
njnbe9b47b2005-05-15 16:22:58 +00001204static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001205{
njnbe9b47b2005-05-15 16:22:58 +00001206 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001207 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001208}
1209
1210void VG_(bad_option) ( Char* opt )
1211{
njnbe9b47b2005-05-15 16:22:58 +00001212 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001213 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001214 VG_(printf)("valgrind: Use --help for more information.\n");
1215 VG_(exit)(1);
1216}
1217
nethercotef4928da2004-06-15 10:54:40 +00001218static void missing_prog ( void )
1219{
njnbe9b47b2005-05-15 16:22:58 +00001220 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001221 VG_(printf)("valgrind: no program specified\n");
1222 VG_(printf)("valgrind: Use --help for more information.\n");
1223 VG_(exit)(1);
1224}
1225
1226static void config_error ( Char* msg )
1227{
njnbe9b47b2005-05-15 16:22:58 +00001228 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001229 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1230 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1231 VG_(exit)(1);
1232}
1233
1234
nethercote71980f02004-01-24 18:18:54 +00001235/*====================================================================*/
1236/*=== Loading the client ===*/
1237/*====================================================================*/
1238
nethercotef4928da2004-06-15 10:54:40 +00001239static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001240 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1241{
1242 // If they didn't specify an executable with --exec, and didn't specify
1243 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001244 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001245 if (cl_argv[0] == NULL ||
1246 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1247 {
nethercotef4928da2004-06-15 10:54:40 +00001248 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001249 }
1250 }
1251
1252 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001253 info->exe_base = VG_(client_base);
1254 info->exe_end = VG_(client_end);
1255 info->argv = cl_argv;
1256
nethercotef4928da2004-06-15 10:54:40 +00001257 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001258 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001259 // Totally zero 'info' before continuing.
1260 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001261 } else {
1262 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001263 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001264 ret = do_exec(exec, info);
1265 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001266 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1267 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001268 exit(127);
1269 }
1270 }
1271
1272 /* Copy necessary bits of 'info' that were filled in */
1273 *client_eip = info->init_eip;
1274 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1275}
1276
nethercote969ecf12004-10-13 17:29:01 +00001277/*====================================================================*/
1278/*=== Address space unpadding ===*/
1279/*====================================================================*/
1280
1281typedef struct {
1282 char* killpad_start;
1283 char* killpad_end;
1284 struct stat* killpad_padstat;
1285} killpad_extra;
1286
1287static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1288 int maj, int min, int ino, void* ex)
1289{
1290 killpad_extra* extra = ex;
1291 void *b, *e;
1292 int res;
1293
1294 vg_assert(NULL != extra->killpad_padstat);
1295
1296 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1297 extra->killpad_padstat->st_ino != ino)
1298 return 1;
1299
1300 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1301 return 1;
1302
1303 if (segstart <= extra->killpad_start)
1304 b = extra->killpad_start;
1305 else
1306 b = segstart;
1307
1308 if (segend >= extra->killpad_end)
1309 e = extra->killpad_end;
1310 else
1311 e = segend;
1312
1313 res = munmap(b, (char *)e-(char *)b);
1314 vg_assert(0 == res);
1315
1316 return 1;
1317}
1318
1319// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001320static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001321{
1322 static struct stat padstat;
1323 killpad_extra extra;
1324 int res;
1325
sewardjb5f6f512005-03-10 23:59:00 +00001326 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001327
1328 res = fstat(padfile, &padstat);
1329 vg_assert(0 == res);
1330 extra.killpad_padstat = &padstat;
1331 extra.killpad_start = start;
1332 extra.killpad_end = end;
1333 foreach_map(killpad, &extra);
1334}
1335
sewardj2c5ffbe2005-03-12 13:32:06 +00001336static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001337{
1338 int res = close(padfile);
1339 vg_assert(0 == res);
1340}
1341
sewardj71bc3cb2005-05-19 00:25:45 +00001342/*====================================================================*/
1343/*=== Command-line: variables, processing, etc ===*/
1344/*====================================================================*/
1345
1346// See pub_{core,tool}_options.h for explanations of all these.
1347
sewardj2c5ffbe2005-03-12 13:32:06 +00001348static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001349{
njn25e49d8e72002-09-23 09:36:25 +00001350 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001351"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001352"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001353" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001354" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001355" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001356" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001357" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001358" -q --quiet run silently; only print error msgs\n"
1359" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001360" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001361" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001362" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001363" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001364"\n"
1365" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001366" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001367" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001368" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001369" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001370" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001371"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001372" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001373" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1374" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001375" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001376" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001377" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001378" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001379" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1380" --show-below-main=no|yes continue stack traces below main() [no]\n"
1381" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001382" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001383" --db-attach=no|yes start debugger when errors detected? [no]\n"
1384" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1385" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001386" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1387" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001388"\n";
njn7cf0bd32002-06-08 13:36:03 +00001389
njn25e49d8e72002-09-23 09:36:25 +00001390 Char* usage2 =
1391"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001392" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001393" --sanity-level=<number> level of sanity checking to do [1]\n"
1394" --single-step=no|yes translate each instr separately? [no]\n"
1395" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001396" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001397" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001398" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1399" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001400" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001401" --trace-syscalls=no|yes show all system calls? [no]\n"
1402" --trace-signals=no|yes show signal handling details? [no]\n"
1403" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001404" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001405" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001406" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001407#if 0
1408" --model-pthreads=yes|no model the pthreads library [no]\n"
1409#endif
1410" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001411"\n"
1412" --vex-iropt-verbosity 0 .. 9 [0]\n"
1413" --vex-iropt-level 0 .. 2 [2]\n"
1414" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001415" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1416" --vex-guest-max-insns 1 .. 100 [50]\n"
1417" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1418"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001419" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001420" 1000 0000 show conversion into IR\n"
1421" 0100 0000 show after initial opt\n"
1422" 0010 0000 show after instrumentation\n"
1423" 0001 0000 show after second opt\n"
1424" 0000 1000 show after tree building\n"
1425" 0000 0100 show selecting insns\n"
1426" 0000 0010 show after reg-alloc\n"
1427" 0000 0001 show final assembly\n"
1428"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001429" debugging options for Valgrind tools that report errors\n"
1430" --dump-error=<number> show translation for basic block associated\n"
1431" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001432"\n";
njn3e884182003-04-15 13:03:23 +00001433
1434 Char* usage3 =
1435"\n"
nethercote71980f02004-01-24 18:18:54 +00001436" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001437"\n"
njn53612422005-03-12 16:22:54 +00001438" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001439" and licensed under the GNU General Public License, version 2.\n"
1440" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001441"\n"
nethercote137bc552003-11-14 17:47:54 +00001442" Tools are copyright and licensed by their authors. See each\n"
1443" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001444"\n";
njn7cf0bd32002-06-08 13:36:03 +00001445
njnbe9b47b2005-05-15 16:22:58 +00001446 // Ensure the message goes to stdout
1447 VG_(clo_log_fd) = 1;
1448 vg_assert( !VG_(logging_to_socket) );
1449
fitzhardinge98abfc72003-12-16 02:05:15 +00001450 VG_(printf)(usage1);
1451 if (VG_(details).name) {
1452 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001453 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001454 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001455 else
1456 VG_(printf)(" (none)\n");
1457 }
nethercote6c999f22004-01-31 22:55:15 +00001458 if (debug_help) {
1459 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001460
nethercote6c999f22004-01-31 22:55:15 +00001461 if (VG_(details).name) {
1462 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1463
1464 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001465 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001466 else
1467 VG_(printf)(" (none)\n");
1468 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001469 }
nethercote421281e2003-11-20 16:20:55 +00001470 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001471 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001472}
sewardjde4a1d02002-03-22 01:27:54 +00001473
nethercote71980f02004-01-24 18:18:54 +00001474static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001475 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001476{
nethercote71980f02004-01-24 18:18:54 +00001477 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001478
sewardj8b635a42004-11-22 19:01:47 +00001479 LibVEX_default_VexControl(& VG_(clo_vex_control));
1480
nethercote71980f02004-01-24 18:18:54 +00001481 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001482 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001483
nethercotef6a1d502004-08-09 12:21:57 +00001484 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001485 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001486 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001487
nethercotef6a1d502004-08-09 12:21:57 +00001488 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1489 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001490 *need_help = 1;
1491
nethercotef6a1d502004-08-09 12:21:57 +00001492 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001493 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001494
nethercotef6c99d72004-11-09 14:35:43 +00001495 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001496 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001497
nethercotef6a1d502004-08-09 12:21:57 +00001498 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1499 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001500 }
1501 }
nethercote71980f02004-01-24 18:18:54 +00001502}
1503
nethercote5ee67ca2004-06-22 14:00:09 +00001504static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001505{
nethercotef8548672004-06-21 12:42:35 +00001506 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001507 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001508 enum {
1509 VgLogTo_Fd,
1510 VgLogTo_File,
1511 VgLogTo_FileExactly,
1512 VgLogTo_Socket
1513 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001514
nethercotee1730692003-11-20 10:38:07 +00001515 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001516 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001517
sewardj19d81412002-06-03 01:10:40 +00001518 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001519 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001520 config_error("Please use absolute paths in "
1521 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001522
njnc6168192004-11-29 13:54:10 +00001523// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001524#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001525 {
sewardjb5f6f512005-03-10 23:59:00 +00001526 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001527 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1528 switch(auxp[0]) {
1529 case AT_SYSINFO:
1530 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1531 break;
1532 }
1533 }
1534 }
1535#endif
sewardjde4a1d02002-03-22 01:27:54 +00001536
nethercotef6a1d502004-08-09 12:21:57 +00001537 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001538
nethercotef6a1d502004-08-09 12:21:57 +00001539 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001540 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001541
thughes3bfd5a02004-07-18 08:05:44 +00001542 /* Look for a colon in the switch name */
1543 while (*colon && *colon != ':' && *colon != '=')
1544 colon++;
nethercote71980f02004-01-24 18:18:54 +00001545
1546 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001547 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001548 if (VG_CLO_STREQN(2, arg, "--") &&
1549 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1550 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1551 {
1552 // prefix matches, convert "--toolname:foo" to "--foo"
1553 if (0)
1554 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001555 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001556 arg[0] = '-';
1557 arg[1] = '-';
1558
1559 } else {
1560 // prefix doesn't match, skip to next arg
1561 continue;
1562 }
1563 }
1564
fitzhardinge98abfc72003-12-16 02:05:15 +00001565 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001566 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1567 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1568 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001569
njn45270a22005-03-27 01:00:11 +00001570 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001571
nethercote71980f02004-01-24 18:18:54 +00001572 else if (VG_CLO_STREQ(arg, "-v") ||
1573 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001574 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001575
nethercote71980f02004-01-24 18:18:54 +00001576 else if (VG_CLO_STREQ(arg, "-q") ||
1577 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001578 VG_(clo_verbosity)--;
1579
sewardj1cf558c2005-04-25 01:36:56 +00001580 else if (VG_CLO_STREQ(arg, "-d")) {
1581 /* do nothing */
1582 }
1583
sewardj71bc3cb2005-05-19 00:25:45 +00001584 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001585 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1586 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1587 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1588 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1589 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1590 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1591 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001592 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001593 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1594 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1595 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1596 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1597 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1598 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1599 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1600 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1601 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001602 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001603 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1604 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1605 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1606 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1607 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001608
njn45270a22005-03-27 01:00:11 +00001609 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1610 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001611
njn45270a22005-03-27 01:00:11 +00001612 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1613 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1614 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1615 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1616 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001617
njn45270a22005-03-27 01:00:11 +00001618 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001619 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001620 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001621 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001622 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001623 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001624 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001625 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001626 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001627 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001628 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001629 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1630
nethercotef8548672004-06-21 12:42:35 +00001631 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001632 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001633 VG_(clo_log_name) = NULL;
1634 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001635 }
1636
nethercotef8548672004-06-21 12:42:35 +00001637 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001638 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001639 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001640 }
njnd6bc3c32005-03-27 00:44:31 +00001641
sewardj603d4102005-01-11 14:01:02 +00001642 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001643 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001644 VG_(clo_log_name) = &arg[19];
1645 }
sewardjde4a1d02002-03-22 01:27:54 +00001646
nethercotef8548672004-06-21 12:42:35 +00001647 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001648 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001649 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001650 }
1651
nethercote71980f02004-01-24 18:18:54 +00001652 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001653 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001654 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001655 VG_(message)(Vg_UserMsg,
1656 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001657 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001658 }
nethercote71980f02004-01-24 18:18:54 +00001659 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001660 VG_(clo_n_suppressions)++;
1661 }
sewardjde4a1d02002-03-22 01:27:54 +00001662
sewardjfa8ec112005-01-19 11:55:34 +00001663 /* "stuvwxyz" --> stuvwxyz (binary) */
1664 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1665 Int j;
1666 char* opt = & arg[14];
1667
1668 if (8 != VG_(strlen)(opt)) {
1669 VG_(message)(Vg_UserMsg,
1670 "--trace-flags argument must have 8 digits");
1671 VG_(bad_option)(arg);
1672 }
1673 for (j = 0; j < 8; j++) {
1674 if ('0' == opt[j]) { /* do nothing */ }
1675 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1676 else {
1677 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1678 "contain 0s and 1s");
1679 VG_(bad_option)(arg);
1680 }
1681 }
1682 }
1683
1684 /* "stuvwxyz" --> stuvwxyz (binary) */
1685 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001686 Int j;
nethercote71980f02004-01-24 18:18:54 +00001687 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001688
sewardj2a99cf62004-11-24 10:44:19 +00001689 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001690 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001691 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001692 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001693 }
sewardj8b635a42004-11-22 19:01:47 +00001694 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001695 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001696 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001697 else {
sewardjfa8ec112005-01-19 11:55:34 +00001698 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001699 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001700 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001701 }
1702 }
1703 }
sewardjde4a1d02002-03-22 01:27:54 +00001704
njn45270a22005-03-27 01:00:11 +00001705 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001706
sewardjd153fae2005-01-10 17:24:47 +00001707 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1708 VG_(clo_gen_suppressions) = 0;
1709 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1710 VG_(clo_gen_suppressions) = 1;
1711 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1712 VG_(clo_gen_suppressions) = 2;
1713
nethercote71980f02004-01-24 18:18:54 +00001714 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001715 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001716 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001717 }
njn8c0b3bb2005-03-12 21:20:39 +00001718 skip_arg:
1719 if (arg != vg_argv[i])
1720 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001721 }
1722
sewardj998d40d2004-12-06 14:24:52 +00001723 /* Make VEX control parameters sane */
1724
1725 if (VG_(clo_vex_control).guest_chase_thresh
1726 >= VG_(clo_vex_control).guest_max_insns)
1727 VG_(clo_vex_control).guest_chase_thresh
1728 = VG_(clo_vex_control).guest_max_insns - 1;
1729
1730 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1731 VG_(clo_vex_control).guest_chase_thresh = 0;
1732
1733 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001734
njnf9ebf672003-05-12 21:41:30 +00001735 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001736 VG_(clo_verbosity) = 0;
1737
nethercote04d0fbc2004-01-26 16:48:06 +00001738 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001739 VG_(message)(Vg_UserMsg, "");
1740 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001741 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001742 VG_(message)(Vg_UserMsg,
1743 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001744 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001745 }
1746
njnbe9b47b2005-05-15 16:22:58 +00001747 if (VG_(clo_gen_suppressions) > 0 &&
1748 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1749 VG_(message)(Vg_UserMsg,
1750 "Can't use --gen-suppressions= with this tool,");
1751 VG_(message)(Vg_UserMsg,
1752 "as it doesn't generate errors.");
1753 VG_(bad_option)("--gen-suppressions=");
1754 }
1755
sewardj71bc3cb2005-05-19 00:25:45 +00001756 /* If we've been asked to emit XML, mash around various other
1757 options so as to constrain the output somewhat, and to remove
1758 any need for user input during the run. */
1759 if (VG_(clo_xml)) {
1760 /* Disable suppression generation (requires user input) */
1761 VG_(clo_gen_suppressions) = 0;
1762 /* Disable attaching to GDB (requires user input) */
1763 VG_(clo_db_attach) = False;
1764 /* Set a known verbosity level */
1765 VG_(clo_verbosity) = 1;
1766 /* Disable error limits (this might be a bad idea!) */
1767 VG_(clo_error_limit) = False;
1768 /* Disable emulation warnings */
1769 VG_(clo_show_emwarns) = False;
1770 /* Disable waiting for GDB to debug Valgrind */
1771 VG_(clo_wait_for_gdb) = False;
1772 /* No file-descriptor leak checking yet */
1773 VG_(clo_track_fds) = False;
1774 /* Also, we want to set options for the leak checker, but that
1775 will have to be done in Memcheck's flag-handling code, not
1776 here. */
1777 }
1778
njnbe9b47b2005-05-15 16:22:58 +00001779 /* All non-logging-related options have been checked. If the logging
1780 option specified is ok, we can switch to it, as we know we won't
1781 have to generate any other command-line-related error messages.
1782 (So far we should be still attached to stderr, so we can show on
1783 the terminal any problems to do with processing command line
1784 opts.)
1785
1786 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001787 should be connected to whatever sink has been selected, and we
1788 indiscriminately chuck stuff into it without worrying what the
1789 nature of it is. Oh the wonder of Unix streams. */
1790
njnbe9b47b2005-05-15 16:22:58 +00001791 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1792 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001793
njnbe9b47b2005-05-15 16:22:58 +00001794 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001795
sewardj4cf05692002-10-27 20:28:29 +00001796 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001797 vg_assert(VG_(clo_log_name) == NULL);
1798 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001799 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001800
sewardj4cf05692002-10-27 20:28:29 +00001801 case VgLogTo_File: {
1802 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001803 Int seq = 0;
1804 Int pid = VG_(getpid)();
1805
nethercotef8548672004-06-21 12:42:35 +00001806 vg_assert(VG_(clo_log_name) != NULL);
1807 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001808
nethercote71980f02004-01-24 18:18:54 +00001809 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001810 if (seq == 0)
1811 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001812 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001813 else
1814 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001815 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001816 seq++;
1817
njnbe9b47b2005-05-15 16:22:58 +00001818 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001819 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001820 = VG_(open)(logfilename,
1821 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1822 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001823 if (eventually_log_fd >= 0) {
1824 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001825 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001826 } else {
njnbe9b47b2005-05-15 16:22:58 +00001827 // If the file already existed, we try the next name. If it
1828 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001829 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001830 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001831 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001832 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001833 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001834 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001835 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001836 }
1837 }
1838 }
sewardj603d4102005-01-11 14:01:02 +00001839 break; /* switch (VG_(clo_log_to)) */
1840 }
1841
1842 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001843 vg_assert(VG_(clo_log_name) != NULL);
1844 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001845
1846 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001847 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001848 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1849 VKI_S_IRUSR|VKI_S_IWUSR);
1850 if (eventually_log_fd >= 0) {
1851 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001852 } else {
sewardj603d4102005-01-11 14:01:02 +00001853 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001854 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001855 VG_(clo_log_name));
1856 VG_(bad_option)(
1857 "--log-file-exactly=<file> (didn't work out for some reason.)");
1858 /*NOTREACHED*/
1859 }
1860 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001861 }
1862
1863 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001864 vg_assert(VG_(clo_log_name) != NULL);
1865 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1866 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1867 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001868 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001869 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001870 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001871 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001872 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001873 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001874 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001875 }
nethercotef8548672004-06-21 12:42:35 +00001876 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001877 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001878 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001879 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001880 VG_(message)(Vg_UserMsg,
1881 "Log messages will sent to stderr instead." );
1882 VG_(message)(Vg_UserMsg,
1883 "" );
1884 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001885 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001886 } else {
nethercotef8548672004-06-21 12:42:35 +00001887 vg_assert(eventually_log_fd > 0);
1888 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001889 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001890 }
sewardj73cf3bc2002-11-03 03:20:15 +00001891 break;
1892 }
sewardj4cf05692002-10-27 20:28:29 +00001893 }
1894
sewardj71bc3cb2005-05-19 00:25:45 +00001895
1896 /* Check that the requested tool actually supports XML output. */
1897 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1898 VG_(clo_xml) = False;
1899 VG_(message)(Vg_UserMsg,
1900 "Currently only Memcheck supports XML output.");
1901 VG_(bad_option)("--xml=yes");
1902 /*NOTREACHED*/
1903 }
1904
njnbe9b47b2005-05-15 16:22:58 +00001905 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1906 // XXX: this is more or less duplicating the behaviour of the calls to
1907 // VG_(safe_fd)() above, although this does not close the original fd.
1908 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1909 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001910 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001911 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001912 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1913 else {
nethercotef8548672004-06-21 12:42:35 +00001914 VG_(clo_log_fd) = eventually_log_fd;
1915 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001916 }
1917
sewardj4cf05692002-10-27 20:28:29 +00001918 /* Ok, the logging sink is running now. Print a suitable preamble.
1919 If logging to file or a socket, write details of parent PID and
1920 command line args, to help people trying to interpret the
1921 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001922
sewardj71bc3cb2005-05-19 00:25:45 +00001923 if (VG_(clo_xml)) {
1924 VG_(message)(Vg_UserMsg, "");
1925 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1926 VG_(message)(Vg_UserMsg, "");
1927 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1928 VG_(message)(Vg_UserMsg, "");
1929 }
1930
1931 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1932 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1933
sewardj83adf412002-05-01 01:25:45 +00001934 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001935 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001936 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1937 xpre,
njnd04b7c62002-10-03 14:05:52 +00001938 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001939 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001940 NULL == VG_(details).version
1941 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001942 VG_(details).description,
1943 xpost);
1944 VG_(message)(Vg_UserMsg, "%s%s%s",
1945 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001946
njnd04b7c62002-10-03 14:05:52 +00001947 /* Core details */
1948 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001949 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1950 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001951 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001952 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1953 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001954 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001955 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1956 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001957 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001958 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1959 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00001960 }
1961
njnbe9b47b2005-05-15 16:22:58 +00001962 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001963 VG_(message)(Vg_UserMsg, "");
1964 VG_(message)(Vg_UserMsg,
1965 "My PID = %d, parent PID = %d. Prog and args are:",
1966 VG_(getpid)(), VG_(getppid)() );
1967 for (i = 0; i < VG_(client_argc); i++)
1968 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1969 }
sewardj71bc3cb2005-05-19 00:25:45 +00001970 else
1971 if (VG_(clo_xml)) {
1972 VG_(message)(Vg_UserMsg, "");
1973 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1974 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00001975 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00001976 VG_(message)(Vg_UserMsg, "");
1977 VG_(message)(Vg_UserMsg, "<argv>");
1978 for (i = 0; i < VG_(client_argc); i++)
1979 VG_(message)(Vg_UserMsg, " <arg>%s</arg>", VG_(client_argv)[i]);
1980 VG_(message)(Vg_UserMsg, "</argv>");
1981 }
sewardj4cf05692002-10-27 20:28:29 +00001982
sewardjde4a1d02002-03-22 01:27:54 +00001983 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001984 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001985 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001986 VG_(message)(Vg_DebugMsg, "");
1987 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1988 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001989 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001990 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00001991
njn1fd5eb22005-03-13 05:43:23 +00001992 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001993 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00001994 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001995 }
nethercotea70f7352004-04-18 12:08:46 +00001996
njn1fd5eb22005-03-13 05:43:23 +00001997 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00001998 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1999 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002000 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002001 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002002# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002003 Char version_buf[BUF_LEN];
2004 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002005 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002006 if (n > 0) {
2007 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002008 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002009 } else {
njn1fd5eb22005-03-13 05:43:23 +00002010 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002011 }
2012 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002013# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002014 }
sewardjde4a1d02002-03-22 01:27:54 +00002015 }
2016
fitzhardinge98abfc72003-12-16 02:05:15 +00002017 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002018 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002019 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002020 needs one, load the default */
2021 static const Char default_supp[] = "default.supp";
2022 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2023 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2024 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2025 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2026 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002027 }
2028}
2029
nethercotef6a1d502004-08-09 12:21:57 +00002030// Build the string for VALGRINDCLO.
2031Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2032{
2033 /* If we're tracing the children, then we need to start it
2034 with our starter+arguments, which are copied into VALGRINDCLO,
2035 except the --exec= option is changed if present.
2036 */
2037 Int i;
2038 Char *exec;
2039 Char *cp;
2040 Char *optvar;
2041 Int optlen, execlen;
2042
2043 // All these allocated blocks are not free - because we're either
2044 // going to exec, or panic when we fail.
2045
2046 // Create --exec= option: "--exec=<exename>"
2047 exec = VG_(arena_malloc)(VG_AR_CORE,
2048 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2049 vg_assert(NULL != exec);
2050 VG_(sprintf)(exec, "--exec=%s", exename);
2051
2052 // Allocate space for optvar (may overestimate by counting --exec twice,
2053 // no matter)
2054 optlen = 1;
2055 for (i = 0; i < vg_argc; i++)
2056 optlen += VG_(strlen)(vg_argv[i]) + 1;
2057 optlen += VG_(strlen)(exec)+1;
2058 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2059
2060 // Copy all valgrind args except the old --exec (if present)
2061 // VG_CLO_SEP is the separator.
2062 cp = optvar;
2063 for (i = 1; i < vg_argc; i++) {
2064 Char *arg = vg_argv[i];
2065
2066 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2067 // don't copy existing --exec= arg
2068 } else if (VG_(strcmp)(arg, "--") == 0) {
2069 // stop at "--"
2070 break;
2071 } else {
2072 // copy non "--exec" arg
2073 Int len = VG_(strlen)(arg);
2074 VG_(memcpy)(cp, arg, len);
2075 cp += len;
2076 *cp++ = VG_CLO_SEP;
2077 }
2078 }
2079 // Add the new --exec= option
2080 execlen = VG_(strlen)(exec);
2081 VG_(memcpy)(cp, exec, execlen);
2082 cp += execlen;
2083 *cp++ = VG_CLO_SEP;
2084
2085 *cp = '\0';
2086
2087 return optvar;
2088}
2089
2090// Build "/proc/self/fd/<execfd>".
2091Char* VG_(build_child_exename)( void )
2092{
2093 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2094 vg_assert(NULL != exename);
2095 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2096 return exename;
2097}
2098
sewardjde4a1d02002-03-22 01:27:54 +00002099
nethercote71980f02004-01-24 18:18:54 +00002100/*====================================================================*/
2101/*=== File descriptor setup ===*/
2102/*====================================================================*/
2103
2104static void setup_file_descriptors(void)
2105{
2106 struct vki_rlimit rl;
2107
2108 /* Get the current file descriptor limits. */
2109 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2110 rl.rlim_cur = 1024;
2111 rl.rlim_max = 1024;
2112 }
2113
2114 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002115 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2116 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002117 } else {
2118 rl.rlim_cur = rl.rlim_max;
2119 }
2120
2121 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002122 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2123 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002124
2125 /* Update the soft limit. */
2126 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2127
nethercotef6a1d502004-08-09 12:21:57 +00002128 if (vgexecfd != -1)
2129 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002130 if (VG_(clexecfd) != -1)
2131 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2132}
2133
nethercote71980f02004-01-24 18:18:54 +00002134/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002135/*=== Initialise program data/text, etc. ===*/
2136/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002137
sewardjb5f6f512005-03-10 23:59:00 +00002138static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2139 UInt dev, UInt ino, ULong foffset,
2140 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002141{
nethercote71980f02004-01-24 18:18:54 +00002142 /* Only record valgrind mappings for now, without loading any
2143 symbols. This is so we know where the free space is before we
2144 start allocating more memory (note: heap is OK, it's just mmap
2145 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002146 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002147 VG_(debugLog)(2, "main",
2148 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002149 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002150 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002151 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2152 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002153 /* update VG_(valgrind_last) if it looks wrong */
2154 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002155 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002156 }
sewardjde4a1d02002-03-22 01:27:54 +00002157}
2158
nethercote71980f02004-01-24 18:18:54 +00002159// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002160Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002161
sewardjb5f6f512005-03-10 23:59:00 +00002162/*
2163 This second pass adds in client mappings, and loads symbol tables
2164 for all interesting mappings. The trouble is that things can
2165 change as we go, because we're calling the Tool to track memory as
2166 we find it.
2167
2168 So for Valgrind mappings, we don't replace any mappings which
2169 aren't still identical (which will include the .so mappings, so we
2170 will load their symtabs)>
2171 */
2172static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2173 UInt dev, UInt ino, ULong foffset,
2174 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002175{
nethercote71980f02004-01-24 18:18:54 +00002176 UInt flags;
2177 Bool is_stack_segment;
2178 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002179
nethercote71980f02004-01-24 18:18:54 +00002180 is_stack_segment
2181 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002182
sewardj8c615892005-04-25 02:38:28 +00002183 VG_(debugLog)(2, "main",
2184 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002185 (void*)start, (void*)(start+size), prot, is_stack_segment,
2186 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002187
nethercote71980f02004-01-24 18:18:54 +00002188 if (is_stack_segment)
2189 flags = SF_STACK | SF_GROWDOWN;
2190 else
2191 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002192
nethercote71980f02004-01-24 18:18:54 +00002193 if (filename != NULL)
2194 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002195
sewardjb5f6f512005-03-10 23:59:00 +00002196#if 0
2197 // This needs to be fixed properly. jrs 20050307
2198 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2199 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002200
sewardjb5f6f512005-03-10 23:59:00 +00002201 /* We have to be a bit careful about inserting new mappings into
2202 the Valgrind part of the address space. We're actively
2203 changing things as we parse these mappings, particularly in
2204 shadow memory, and so we don't want to overwrite those
2205 changes. Therefore, we only insert/update a mapping if it is
2206 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002207
sewardjb5f6f512005-03-10 23:59:00 +00002208 NOTE: we're only talking about the Segment list mapping
2209 metadata; this doesn't actually mmap anything more. */
2210 if (filename || (s && s->addr == start && s->len == size)) {
2211 flags |= SF_VALGRIND;
2212 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2213 } else {
2214 /* assert range is already mapped */
2215 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2216 }
2217 } else
2218#endif
2219 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2220
2221 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2222 VG_TRACK( new_mem_startup, start, size,
2223 !!(prot & VKI_PROT_READ),
2224 !!(prot & VKI_PROT_WRITE),
2225 !!(prot & VKI_PROT_EXEC));
2226 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002227
nethercote71980f02004-01-24 18:18:54 +00002228 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002229 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002230 vg_assert(0 != r_esp);
2231 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002232 if (0) {
2233 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002234 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002235 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2236 r_esp, start+size);
2237 }
nethercote71980f02004-01-24 18:18:54 +00002238 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002239 // what's this for?
2240 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002241 }
sewardjde4a1d02002-03-22 01:27:54 +00002242}
2243
2244
nethercote71980f02004-01-24 18:18:54 +00002245/*====================================================================*/
2246/*=== Sanity check machinery (permanently engaged) ===*/
2247/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002248
2249/* A fast sanity check -- suitable for calling circa once per
2250 millisecond. */
2251
nethercote885dd912004-08-03 23:14:00 +00002252void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002253{
sewardjb5f6f512005-03-10 23:59:00 +00002254 ThreadId tid;
2255
njn37cea302002-09-30 11:24:00 +00002256 VGP_PUSHCC(VgpCoreCheapSanity);
2257
nethercote27fec902004-06-16 21:26:32 +00002258 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002259
2260 /* --- First do all the tests that we can do quickly. ---*/
2261
nethercote297effd2004-08-02 15:07:57 +00002262 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002263
njn25e49d8e72002-09-23 09:36:25 +00002264 /* Check stuff pertaining to the memory check system. */
2265
2266 /* Check that nobody has spuriously claimed that the first or
2267 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002268 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002269 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002270 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002271 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002272 }
njn25e49d8e72002-09-23 09:36:25 +00002273
2274 /* --- Now some more expensive checks. ---*/
2275
2276 /* Once every 25 times, check some more expensive stuff. */
2277 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002278 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002279 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002280
njn37cea302002-09-30 11:24:00 +00002281 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002282 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002283
2284# if 0
2285 { void zzzmemscan(void); zzzmemscan(); }
2286# endif
2287
nethercote297effd2004-08-02 15:07:57 +00002288 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002289 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002290
2291 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002292 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002293 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002294 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002295 }
sewardjb5f6f512005-03-10 23:59:00 +00002296
2297 /* Check that Segments and /proc/self/maps match up */
2298 //vg_assert(VG_(sanity_check_memory)());
2299
2300 /* Look for stack overruns. Visit all threads. */
2301 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002302 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002303
2304 if (VG_(threads)[tid].status == VgTs_Empty ||
2305 VG_(threads)[tid].status == VgTs_Zombie)
2306 continue;
2307
2308 remains = VGA_(stack_unused)(tid);
2309 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002310 VG_(message)(Vg_DebugMsg,
2311 "WARNING: Thread %d is within %d bytes "
2312 "of running out of stack!",
2313 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002314 }
2315
njn25e49d8e72002-09-23 09:36:25 +00002316 /*
nethercote297effd2004-08-02 15:07:57 +00002317 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002318 */
njn37cea302002-09-30 11:24:00 +00002319 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002320 }
2321
nethercote27fec902004-06-16 21:26:32 +00002322 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002323 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002324 /* Check sanity of the low-level memory manager. Note that bugs
2325 in the client's code can cause this to fail, so we don't do
2326 this check unless specially asked for. And because it's
2327 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002328 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002329 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002330 }
njn37cea302002-09-30 11:24:00 +00002331 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002332}
nethercote71980f02004-01-24 18:18:54 +00002333
2334
2335/*====================================================================*/
2336/*=== main() ===*/
2337/*====================================================================*/
2338
nethercotec314eba2004-07-15 12:59:41 +00002339/*
2340 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002341 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002342 loads the client executable (and the dynamic linker, if necessary)
2343 into the client part, and calls into Valgrind proper.
2344
2345 The code is careful not to allow spurious mappings to appear in the
2346 wrong parts of the address space. In particular, to make sure
2347 dlopen puts things in the right place, it will pad out the forbidden
2348 chunks of address space so that dlopen is forced to put things where
2349 we want them.
2350
2351 The memory map it creates is:
2352
njn311c5d82005-05-15 21:03:42 +00002353 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002354 | client address space |
2355 : :
2356 : :
2357 | client stack |
2358 client_end +-------------------------+
2359 | redzone |
2360 shadow_base +-------------------------+
2361 | |
nethercote996901a2004-08-03 13:29:09 +00002362 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002363 | (may be 0 sized) |
2364 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002365 valgrind_base +-------------------------+
2366 | kickstart executable |
2367 | valgrind heap vvvvvvvvv| (barely used)
2368 - -
2369 | valgrind .so files |
2370 | and mappings |
2371 - -
2372 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002373 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002374 : kernel :
2375
2376 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2377 VG_(mmap)(), we need to build the segment skip-list, so we know where
2378 we can put things. However, building that structure requires
2379 allocating memory. So we need to a bootstrapping process. It's done
2380 by making VG_(arena_malloc)() have a special static superblock that's
2381 used for the first 1MB's worth of allocations. This is enough to
2382 build the segment skip-list.
2383*/
2384
thughes4ad52d02004-06-27 17:37:21 +00002385
sewardj1cf558c2005-04-25 01:36:56 +00002386/* This may be needed before m_mylibc is OK to run. */
2387static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2388{
2389 while (True) {
2390 if (*s1 == 0 && *s2 == 0) return 0;
2391 if (*s1 == 0) return -1;
2392 if (*s2 == 0) return 1;
2393
2394 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2395 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2396
2397 s1++; s2++;
2398 }
2399}
2400
2401
sewardjb5f6f512005-03-10 23:59:00 +00002402int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002403{
2404 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002405 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002406 const char *exec = NULL;
2407 char *preload; /* tool-specific LD_PRELOAD .so */
2408 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002409 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002410 struct exeinfo info;
2411 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002412 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002413 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002414 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002415 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002416 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002417
2418 //============================================================
2419 // Nb: startup is complex. Prerequisites are shown at every step.
2420 //
2421 // *** Be very careful when messing with the order ***
2422 //============================================================
2423
sewardj1cf558c2005-04-25 01:36:56 +00002424 //--------------------------------------------------------------
2425 // Start up the logging mechanism
2426 // p: none
2427 //--------------------------------------------------------------
2428 /* Start the debugging-log system ASAP. First find out how many
2429 "-d"s were specified. This is a pre-scan of the command line. */
2430 loglevel = 0;
2431 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002432 if (argv[i][0] != '-')
2433 break;
2434 if (0 == local_strcmp(argv[i], "--"))
2435 break;
2436 if (0 == local_strcmp(argv[i], "-d"))
2437 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002438 }
2439
2440 /* ... and start the debug logger. Now we can safely emit logging
2441 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002442 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002443
nethercotef4928da2004-06-15 10:54:40 +00002444 //============================================================
2445 // Command line argument handling order:
2446 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002447 // (including the tool-specific usage)
2448 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002449 // * Then, if client is missing, abort with error msg
2450 // * Then, if any cmdline args are bad, abort with error msg
2451 //============================================================
2452
fitzhardingeb50068f2004-02-24 23:42:55 +00002453 // Get the current process datasize rlimit, and set it to zero.
2454 // This prevents any internal uses of brk() from having any effect.
2455 // We remember the old value so we can restore it on exec, so that
2456 // child processes will have a reasonable brk value.
2457 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2458 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2459 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002460
2461 // Get the current process stack rlimit.
2462 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2463
nethercote71980f02004-01-24 18:18:54 +00002464 //--------------------------------------------------------------
2465 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002466 // p: none
nethercote71980f02004-01-24 18:18:54 +00002467 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002468 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002469 {
sewardj1fbc1a52005-04-25 02:05:54 +00002470 void* init_sp = argv - 1;
2471 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002472 }
2473
2474 //--------------------------------------------------------------
2475 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002476 // p: none
nethercote71980f02004-01-24 18:18:54 +00002477 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002478 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002479 if (cp != NULL)
2480 VG_(libdir) = cp;
2481 }
2482
2483 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002484 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2485 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002486 // p: none
nethercote71980f02004-01-24 18:18:54 +00002487 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002488 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002489 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002490 pre_process_cmd_line_options(&need_help, &tool, &exec);
2491
sewardj10759312005-05-30 23:52:47 +00002492 /* If this process was created by exec done by another Valgrind
2493 process, the arguments will only show up at this point. Hence
2494 we need to also snoop around in vg_argv to see if anyone is
2495 asking for debug logging. */
2496 if (loglevel == 0) {
2497 for (i = 1; i < vg_argc; i++) {
2498 if (vg_argv[i][0] != '-')
2499 break;
2500 if (0 == local_strcmp(vg_argv[i], "--"))
2501 break;
2502 if (0 == local_strcmp(vg_argv[i], "-d"))
2503 loglevel++;
2504 }
2505 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2506 }
2507
nethercote71980f02004-01-24 18:18:54 +00002508 //==============================================================
2509 // Nb: once a tool is specified, the tool.so must be loaded even if
2510 // they specified --help or didn't specify a client program.
2511 //==============================================================
2512
2513 //--------------------------------------------------------------
2514 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002515 // p: set-libdir [for VG_(libdir)]
2516 // p: pre_process_cmd_line_options() [for 'tool']
2517 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002518 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002519 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002520
2521 //==============================================================
2522 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002523 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002524 //==============================================================
2525
2526 //--------------------------------------------------------------
2527 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002528 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002529 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002530 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002531 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002532
2533 //--------------------------------------------------------------
2534 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002535 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2536 // p: layout_remaining_space [so there's space]
2537 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002538 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002539 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002540
2541 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002542 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002543 // p: layout_remaining_space() [everything must be mapped in before now]
2544 // p: load_client() [ditto]
2545 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002546 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2547 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002548
2549 //--------------------------------------------------------------
2550 // Set up client's environment
2551 // p: set-libdir [for VG_(libdir)]
2552 // p: load_tool() [for 'preload']
2553 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002554 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002555 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002556
2557 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002558 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002559 // p: load_client() [for 'info']
2560 // p: fix_environment() [for 'env']
2561 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002562 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002563 {
sewardj1fbc1a52005-04-25 02:05:54 +00002564 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002565
sewardj1fbc1a52005-04-25 02:05:54 +00002566 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2567 &client_auxv);
2568 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002569 }
nethercote71980f02004-01-24 18:18:54 +00002570
sewardj1fbc1a52005-04-25 02:05:54 +00002571 VG_(debugLog)(2, "main",
2572 "Client info: "
2573 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2574 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2575 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002576
2577 //==============================================================
2578 // Finished setting up operating environment. Now initialise
2579 // Valgrind. (This is where the old VG_(main)() started.)
2580 //==============================================================
2581
2582 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002583 // setup file descriptors
2584 // p: n/a
2585 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002586 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002587 setup_file_descriptors();
2588
2589 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002590 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002591 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002592 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002593 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002594 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2595
2596 //==============================================================
2597 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2598 //==============================================================
2599
2600 //--------------------------------------------------------------
2601 // Init tool: pre_clo_init, process cmd line, post_clo_init
2602 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002603 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002604 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2605 // p: parse_procselfmaps [so VG segments are setup so tool can
2606 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002607 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002608 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002609 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002610 VG_(sanity_check_needs)();
2611
nethercotef4928da2004-06-15 10:54:40 +00002612 // If --tool and --help/--help-debug was given, now give the core+tool
2613 // help message
nethercotef4928da2004-06-15 10:54:40 +00002614 if (need_help) {
2615 usage(/*--help-debug?*/2 == need_help);
2616 }
nethercotec314eba2004-07-15 12:59:41 +00002617 process_cmd_line_options(client_auxv, tool);
2618
njn51d827b2005-05-09 01:02:08 +00002619 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002620
2621 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002622 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002623 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002624 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002625 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002626 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002627 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002628 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002629 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002630 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002631
sewardj21c6d0f2005-05-02 10:33:44 +00002632#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002633 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002634 // Protect client trampoline page (which is also sysinfo stuff)
2635 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002636 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002637 {
2638 Segment *seg;
2639 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2640 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002641
sewardjb5f6f512005-03-10 23:59:00 +00002642 /* Make sure this segment isn't treated as stack */
2643 seg = VG_(find_segment)(VG_(client_trampoline_code));
2644 if (seg)
2645 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2646 }
sewardj21c6d0f2005-05-02 10:33:44 +00002647#endif
sewardjb5f6f512005-03-10 23:59:00 +00002648
nethercotec314eba2004-07-15 12:59:41 +00002649 //==============================================================
2650 // Can use VG_(map)() after segments set up
2651 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002652
2653 //--------------------------------------------------------------
2654 // Allow GDB attach
2655 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2656 //--------------------------------------------------------------
2657 /* Hook to delay things long enough so we can get the pid and
2658 attach GDB in another shell. */
2659 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002660 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002661 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2662 /* jrs 20050206: I don't understand why this works on x86. On
2663 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2664 work. */
2665 /* do "jump *$eip" to skip this in gdb (x86) */
2666 //VG_(do_syscall0)(__NR_pause);
2667 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002668 }
2669
sewardjb5d320c2005-03-13 18:57:15 +00002670 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002671 // Search for file descriptors that are inherited from our parent
2672 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2673 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002674 if (VG_(clo_track_fds)) {
2675 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002676 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002677 }
nethercote71980f02004-01-24 18:18:54 +00002678
2679 //--------------------------------------------------------------
2680 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002681 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2682 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002683 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002684 VG_(scheduler_init)();
2685
2686 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002687 // Initialise the pthread model
2688 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002689 // load_client() [for 'client_eip']
2690 // setup_client_stack() [for 'sp_at_startup']
2691 // setup_scheduler() [for the rest of state 1 stuff]
2692 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002693 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002694 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002695
2696 // Tell the tool that we just wrote to the registers.
2697 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2698 sizeof(VexGuestArchState));
2699
sewardj2a99cf62004-11-24 10:44:19 +00002700 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002701 // Initialise the pthread model
2702 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002703 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002704 //if (VG_(clo_model_pthreads))
2705 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002706
2707 //--------------------------------------------------------------
2708 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002709 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002710 //--------------------------------------------------------------
2711 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002712 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002713 VG_(sigstartup_actions)();
2714
2715 //--------------------------------------------------------------
2716 // Perhaps we're profiling Valgrind?
2717 // p: process_cmd_line_options() [for VG_(clo_profile)]
2718 // p: others?
2719 //
2720 // XXX: this seems to be broken? It always says the tool wasn't built
2721 // for profiling; vg_profile.c's functions don't seem to be overriding
2722 // vg_dummy_profile.c's?
2723 //
2724 // XXX: want this as early as possible. Looking for --profile
2725 // in pre_process_cmd_line_options() could get it earlier.
2726 //--------------------------------------------------------------
2727 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002728 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002729
2730 VGP_PUSHCC(VgpStartup);
2731
2732 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002733 // Read suppression file
2734 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2735 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002736 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2737 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002738 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002739 }
nethercote71980f02004-01-24 18:18:54 +00002740
2741 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002742 // Initialise translation table and translation cache
2743 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2744 // aren't identified as part of the client, which would waste
2745 // > 20M of virtual address space.]
2746 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002747 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002748 VG_(init_tt_tc)();
2749
2750 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002751 // Read debug info to find glibc entry points to intercept
2752 // p: parse_procselfmaps? [XXX for debug info?]
2753 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2754 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002755 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002756 VG_(setup_code_redirect_table)();
2757
2758 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002759 // Verbosity message
2760 // p: end_rdtsc_calibration [so startup message is printed first]
2761 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002762 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002763 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2764 if (VG_(clo_verbosity) > 0)
2765 VG_(message)(Vg_UserMsg, "");
2766
2767 //--------------------------------------------------------------
2768 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002769 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002770 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2771 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002772 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002773 VG_(clo_pointercheck) =
2774 VGA_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002775
nethercote71980f02004-01-24 18:18:54 +00002776 //--------------------------------------------------------------
2777 // Run!
2778 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002779 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002780
sewardj71bc3cb2005-05-19 00:25:45 +00002781 if (VG_(clo_xml)) {
2782 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2783 VG_(message)(Vg_UserMsg, "");
2784 }
2785
sewardj1fbc1a52005-04-25 02:05:54 +00002786 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002787 /* As a result of the following call, the last thread standing
2788 eventually winds up running VG_(shutdown_actions_NORETURN) just
2789 below. */
2790 VGP_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002791
sewardj1d887112005-05-30 21:44:08 +00002792 /*NOTREACHED*/
2793 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002794}
2795
2796
2797/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002798void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2799 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002800{
sewardj1d887112005-05-30 21:44:08 +00002801 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2802
2803 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002804 vg_assert(VG_(is_running_thread)(tid));
2805
2806 // Wait for all other threads to exit.
2807 VGA_(reap_threads)(tid);
2808
2809 VG_(clo_model_pthreads) = False;
2810
2811 // Clean the client up before the final report
2812 VGA_(final_tidyup)(tid);
2813
2814 // OK, done
2815 VG_(exit_thread)(tid);
2816
2817 /* should be no threads left */
2818 vg_assert(VG_(count_living_threads)() == 0);
2819
2820 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002821 //--------------------------------------------------------------
2822 // Finalisation: cleanup, messages, etc. Order no so important, only
2823 // affects what order the messages come.
2824 //--------------------------------------------------------------
2825 if (VG_(clo_verbosity) > 0)
2826 VG_(message)(Vg_UserMsg, "");
2827
sewardj71bc3cb2005-05-19 00:25:45 +00002828 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002829 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2830 VG_(show_error_counts_as_XML)();
2831 VG_(message)(Vg_UserMsg, "");
2832 }
sewardj71bc3cb2005-05-19 00:25:45 +00002833 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2834 VG_(message)(Vg_UserMsg, "");
2835 }
2836
nethercote71980f02004-01-24 18:18:54 +00002837 /* Print out file descriptor summary and stats. */
2838 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002839 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002840
njn95ec8702004-11-22 16:46:13 +00002841 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002842 VG_(show_all_errors)();
2843
njn51d827b2005-05-09 01:02:08 +00002844 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002845
sewardj71bc3cb2005-05-19 00:25:45 +00002846 if (VG_(clo_xml)) {
2847 VG_(message)(Vg_UserMsg, "");
2848 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2849 VG_(message)(Vg_UserMsg, "");
2850 }
2851
nethercote885dd912004-08-03 23:14:00 +00002852 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002853
2854 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002855 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002856
nethercote71980f02004-01-24 18:18:54 +00002857 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002858 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002859 if (VG_(clo_profile_flags) > 0)
2860 VG_(show_BB_profile)();
2861
sewardj8b635a42004-11-22 19:01:47 +00002862 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002863 if (0)
2864 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002865
2866 /* Ok, finally exit in the os-specific way. In short, if the
2867 (last) thread exited by calling sys_exit, do likewise; if the
2868 (last) thread stopped due to a fatal signal, terminate the
2869 entire system with that same fatal signal. */
2870 VGO_(terminate_NORETURN)( tid, tids_schedretcode );
njne96be672005-05-08 19:08:54 +00002871}
sewardj8b635a42004-11-22 19:01:47 +00002872
sewardjde4a1d02002-03-22 01:27:54 +00002873/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002874/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002875/*--------------------------------------------------------------------*/