blob: 713667ccda9ab824ba3f5c65ddc196aac7d8a553 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00003/*--- Startup: the real stuff m_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000035#include "pub_core_aspacemgr.h"
njn2521d322005-05-08 14:45:13 +000036#include "pub_core_debuglog.h"
37#include "pub_core_errormgr.h"
38#include "pub_core_execontext.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
njn04e16982005-05-31 00:23:43 +000040#include "pub_core_main.h"
njn20242342005-05-16 23:31:24 +000041#include "pub_core_options.h"
njn31513b42005-06-01 03:09:59 +000042#include "pub_core_profile.h"
njnd1af0032005-05-29 17:01:48 +000043#include "pub_core_redir.h"
njn0c246472005-05-31 01:00:08 +000044#include "pub_core_signals.h"
njn2521d322005-05-08 14:45:13 +000045#include "pub_core_syscalls.h"
njn43b9a8a2005-05-10 04:37:01 +000046#include "pub_core_tooliface.h"
njn8bddf582005-05-13 23:40:55 +000047#include "pub_core_transtab.h"
nethercote71980f02004-01-24 18:18:54 +000048
49#include <dirent.h>
50#include <dlfcn.h>
51#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000052#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000053#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000054#include <string.h>
55#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000056#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000057#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000058#include <sys/wait.h>
59#include <unistd.h>
60
sewardjb5f6f512005-03-10 23:59:00 +000061#include "memcheck/memcheck.h"
62
thughes74b8de22004-04-22 18:12:31 +000063#ifndef AT_DCACHEBSIZE
64#define AT_DCACHEBSIZE 19
65#endif /* AT_DCACHEBSIZE */
66
67#ifndef AT_ICACHEBSIZE
68#define AT_ICACHEBSIZE 20
69#endif /* AT_ICACHEBSIZE */
70
71#ifndef AT_UCACHEBSIZE
72#define AT_UCACHEBSIZE 21
73#endif /* AT_UCACHEBSIZE */
74
nethercote71980f02004-01-24 18:18:54 +000075#ifndef AT_SYSINFO
76#define AT_SYSINFO 32
77#endif /* AT_SYSINFO */
78
79#ifndef AT_SYSINFO_EHDR
80#define AT_SYSINFO_EHDR 33
81#endif /* AT_SYSINFO_EHDR */
82
83#ifndef AT_SECURE
84#define AT_SECURE 23 /* secure mode boolean */
85#endif /* AT_SECURE */
86
nethercote71980f02004-01-24 18:18:54 +000087/* redzone gap between client address space and shadow */
88#define REDZONE_SIZE (1 * 1024*1024)
89
90/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000091#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000092
nethercotee2097312004-06-27 12:29:56 +000093/* Proportion of client space for its heap (rest is for mmaps + stack) */
94#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000095
njn14319cc2005-03-13 06:26:22 +000096/* Number of file descriptors that Valgrind tries to reserve for
97 it's own use - just a small constant. */
98#define N_RESERVED_FDS (10)
99
nethercote71980f02004-01-24 18:18:54 +0000100/*====================================================================*/
101/*=== Global entities not referenced from generated code ===*/
102/*====================================================================*/
103
sewardjde4a1d02002-03-22 01:27:54 +0000104/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000105 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +0000106 ------------------------------------------------------------------ */
107
nethercote73b526f2004-10-31 18:48:21 +0000108struct vki_rlimit VG_(client_rlimit_data);
109struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000110
fitzhardinge98abfc72003-12-16 02:05:15 +0000111/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000112static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000113
114/* client executable */
115Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000116
117/* Path to library directory */
118const Char *VG_(libdir) = VG_LIBDIR;
119
120/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000121static Int vg_argc;
122static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
thughesad1c9562004-06-26 11:27:52 +0000124/* Application-visible file descriptor limits */
125Int VG_(fd_soft_limit) = -1;
126Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000127
nethercote4ad74312004-10-26 09:59:49 +0000128/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000129 envp[] as extracted from the client's stack at startup-time. */
130Int VG_(client_argc);
131Char** VG_(client_argv);
132Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000133
sewardj51ac0872004-12-21 01:20:49 +0000134
sewardjde4a1d02002-03-22 01:27:54 +0000135/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000136 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000137 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000138
sewardjde4a1d02002-03-22 01:27:54 +0000139/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000140ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000141
sewardj73cf3bc2002-11-03 03:20:15 +0000142
nethercote71980f02004-01-24 18:18:54 +0000143/*====================================================================*/
144/*=== Counters, for profiling purposes only ===*/
145/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000146
sewardjde4a1d02002-03-22 01:27:54 +0000147/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000148static UInt sanity_fast_count = 0;
149static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000150
nethercote3a42fb82004-08-03 18:08:50 +0000151static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000152{
nethercote3a42fb82004-08-03 18:08:50 +0000153 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000154 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000155 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000156 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000157
nethercote3a42fb82004-08-03 18:08:50 +0000158 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000159 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161 VG_(message)(Vg_DebugMsg,
162 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000163 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000164
njn9271cbc2005-03-13 05:38:25 +0000165 VG_(print_ExeContext_stats)();
166
nethercote3a42fb82004-08-03 18:08:50 +0000167 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000168 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000169 VG_(message)(Vg_DebugMsg, "");
170 VG_(message)(Vg_DebugMsg,
171 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000172 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000173 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000174 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000175 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000176 }
nethercote71980f02004-01-24 18:18:54 +0000177}
178
179
180/*====================================================================*/
181/*=== Miscellaneous global functions ===*/
182/*====================================================================*/
183
nethercotecf97ffb2004-09-09 13:40:31 +0000184static Int ptrace_setregs(Int pid, ThreadId tid)
185{
sewardj2a99cf62004-11-24 10:44:19 +0000186 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000187}
188
nethercote04d0fbc2004-01-26 16:48:06 +0000189/* Start debugger and get it to attach to this process. Called if the
190 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000191 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000192 meaningfully get the debugger to continue the program, though; to
193 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000194void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000195{
196 Int pid;
197
198 if ((pid = fork()) == 0) {
199 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000200 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000201
202 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000203 Int status;
204 Int res;
205
nethercote71980f02004-01-24 18:18:54 +0000206 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
207 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000208 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000209 kill(pid, SIGSTOP) == 0 &&
210 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000211 Char pidbuf[15];
212 Char file[30];
213 Char buf[100];
214 Char *bufptr;
215 Char *cmdptr;
216
217 VG_(sprintf)(pidbuf, "%d", pid);
218 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
219
220 bufptr = buf;
221 cmdptr = VG_(clo_db_command);
222
223 while (*cmdptr) {
224 switch (*cmdptr) {
225 case '%':
226 switch (*++cmdptr) {
227 case 'f':
228 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
229 bufptr += VG_(strlen)(file);
230 cmdptr++;
231 break;
232 case 'p':
233 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
234 bufptr += VG_(strlen)(pidbuf);
235 cmdptr++;
236 break;
237 default:
238 *bufptr++ = *cmdptr++;
239 break;
240 }
241 break;
242 default:
243 *bufptr++ = *cmdptr++;
244 break;
245 }
246 }
247
248 *bufptr++ = '\0';
249
250 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000251 res = VG_(system)(buf);
252 if (res == 0) {
253 VG_(message)(Vg_UserMsg, "");
254 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000255 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000256 } else {
257 VG_(message)(Vg_UserMsg, "Apparently failed!");
258 VG_(message)(Vg_UserMsg, "");
259 }
260 }
261
nethercote73b526f2004-10-31 18:48:21 +0000262 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000263 VG_(waitpid)(pid, &status, 0);
264 }
265}
266
267
sewardj2a99cf62004-11-24 10:44:19 +0000268/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000269Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000270{
njncf45fd42004-11-24 16:30:22 +0000271 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000272}
273
njn67516132005-03-22 04:02:43 +0000274Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000275{
276 return INSTR_PTR( VG_(threads)[tid].arch );
277}
278
njnea4b28c2004-11-30 16:04:58 +0000279
nethercote71980f02004-01-24 18:18:54 +0000280/*====================================================================*/
281/*=== Check we were launched by stage 1 ===*/
282/*====================================================================*/
283
284/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000285static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000286{
nethercoteebf1d862004-11-01 18:22:05 +0000287 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000288 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000289
290 for (; auxv->a_type != AT_NULL; auxv++)
291 switch(auxv->a_type) {
292 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000293 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000294 found |= 1;
295 break;
296
297 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000298 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000299 found |= 2;
300 break;
nethercote7f390022004-10-25 17:18:24 +0000301
302 case AT_PHDR:
njn13bfd852005-06-02 03:52:53 +0000303 VG_(valgrind_base) = VG_PGROUNDDN(auxv->u.a_val);
nethercote7f390022004-10-25 17:18:24 +0000304 break;
nethercote71980f02004-01-24 18:18:54 +0000305 }
306
nethercote361a14e2004-07-26 11:11:56 +0000307 if ( found != (1|2) ) {
308 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000309 exit(127);
310 }
nethercote31779c72004-07-30 21:50:15 +0000311 vg_assert(padfile >= 0);
312 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000313}
314
315
316/*====================================================================*/
317/*=== Address space determination ===*/
318/*====================================================================*/
319
nethercote7f390022004-10-25 17:18:24 +0000320extern char _start[];
321
nethercote31779c72004-07-30 21:50:15 +0000322static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000323{
nethercotea3c3cf22004-11-01 18:38:00 +0000324 Int ires;
325 void* vres;
326 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000327
nethercote7f390022004-10-25 17:18:24 +0000328 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
329 // this is a workable approximation
330 if (VG_(valgrind_base) == 0) {
njn13bfd852005-06-02 03:52:53 +0000331 VG_(valgrind_base) = VG_PGROUNDDN(&_start);
nethercote7f390022004-10-25 17:18:24 +0000332 }
333
njn13bfd852005-06-02 03:52:53 +0000334 VG_(valgrind_last) = VG_ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000335
nethercote31779c72004-07-30 21:50:15 +0000336 // This gives the client the largest possible address space while
337 // taking into account the tool's shadow needs.
njn13bfd852005-06-02 03:52:53 +0000338 client_size = VG_ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000339 CLIENT_SIZE_MULTIPLE);
njn311c5d82005-05-15 21:03:42 +0000340 VG_(client_base) = 0;
nethercote71980f02004-01-24 18:18:54 +0000341 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000342 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000343 VG_(client_mapbase) = VG_(client_base) +
njn13bfd852005-06-02 03:52:53 +0000344 VG_PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000345
nethercote31779c72004-07-30 21:50:15 +0000346 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000347 VG_(shadow_end) = VG_(valgrind_base);
348 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000349
nethercotee2097312004-06-27 12:29:56 +0000350#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
351
nethercote71980f02004-01-24 18:18:54 +0000352 if (0)
nethercotee2097312004-06-27 12:29:56 +0000353 VG_(printf)(
tomb1d43182005-03-29 09:00:12 +0000354 "client_base %p (%dMB)\n"
355 "client_mapbase %p (%dMB)\n"
356 "client_end %p (%dMB)\n"
357 "shadow_base %p (%dMB)\n"
358 "shadow_end %p\n"
359 "valgrind_base %p (%dMB)\n"
360 "valgrind_last %p\n",
nethercotee2097312004-06-27 12:29:56 +0000361 VG_(client_base), SEGSIZE(client_base, client_mapbase),
362 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
363 VG_(client_end), SEGSIZE(client_end, shadow_base),
364 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000365 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000366 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
367 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000368 );
369
370#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000371
372 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000373 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000374 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000375 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000376
377 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000378 ires = munmap((void*)VG_(client_base), client_size);
379 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000380
381 // Map shadow memory.
382 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000383 if (shadow_size != 0) {
384 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000385 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000386 if ((void*)-1 == vres) {
387 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000388 "valgrind: Could not allocate address space (%p bytes)\n"
389 "valgrind: for shadow memory\n"
390 "valgrind: Possible causes:\n"
391 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
392 "valgrind: needs at least 1.5GB swap space.\n"
393 "valgrind: - Or, your virtual memory size may be limited (check\n"
394 "valgrind: with 'ulimit -v').\n"
395 "valgrind: - Or, your system may use a kernel that provides only a\n"
396 "valgrind: too-small (eg. 2GB) user address space.\n"
397 , (void*)shadow_size
398 );
nethercoted4722622004-08-30 19:36:42 +0000399 exit(1);
400 }
nethercotee567e702004-07-10 17:49:17 +0000401 }
nethercote71980f02004-01-24 18:18:54 +0000402}
403
404/*====================================================================*/
405/*=== Command line setup ===*/
406/*====================================================================*/
407
nethercote71980f02004-01-24 18:18:54 +0000408static char* get_file_clo(char* dir)
409{
410# define FLEN 512
411 Int fd, n;
412 struct stat s1;
413 char* f_clo = NULL;
414 char filename[FLEN];
415
416 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
417 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
418 if ( fd > 0 ) {
419 if ( 0 == fstat(fd, &s1) ) {
420 f_clo = malloc(s1.st_size+1);
421 vg_assert(f_clo);
422 n = read(fd, f_clo, s1.st_size);
423 if (n == -1) n = 0;
424 f_clo[n] = '\0';
425 }
426 close(fd);
427 }
428 return f_clo;
429# undef FLEN
430}
431
432static Int count_args(char* s)
433{
434 Int n = 0;
435 if (s) {
436 char* cp = s;
437 while (True) {
438 // We have alternating sequences: blanks, non-blanks, blanks...
439 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000440 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000441 if ( !*cp ) break;
442 n++;
njn0c0f32a2005-03-26 04:14:01 +0000443 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000444 }
445 }
446 return n;
447}
448
449/* add args out of environment, skipping multiple spaces and -- args */
450static char** copy_args( char* s, char** to )
451{
452 if (s) {
453 char* cp = s;
454 while (True) {
455 // We have alternating sequences: blanks, non-blanks, blanks...
456 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000457 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000458 if ( !*cp ) break;
459 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000460 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000461 if ( *cp ) *cp++ = '\0'; // terminate if necessary
462 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
463 }
464 }
465 return to;
466}
467
468// Augment command line with arguments from environment and .valgrindrc
469// files.
470static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
471{
nethercotef6a1d502004-08-09 12:21:57 +0000472 int vg_argc0 = *vg_argc_inout;
473 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000474
475 char* env_clo = getenv(VALGRINDOPTS);
476 char* f1_clo = get_file_clo( getenv("HOME") );
477 char* f2_clo = get_file_clo(".");
478
479 /* copy any extra args from file or environment, if present */
480 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
481 /* ' ' separated extra options */
482 char **from;
483 char **to;
thughescaca0022004-09-13 10:20:34 +0000484 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
485
486 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
487
nethercote71980f02004-01-24 18:18:54 +0000488 env_arg_count = count_args(env_clo);
489 f1_arg_count = count_args(f1_clo);
490 f2_arg_count = count_args(f2_clo);
491
492 if (0)
493 printf("extra-argc=%d %d %d\n",
494 env_arg_count, f1_arg_count, f2_arg_count);
495
496 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000497 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000498 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000499 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000500 vg_assert(vg_argv0);
501 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000502
503 /* copy argv[0] */
504 *to++ = *from++;
505
506 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
507 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
508 * to override less local ones. */
509 to = copy_args(f1_clo, to);
510 to = copy_args(env_clo, to);
511 to = copy_args(f2_clo, to);
njna96e15a2005-05-24 21:36:32 +0000512
513 // Free memory
514 free(f1_clo);
515 free(f2_clo);
nethercote71980f02004-01-24 18:18:54 +0000516
517 /* copy original arguments, stopping at command or -- */
518 while (*from) {
519 if (**from != '-')
520 break;
521 if (VG_STREQ(*from, "--")) {
522 from++; /* skip -- */
523 break;
524 }
525 *to++ = *from++;
526 }
527
528 /* add -- */
529 *to++ = "--";
530
nethercotef6a1d502004-08-09 12:21:57 +0000531 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000532
533 /* copy rest of original command line, then NULL */
534 while (*from) *to++ = *from++;
535 *to = NULL;
536 }
537
nethercotef6a1d502004-08-09 12:21:57 +0000538 *vg_argc_inout = vg_argc0;
539 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000540}
541
nethercotef6a1d502004-08-09 12:21:57 +0000542#define VG_CLO_SEP '\01'
543
nethercote71980f02004-01-24 18:18:54 +0000544static void get_command_line( int argc, char** argv,
545 Int* vg_argc_out, Char*** vg_argv_out,
546 char*** cl_argv_out )
547{
nethercotef6a1d502004-08-09 12:21:57 +0000548 int vg_argc0;
549 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000550 char** cl_argv;
551 char* env_clo = getenv(VALGRINDCLO);
552
553 if (env_clo != NULL && *env_clo != '\0') {
554 char *cp;
555 char **cpp;
556
nethercotef6a1d502004-08-09 12:21:57 +0000557 /* OK, VALGRINDCLO is set, which means we must be a child of another
558 Valgrind process using --trace-children, so we're getting all our
559 arguments from VALGRINDCLO, and the entire command line belongs to
560 the client (including argv[0]) */
561 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000562 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000563 if (*cp == VG_CLO_SEP)
564 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000565
nethercotef6a1d502004-08-09 12:21:57 +0000566 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
567 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000568
nethercotef6a1d502004-08-09 12:21:57 +0000569 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000570
571 *cpp++ = "valgrind"; /* nominal argv[0] */
572 *cpp++ = env_clo;
573
nethercotef6a1d502004-08-09 12:21:57 +0000574 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000575 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000576 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000577 *cp++ = '\0'; /* chop it up in place */
578 *cpp++ = cp;
579 }
580 }
581 *cpp = NULL;
582 cl_argv = argv;
583
584 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000585 Bool noaugment = False;
586
nethercote71980f02004-01-24 18:18:54 +0000587 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000588 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000589
nethercotef6a1d502004-08-09 12:21:57 +0000590 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000591 Char* arg = argv[vg_argc0];
592 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000593 break;
sewardjb5f6f512005-03-10 23:59:00 +0000594 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000595 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000596 break;
597 }
njn45270a22005-03-27 01:00:11 +0000598 VG_BOOL_CLO(arg, "--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000599 }
nethercotef6a1d502004-08-09 12:21:57 +0000600 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000601
602 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000603 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000604 those extra args will already be present in VALGRINDCLO.
605 (We also don't do it when --command-line-only=yes.) */
606 if (!noaugment)
607 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000608 }
609
610 if (0) {
611 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000612 for (i = 0; i < vg_argc0; i++)
613 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000614 }
615
nethercotef6a1d502004-08-09 12:21:57 +0000616 *vg_argc_out = vg_argc0;
617 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000618 *cl_argv_out = cl_argv;
619}
620
621
622/*====================================================================*/
623/*=== Environment and stack setup ===*/
624/*====================================================================*/
625
626/* Scan a colon-separated list, and call a function on each element.
627 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000628 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000629 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000630
631 This routine will return True if (*func) returns True and False if
632 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000633*/
thughes4ad52d02004-06-27 17:37:21 +0000634static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000635{
636 char *cp, *entry;
637 int end;
638
639 if (colsep == NULL ||
640 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000641 return False;
nethercote71980f02004-01-24 18:18:54 +0000642
643 entry = cp = colsep;
644
645 do {
646 end = (*cp == '\0');
647
648 if (*cp == ':' || *cp == '\0') {
649 char save = *cp;
650
651 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000652 if ((*func)(entry)) {
653 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000654 return True;
thughes21942d92004-07-12 09:35:37 +0000655 }
nethercote71980f02004-01-24 18:18:54 +0000656 *cp = save;
657 entry = cp+1;
658 }
659 cp++;
660 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000661
662 return False;
663}
664
nethercote71980f02004-01-24 18:18:54 +0000665/* Prepare the client's environment. This is basically a copy of our
666 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000667 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000668
sewardjb5f6f512005-03-10 23:59:00 +0000669 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000670
671 Yummy. String hacking in C.
672
673 If this needs to handle any more variables it should be hacked
674 into something table driven.
675 */
676static char **fix_environment(char **origenv, const char *preload)
677{
678 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000679 static const char ld_preload[] = "LD_PRELOAD=";
680 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000681 static const int ld_preload_len = sizeof(ld_preload)-1;
682 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
683 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000684 char *inject_path;
685 int inject_path_len;
686 int vgliblen = strlen(VG_(libdir));
687 char **cpp;
688 char **ret;
689 int envc;
690 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
691
692 /* Find the vg_inject.so; also make room for the tool preload
693 library */
694 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
695 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000696 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000697
698 if (preload)
699 snprintf(inject_path, inject_path_len, "%s/%s:%s",
700 VG_(libdir), inject_so, preload);
701 else
702 snprintf(inject_path, inject_path_len, "%s/%s",
703 VG_(libdir), inject_so);
704
705 /* Count the original size of the env */
706 envc = 0; /* trailing NULL */
707 for (cpp = origenv; cpp && *cpp; cpp++)
708 envc++;
709
710 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000711 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000712 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000713
714 /* copy it over */
715 for (cpp = ret; *origenv; )
716 *cpp++ = *origenv++;
717 *cpp = NULL;
718
719 vg_assert(envc == (cpp - ret));
720
721 /* Walk over the new environment, mashing as we go */
722 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000723 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000724 int len = strlen(*cpp) + inject_path_len;
725 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000726 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000727
728 snprintf(cp, len, "%s%s:%s",
729 ld_preload, inject_path, (*cpp)+ld_preload_len);
730
731 *cpp = cp;
732
733 ld_preload_done = 1;
734 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
735 *cpp = "";
736 }
737 }
738
739 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000740 if (!ld_preload_done) {
741 int len = ld_preload_len + inject_path_len;
742 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000743 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000744
745 snprintf(cp, len, "%s%s",
746 ld_preload, inject_path);
747
748 ret[envc++] = cp;
749 }
750
sewardjb5f6f512005-03-10 23:59:00 +0000751 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000752 ret[envc] = NULL;
753
754 return ret;
755}
756
757extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000758
759/* Add a string onto the string table, and return its address */
760static char *copy_str(char **tab, const char *str)
761{
762 char *cp = *tab;
763 char *orig = cp;
764
765 while(*str)
766 *cp++ = *str++;
767 *cp++ = '\0';
768
769 if (0)
nethercote545fe672004-11-01 16:52:43 +0000770 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000771
772 *tab = cp;
773
774 return orig;
775}
776
777/*
778 This sets up the client's initial stack, containing the args,
779 environment and aux vector.
780
781 The format of the stack is:
782
783 higher address +-----------------+
784 | Trampoline code |
785 +-----------------+
786 | |
787 : string table :
788 | |
789 +-----------------+
790 | AT_NULL |
791 - -
792 | auxv |
793 +-----------------+
794 | NULL |
795 - -
796 | envp |
797 +-----------------+
798 | NULL |
799 - -
800 | argv |
801 +-----------------+
802 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000803 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000804 | undefined |
805 : :
806 */
nethercotec25c4492004-10-18 11:52:17 +0000807static Addr setup_client_stack(void* init_sp,
808 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000809 const struct exeinfo *info,
810 UInt** client_auxv)
811{
nethercotee567e702004-07-10 17:49:17 +0000812 void* res;
nethercote71980f02004-01-24 18:18:54 +0000813 char **cpp;
814 char *strtab; /* string table */
815 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000816 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000817 struct ume_auxv *auxv;
818 const struct ume_auxv *orig_auxv;
819 const struct ume_auxv *cauxv;
820 unsigned stringsize; /* total size of strings in bytes */
821 unsigned auxsize; /* total size of auxv in bytes */
822 int argc; /* total argc */
823 int envc; /* total number of env vars */
824 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000825 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000826
827 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000828 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000829
830 /* ==================== compute sizes ==================== */
831
832 /* first of all, work out how big the client stack will be */
833 stringsize = 0;
834
835 /* paste on the extra args if the loader needs them (ie, the #!
836 interpreter and its argument) */
837 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000838 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000839 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000840 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000841 }
nethercoted6a56872004-07-26 15:32:47 +0000842 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000843 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000844 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000845 }
846
847 /* now scan the args we're given... */
848 for (cpp = orig_argv; *cpp; cpp++) {
849 argc++;
850 stringsize += strlen(*cpp) + 1;
851 }
852
853 /* ...and the environment */
854 envc = 0;
855 for (cpp = orig_envp; cpp && *cpp; cpp++) {
856 envc++;
857 stringsize += strlen(*cpp) + 1;
858 }
859
860 /* now, how big is the auxv? */
861 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
862 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
863 if (cauxv->a_type == AT_PLATFORM)
864 stringsize += strlen(cauxv->u.a_ptr) + 1;
865 auxsize += sizeof(*cauxv);
866 }
867
868 /* OK, now we know how big the client stack is */
869 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000870 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000871 sizeof(char **)*argc + /* argv */
872 sizeof(char **) + /* terminal NULL */
873 sizeof(char **)*envc + /* envp */
874 sizeof(char **) + /* terminal NULL */
875 auxsize + /* auxv */
njn13bfd852005-06-02 03:52:53 +0000876 VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000877 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000878
sewardj79048ce2005-02-18 08:28:32 +0000879 if (0) VG_(printf)("stacksize = %d\n", stacksize);
880
nethercotef84f6952004-07-15 14:58:33 +0000881 // decide where stack goes!
882 VG_(clstk_end) = VG_(client_end);
883
nethercote73b526f2004-10-31 18:48:21 +0000884 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000885
nethercote71980f02004-01-24 18:18:54 +0000886 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000887 cl_esp = VG_(clstk_end) - stacksize;
njn13bfd852005-06-02 03:52:53 +0000888 cl_esp = VG_ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
nethercote71980f02004-01-24 18:18:54 +0000889
nethercote71980f02004-01-24 18:18:54 +0000890 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000891 stringbase = strtab = (char *)(VG_(client_trampoline_code)
njn13bfd852005-06-02 03:52:53 +0000892 - VG_ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000893
njn13bfd852005-06-02 03:52:53 +0000894 VG_(clstk_base) = VG_PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000895
sewardj79048ce2005-02-18 08:28:32 +0000896 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000897 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000898 "clstk_base %p\n"
899 "clstk_end %p\n",
900 stringsize, auxsize, stacksize,
901 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000902
nethercote71980f02004-01-24 18:18:54 +0000903 /* ==================== allocate space ==================== */
904
905 /* allocate a stack - mmap enough space for the stack */
njn13bfd852005-06-02 03:52:53 +0000906 res = mmap((void *)VG_PGROUNDDN(cl_esp),
907 VG_(clstk_end) - VG_PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000908 PROT_READ | PROT_WRITE | PROT_EXEC,
909 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
910 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000911
912 /* ==================== copy client stack ==================== */
913
nethercotea3c3cf22004-11-01 18:38:00 +0000914 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000915
916 /* --- argc --- */
917 *ptr++ = argc; /* client argc */
918
919 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000920 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000921 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000922 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000923 }
nethercoted6a56872004-07-26 15:32:47 +0000924 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000925 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000926 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000927 }
928 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000929 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000930 }
931 *ptr++ = 0;
932
933 /* --- envp --- */
934 VG_(client_envp) = (Char **)ptr;
935 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000936 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000937 *ptr++ = 0;
938
939 /* --- auxv --- */
940 auxv = (struct ume_auxv *)ptr;
941 *client_auxv = (UInt *)auxv;
942
943 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
944 /* copy the entry... */
945 *auxv = *orig_auxv;
946
947 /* ...and fix up the copy */
948 switch(auxv->a_type) {
949 case AT_PHDR:
950 if (info->phdr == 0)
951 auxv->a_type = AT_IGNORE;
952 else
953 auxv->u.a_val = info->phdr;
954 break;
955
956 case AT_PHNUM:
957 if (info->phdr == 0)
958 auxv->a_type = AT_IGNORE;
959 else
960 auxv->u.a_val = info->phnum;
961 break;
962
963 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +0000964 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +0000965 break;
966
967 case AT_PLATFORM: /* points to a platform description string */
968 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
969 break;
970
971 case AT_ENTRY:
972 auxv->u.a_val = info->entry;
973 break;
974
975 case AT_IGNORE:
976 case AT_EXECFD:
977 case AT_PHENT:
978 case AT_PAGESZ:
979 case AT_FLAGS:
980 case AT_NOTELF:
981 case AT_UID:
982 case AT_EUID:
983 case AT_GID:
984 case AT_EGID:
985 case AT_CLKTCK:
986 case AT_HWCAP:
987 case AT_FPUCW:
988 case AT_DCACHEBSIZE:
989 case AT_ICACHEBSIZE:
990 case AT_UCACHEBSIZE:
991 /* All these are pointerless, so we don't need to do anything
992 about them. */
993 break;
994
995 case AT_SECURE:
996 /* If this is 1, then it means that this program is running
997 suid, and therefore the dynamic linker should be careful
998 about LD_PRELOAD, etc. However, since stage1 (the thing
999 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001000 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001001 set AT_SECURE to 0. */
1002 auxv->u.a_val = 0;
1003 break;
1004
1005 case AT_SYSINFO:
1006 /* Leave this unmolested for now, but we'll update it later
1007 when we set up the client trampoline code page */
1008 break;
1009
1010 case AT_SYSINFO_EHDR:
1011 /* Trash this, because we don't reproduce it */
1012 auxv->a_type = AT_IGNORE;
1013 break;
1014
1015 default:
1016 /* stomp out anything we don't know about */
1017 if (0)
nethercote545fe672004-11-01 16:52:43 +00001018 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001019 auxv->a_type = AT_IGNORE;
1020 break;
1021
1022 }
1023 }
1024 *auxv = *orig_auxv;
1025 vg_assert(auxv->a_type == AT_NULL);
1026
njnc6168192004-11-29 13:54:10 +00001027// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1028// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardj21c6d0f2005-05-02 10:33:44 +00001029#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotef84f6952004-07-15 14:58:33 +00001030 /* --- trampoline page --- */
1031 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1032 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001033#endif
nethercotef84f6952004-07-15 14:58:33 +00001034
nethercote71980f02004-01-24 18:18:54 +00001035 vg_assert((strtab-stringbase) == stringsize);
1036
nethercote5ee67ca2004-06-22 14:00:09 +00001037 /* We know the initial ESP is pointing at argc/argv */
1038 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001039 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001040
sewardj79048ce2005-02-18 08:28:32 +00001041 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001042 return cl_esp;
1043}
1044
1045/*====================================================================*/
1046/*=== Find executable ===*/
1047/*====================================================================*/
1048
thughes4ad52d02004-06-27 17:37:21 +00001049static const char* executable_name;
1050
1051static Bool match_executable(const char *entry) {
1052 char buf[strlen(entry) + strlen(executable_name) + 2];
1053
1054 /* empty PATH element means . */
1055 if (*entry == '\0')
1056 entry = ".";
1057
1058 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1059
1060 if (access(buf, R_OK|X_OK) == 0) {
1061 executable_name = strdup(buf);
1062 vg_assert(NULL != executable_name);
1063 return True;
1064 }
1065 return False;
1066}
1067
nethercote71980f02004-01-24 18:18:54 +00001068static const char* find_executable(const char* exec)
1069{
1070 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001071 executable_name = exec;
1072 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001073 /* no '/' - we need to search the path */
1074 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001075 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001076 }
thughes4ad52d02004-06-27 17:37:21 +00001077 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001078}
1079
1080
1081/*====================================================================*/
1082/*=== Loading tools ===*/
1083/*====================================================================*/
1084
1085static void list_tools(void)
1086{
1087 DIR *dir = opendir(VG_(libdir));
1088 struct dirent *de;
1089 int first = 1;
1090
1091 if (dir == NULL) {
1092 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001093 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001094 return;
1095 }
1096
nethercotef4928da2004-06-15 10:54:40 +00001097 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001098 int len = strlen(de->d_name);
1099
njn063c5402004-11-22 16:58:05 +00001100 /* look for vgtool_TOOL.so names */
1101 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1102 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001103 VG_STREQ(de->d_name + len - 3, ".so")) {
1104 if (first) {
1105 fprintf(stderr, "Available tools:\n");
1106 first = 0;
1107 }
1108 de->d_name[len-3] = '\0';
1109 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001110 }
1111 }
1112
1113 closedir(dir);
1114
1115 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001116 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1117 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001118}
1119
1120
1121/* Find and load a tool, and check it looks ok. Also looks to see if there's
1122 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
njn8a97c6d2005-03-31 04:37:24 +00001123static void load_tool( const char *toolname,
nethercote71980f02004-01-24 18:18:54 +00001124 ToolInfo** toolinfo_out, char **preloadpath_out )
1125{
1126 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001127 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001128 char buf[len];
1129 void* handle;
1130 ToolInfo* toolinfo;
1131 char* preloadpath = NULL;
nethercote71980f02004-01-24 18:18:54 +00001132
1133 // XXX: allowing full paths for --tool option -- does it make sense?
1134 // Doesn't allow for vgpreload_<tool>.so.
1135
1136 if (strchr(toolname, '/') != 0) {
1137 /* toolname contains '/', and so must be a pathname */
1138 handle = dlopen(toolname, RTLD_NOW);
1139 } else {
1140 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001141 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001142 handle = dlopen(buf, RTLD_NOW);
1143
1144 if (handle != NULL) {
1145 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1146 if (access(buf, R_OK) == 0) {
1147 preloadpath = strdup(buf);
1148 vg_assert(NULL != preloadpath);
1149 }
1150 }
1151 }
1152
1153 ok = (NULL != handle);
1154 if (!ok) {
1155 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1156 goto bad_load;
1157 }
1158
njn51d827b2005-05-09 01:02:08 +00001159 toolinfo = dlsym(handle, "vgPlain_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001160 ok = (NULL != toolinfo);
1161 if (!ok) {
njn51d827b2005-05-09 01:02:08 +00001162 fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
nethercote71980f02004-01-24 18:18:54 +00001163 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1164 goto bad_load;
1165 }
1166
1167 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
njn51d827b2005-05-09 01:02:08 +00001168 toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
1169 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001170 if (!ok) {
1171 fprintf(stderr, "Error:\n"
1172 " Tool and core interface versions do not match.\n"
njn51d827b2005-05-09 01:02:08 +00001173 " Interface version used by core is: %d (size %d)\n"
1174 " Interface version used by tool is: %d (size %d)\n"
1175 " The version numbers must match.\n",
1176 VG_CORE_INTERFACE_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001177 (Int)sizeof(*toolinfo),
njn51d827b2005-05-09 01:02:08 +00001178 toolinfo->interface_version,
nethercote71980f02004-01-24 18:18:54 +00001179 toolinfo->sizeof_ToolInfo);
1180 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
njn51d827b2005-05-09 01:02:08 +00001181 if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
nethercote996901a2004-08-03 13:29:09 +00001182 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001183 else
nethercote996901a2004-08-03 13:29:09 +00001184 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001185 goto bad_load;
1186 }
1187
njn8a97c6d2005-03-31 04:37:24 +00001188 vg_assert(NULL != toolinfo);
nethercote71980f02004-01-24 18:18:54 +00001189 *toolinfo_out = toolinfo;
1190 *preloadpath_out = preloadpath;
1191 return;
1192
1193
1194 bad_load:
1195 if (handle != NULL)
1196 dlclose(handle);
1197
nethercotef4928da2004-06-15 10:54:40 +00001198 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001199 list_tools();
1200 exit(127);
1201}
1202
nethercotef4928da2004-06-15 10:54:40 +00001203
1204/*====================================================================*/
1205/*=== Command line errors ===*/
1206/*====================================================================*/
1207
njnbe9b47b2005-05-15 16:22:58 +00001208static void revert_to_stderr ( void )
nethercotef4928da2004-06-15 10:54:40 +00001209{
njnbe9b47b2005-05-15 16:22:58 +00001210 vg_assert( !VG_(logging_to_socket) );
nethercotef8548672004-06-21 12:42:35 +00001211 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001212}
1213
1214void VG_(bad_option) ( Char* opt )
1215{
njnbe9b47b2005-05-15 16:22:58 +00001216 revert_to_stderr();
njn02bc4b82005-05-15 17:28:26 +00001217 VG_(printf)("valgrind: Bad option '%s'; aborting.\n", opt);
nethercotef4928da2004-06-15 10:54:40 +00001218 VG_(printf)("valgrind: Use --help for more information.\n");
1219 VG_(exit)(1);
1220}
1221
nethercotef4928da2004-06-15 10:54:40 +00001222static void missing_prog ( void )
1223{
njnbe9b47b2005-05-15 16:22:58 +00001224 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001225 VG_(printf)("valgrind: no program specified\n");
1226 VG_(printf)("valgrind: Use --help for more information.\n");
1227 VG_(exit)(1);
1228}
1229
1230static void config_error ( Char* msg )
1231{
njnbe9b47b2005-05-15 16:22:58 +00001232 revert_to_stderr();
nethercotef4928da2004-06-15 10:54:40 +00001233 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1234 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1235 VG_(exit)(1);
1236}
1237
1238
nethercote71980f02004-01-24 18:18:54 +00001239/*====================================================================*/
1240/*=== Loading the client ===*/
1241/*====================================================================*/
1242
nethercotef4928da2004-06-15 10:54:40 +00001243static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001244 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1245{
1246 // If they didn't specify an executable with --exec, and didn't specify
1247 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001248 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001249 if (cl_argv[0] == NULL ||
1250 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1251 {
nethercotef4928da2004-06-15 10:54:40 +00001252 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001253 }
1254 }
1255
1256 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001257 info->exe_base = VG_(client_base);
1258 info->exe_end = VG_(client_end);
1259 info->argv = cl_argv;
1260
nethercotef4928da2004-06-15 10:54:40 +00001261 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001262 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001263 // Totally zero 'info' before continuing.
1264 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001265 } else {
1266 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001267 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001268 ret = do_exec(exec, info);
1269 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001270 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1271 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001272 exit(127);
1273 }
1274 }
1275
1276 /* Copy necessary bits of 'info' that were filled in */
1277 *client_eip = info->init_eip;
1278 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1279}
1280
nethercote969ecf12004-10-13 17:29:01 +00001281/*====================================================================*/
1282/*=== Address space unpadding ===*/
1283/*====================================================================*/
1284
1285typedef struct {
1286 char* killpad_start;
1287 char* killpad_end;
1288 struct stat* killpad_padstat;
1289} killpad_extra;
1290
1291static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1292 int maj, int min, int ino, void* ex)
1293{
1294 killpad_extra* extra = ex;
1295 void *b, *e;
1296 int res;
1297
1298 vg_assert(NULL != extra->killpad_padstat);
1299
1300 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1301 extra->killpad_padstat->st_ino != ino)
1302 return 1;
1303
1304 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1305 return 1;
1306
1307 if (segstart <= extra->killpad_start)
1308 b = extra->killpad_start;
1309 else
1310 b = segstart;
1311
1312 if (segend >= extra->killpad_end)
1313 e = extra->killpad_end;
1314 else
1315 e = segend;
1316
1317 res = munmap(b, (char *)e-(char *)b);
1318 vg_assert(0 == res);
1319
1320 return 1;
1321}
1322
1323// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001324static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001325{
1326 static struct stat padstat;
1327 killpad_extra extra;
1328 int res;
1329
sewardjb5f6f512005-03-10 23:59:00 +00001330 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001331
1332 res = fstat(padfile, &padstat);
1333 vg_assert(0 == res);
1334 extra.killpad_padstat = &padstat;
1335 extra.killpad_start = start;
1336 extra.killpad_end = end;
1337 foreach_map(killpad, &extra);
1338}
1339
sewardj2c5ffbe2005-03-12 13:32:06 +00001340static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001341{
1342 int res = close(padfile);
1343 vg_assert(0 == res);
1344}
1345
sewardj71bc3cb2005-05-19 00:25:45 +00001346/*====================================================================*/
1347/*=== Command-line: variables, processing, etc ===*/
1348/*====================================================================*/
1349
1350// See pub_{core,tool}_options.h for explanations of all these.
1351
sewardj2c5ffbe2005-03-12 13:32:06 +00001352static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001353{
njn25e49d8e72002-09-23 09:36:25 +00001354 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001355"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001356"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001357" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001358" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001359" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001360" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001361" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001362" -q --quiet run silently; only print error msgs\n"
1363" -v --verbose be more verbose, incl counts of errors\n"
sewardjf178c302005-05-20 02:02:10 +00001364" --xml=yes all output is in XML (Memcheck only)\n"
nethercote77eba602003-11-13 17:35:04 +00001365" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001366" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001367" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001368"\n"
1369" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001370" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001371" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001372" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001373" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001374" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001375"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001376" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001377" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1378" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001379" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001380" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001381" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001382" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001383" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1384" --show-below-main=no|yes continue stack traces below main() [no]\n"
1385" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001386" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001387" --db-attach=no|yes start debugger when errors detected? [no]\n"
1388" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1389" --input-fd=<number> file descriptor for input [0=stdin]\n"
sewardj97724e52005-04-02 23:40:59 +00001390" --max-stackframe=<number> assume stack switch for SP changes larger\n"
1391" than <number> bytes [2000000]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001392"\n";
njn7cf0bd32002-06-08 13:36:03 +00001393
njn25e49d8e72002-09-23 09:36:25 +00001394 Char* usage2 =
1395"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001396" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001397" --sanity-level=<number> level of sanity checking to do [1]\n"
1398" --single-step=no|yes translate each instr separately? [no]\n"
1399" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001400" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001401" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001402" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1403" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001404" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001405" --trace-syscalls=no|yes show all system calls? [no]\n"
1406" --trace-signals=no|yes show signal handling details? [no]\n"
1407" --trace-symtab=no|yes show symbol table details? [no]\n"
sewardjce058b02005-05-01 08:55:38 +00001408" --trace-cfi=no|yes show call-frame-info details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001409" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001410" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001411#if 0
1412" --model-pthreads=yes|no model the pthreads library [no]\n"
1413#endif
1414" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001415"\n"
1416" --vex-iropt-verbosity 0 .. 9 [0]\n"
1417" --vex-iropt-level 0 .. 2 [2]\n"
1418" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001419" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1420" --vex-guest-max-insns 1 .. 100 [50]\n"
1421" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1422"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001423" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001424" 1000 0000 show conversion into IR\n"
1425" 0100 0000 show after initial opt\n"
1426" 0010 0000 show after instrumentation\n"
1427" 0001 0000 show after second opt\n"
1428" 0000 1000 show after tree building\n"
1429" 0000 0100 show selecting insns\n"
1430" 0000 0010 show after reg-alloc\n"
1431" 0000 0001 show final assembly\n"
1432"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001433" debugging options for Valgrind tools that report errors\n"
1434" --dump-error=<number> show translation for basic block associated\n"
1435" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001436"\n";
njn3e884182003-04-15 13:03:23 +00001437
1438 Char* usage3 =
1439"\n"
nethercote71980f02004-01-24 18:18:54 +00001440" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001441"\n"
njn53612422005-03-12 16:22:54 +00001442" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001443" and licensed under the GNU General Public License, version 2.\n"
1444" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001445"\n"
nethercote137bc552003-11-14 17:47:54 +00001446" Tools are copyright and licensed by their authors. See each\n"
1447" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001448"\n";
njn7cf0bd32002-06-08 13:36:03 +00001449
njnbe9b47b2005-05-15 16:22:58 +00001450 // Ensure the message goes to stdout
1451 VG_(clo_log_fd) = 1;
1452 vg_assert( !VG_(logging_to_socket) );
1453
fitzhardinge98abfc72003-12-16 02:05:15 +00001454 VG_(printf)(usage1);
1455 if (VG_(details).name) {
1456 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001457 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001458 VG_TDICT_CALL(tool_print_usage);
fitzhardinge98abfc72003-12-16 02:05:15 +00001459 else
1460 VG_(printf)(" (none)\n");
1461 }
nethercote6c999f22004-01-31 22:55:15 +00001462 if (debug_help) {
1463 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001464
nethercote6c999f22004-01-31 22:55:15 +00001465 if (VG_(details).name) {
1466 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1467
1468 if (VG_(needs).command_line_options)
njn51d827b2005-05-09 01:02:08 +00001469 VG_TDICT_CALL(tool_print_debug_usage);
nethercote6c999f22004-01-31 22:55:15 +00001470 else
1471 VG_(printf)(" (none)\n");
1472 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001473 }
nethercote421281e2003-11-20 16:20:55 +00001474 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001475 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001476}
sewardjde4a1d02002-03-22 01:27:54 +00001477
nethercote71980f02004-01-24 18:18:54 +00001478static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001479 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001480{
nethercote71980f02004-01-24 18:18:54 +00001481 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001482
sewardj8b635a42004-11-22 19:01:47 +00001483 LibVEX_default_VexControl(& VG_(clo_vex_control));
1484
nethercote71980f02004-01-24 18:18:54 +00001485 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001486 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001487
nethercotef6a1d502004-08-09 12:21:57 +00001488 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001489 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001490 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001491
nethercotef6a1d502004-08-09 12:21:57 +00001492 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1493 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001494 *need_help = 1;
1495
nethercotef6a1d502004-08-09 12:21:57 +00001496 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001497 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001498
nethercotef6c99d72004-11-09 14:35:43 +00001499 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001500 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001501
nethercotef6a1d502004-08-09 12:21:57 +00001502 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1503 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001504 }
1505 }
nethercote71980f02004-01-24 18:18:54 +00001506}
1507
nethercote5ee67ca2004-06-22 14:00:09 +00001508static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001509{
nethercotef8548672004-06-21 12:42:35 +00001510 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001511 Int toolname_len = VG_(strlen)(toolname);
njnbe9b47b2005-05-15 16:22:58 +00001512 enum {
1513 VgLogTo_Fd,
1514 VgLogTo_File,
1515 VgLogTo_FileExactly,
1516 VgLogTo_Socket
1517 } log_to = VgLogTo_Fd; // Where is logging output to be sent?
sewardjde4a1d02002-03-22 01:27:54 +00001518
nethercotee1730692003-11-20 10:38:07 +00001519 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001520 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001521
sewardj19d81412002-06-03 01:10:40 +00001522 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001523 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001524 config_error("Please use absolute paths in "
1525 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001526
njnc6168192004-11-29 13:54:10 +00001527// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
sewardj21c6d0f2005-05-02 10:33:44 +00001528#if defined(VGP_x86_linux)
njnca0518d2004-11-26 19:34:36 +00001529 {
sewardjb5f6f512005-03-10 23:59:00 +00001530 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001531 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1532 switch(auxp[0]) {
1533 case AT_SYSINFO:
1534 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1535 break;
1536 }
1537 }
1538 }
1539#endif
sewardjde4a1d02002-03-22 01:27:54 +00001540
nethercotef6a1d502004-08-09 12:21:57 +00001541 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001542
nethercotef6a1d502004-08-09 12:21:57 +00001543 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001544 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001545
thughes3bfd5a02004-07-18 08:05:44 +00001546 /* Look for a colon in the switch name */
1547 while (*colon && *colon != ':' && *colon != '=')
1548 colon++;
nethercote71980f02004-01-24 18:18:54 +00001549
1550 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001551 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001552 if (VG_CLO_STREQN(2, arg, "--") &&
1553 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1554 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1555 {
1556 // prefix matches, convert "--toolname:foo" to "--foo"
1557 if (0)
1558 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001559 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001560 arg[0] = '-';
1561 arg[1] = '-';
1562
1563 } else {
1564 // prefix doesn't match, skip to next arg
1565 continue;
1566 }
1567 }
1568
fitzhardinge98abfc72003-12-16 02:05:15 +00001569 /* Ignore these options - they've already been handled */
njn45270a22005-03-27 01:00:11 +00001570 if (VG_CLO_STREQN( 7, arg, "--tool=")) goto skip_arg;
1571 if (VG_CLO_STREQN( 7, arg, "--exec=")) goto skip_arg;
1572 if (VG_CLO_STREQN(20, arg, "--command-line-only=")) goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001573
njn45270a22005-03-27 01:00:11 +00001574 if ( VG_CLO_STREQ(arg, "--")) goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001575
nethercote71980f02004-01-24 18:18:54 +00001576 else if (VG_CLO_STREQ(arg, "-v") ||
1577 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001578 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001579
nethercote71980f02004-01-24 18:18:54 +00001580 else if (VG_CLO_STREQ(arg, "-q") ||
1581 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001582 VG_(clo_verbosity)--;
1583
sewardj1cf558c2005-04-25 01:36:56 +00001584 else if (VG_CLO_STREQ(arg, "-d")) {
1585 /* do nothing */
1586 }
1587
sewardj71bc3cb2005-05-19 00:25:45 +00001588 else VG_BOOL_CLO(arg, "--xml", VG_(clo_xml))
njn45270a22005-03-27 01:00:11 +00001589 else VG_BOOL_CLO(arg, "--branchpred", VG_(clo_branchpred))
1590 else VG_BOOL_CLO(arg, "--db-attach", VG_(clo_db_attach))
1591 else VG_BOOL_CLO(arg, "--demangle", VG_(clo_demangle))
1592 else VG_BOOL_CLO(arg, "--error-limit", VG_(clo_error_limit))
1593 else VG_BOOL_CLO(arg, "--pointercheck", VG_(clo_pointercheck))
1594 else VG_BOOL_CLO(arg, "--support-elan3", VG_(clo_support_elan3))
1595 else VG_BOOL_CLO(arg, "--show-emwarns", VG_(clo_show_emwarns))
sewardj97724e52005-04-02 23:40:59 +00001596 else VG_NUM_CLO (arg, "--max-stackframe", VG_(clo_max_stackframe))
njn45270a22005-03-27 01:00:11 +00001597 else VG_BOOL_CLO(arg, "--profile", VG_(clo_profile))
1598 else VG_BOOL_CLO(arg, "--run-libc-freeres", VG_(clo_run_libc_freeres))
1599 else VG_BOOL_CLO(arg, "--show-below-main", VG_(clo_show_below_main))
1600 else VG_BOOL_CLO(arg, "--time-stamp", VG_(clo_time_stamp))
1601 else VG_BOOL_CLO(arg, "--track-fds", VG_(clo_track_fds))
1602 else VG_BOOL_CLO(arg, "--trace-children", VG_(clo_trace_children))
1603 else VG_BOOL_CLO(arg, "--trace-sched", VG_(clo_trace_sched))
1604 else VG_BOOL_CLO(arg, "--trace-signals", VG_(clo_trace_signals))
1605 else VG_BOOL_CLO(arg, "--trace-symtab", VG_(clo_trace_symtab))
sewardjce058b02005-05-01 08:55:38 +00001606 else VG_BOOL_CLO(arg, "--trace-cfi", VG_(clo_trace_cfi))
njn45270a22005-03-27 01:00:11 +00001607 else VG_BOOL_CLO(arg, "--trace-redir", VG_(clo_trace_redir))
1608 else VG_BOOL_CLO(arg, "--trace-syscalls", VG_(clo_trace_syscalls))
1609 else VG_BOOL_CLO(arg, "--trace-pthreads", VG_(clo_trace_pthreads))
1610 else VG_BOOL_CLO(arg, "--wait-for-gdb", VG_(clo_wait_for_gdb))
1611 else VG_BOOL_CLO(arg, "--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001612
njn45270a22005-03-27 01:00:11 +00001613 else VG_STR_CLO (arg, "--db-command", VG_(clo_db_command))
1614 else VG_STR_CLO (arg, "--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001615
njn45270a22005-03-27 01:00:11 +00001616 else VG_NUM_CLO (arg, "--dump-error", VG_(clo_dump_error))
1617 else VG_NUM_CLO (arg, "--input-fd", VG_(clo_input_fd))
1618 else VG_NUM_CLO (arg, "--sanity-level", VG_(clo_sanity_level))
1619 else VG_BNUM_CLO(arg, "--num-callers", VG_(clo_backtrace_size), 1,
1620 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001621
njn45270a22005-03-27 01:00:11 +00001622 else VG_BNUM_CLO(arg, "--vex-iropt-verbosity",
sewardj8b635a42004-11-22 19:01:47 +00001623 VG_(clo_vex_control).iropt_verbosity, 0, 10)
njn45270a22005-03-27 01:00:11 +00001624 else VG_BNUM_CLO(arg, "--vex-iropt-level",
sewardj8b635a42004-11-22 19:01:47 +00001625 VG_(clo_vex_control).iropt_level, 0, 2)
njn45270a22005-03-27 01:00:11 +00001626 else VG_BOOL_CLO(arg, "--vex-iropt-precise-memory-exns",
sewardj8b635a42004-11-22 19:01:47 +00001627 VG_(clo_vex_control).iropt_precise_memory_exns)
njn45270a22005-03-27 01:00:11 +00001628 else VG_BNUM_CLO(arg, "--vex-iropt-unroll-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001629 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
njn45270a22005-03-27 01:00:11 +00001630 else VG_BNUM_CLO(arg, "--vex-guest-max-insns",
sewardj8b635a42004-11-22 19:01:47 +00001631 VG_(clo_vex_control).guest_max_insns, 1, 100)
njn45270a22005-03-27 01:00:11 +00001632 else VG_BNUM_CLO(arg, "--vex-guest-chase-thresh",
sewardj8b635a42004-11-22 19:01:47 +00001633 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1634
nethercotef8548672004-06-21 12:42:35 +00001635 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
njnbe9b47b2005-05-15 16:22:58 +00001636 log_to = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001637 VG_(clo_log_name) = NULL;
1638 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001639 }
1640
nethercotef8548672004-06-21 12:42:35 +00001641 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
njnbe9b47b2005-05-15 16:22:58 +00001642 log_to = VgLogTo_File;
nethercotef8548672004-06-21 12:42:35 +00001643 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001644 }
njnd6bc3c32005-03-27 00:44:31 +00001645
sewardj603d4102005-01-11 14:01:02 +00001646 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
njnbe9b47b2005-05-15 16:22:58 +00001647 log_to = VgLogTo_FileExactly;
sewardj603d4102005-01-11 14:01:02 +00001648 VG_(clo_log_name) = &arg[19];
1649 }
sewardjde4a1d02002-03-22 01:27:54 +00001650
nethercotef8548672004-06-21 12:42:35 +00001651 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
njnbe9b47b2005-05-15 16:22:58 +00001652 log_to = VgLogTo_Socket;
nethercotef8548672004-06-21 12:42:35 +00001653 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001654 }
1655
nethercote71980f02004-01-24 18:18:54 +00001656 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001657 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001658 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001659 VG_(message)(Vg_UserMsg,
1660 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001661 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001662 }
nethercote71980f02004-01-24 18:18:54 +00001663 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001664 VG_(clo_n_suppressions)++;
1665 }
sewardjde4a1d02002-03-22 01:27:54 +00001666
sewardjfa8ec112005-01-19 11:55:34 +00001667 /* "stuvwxyz" --> stuvwxyz (binary) */
1668 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1669 Int j;
1670 char* opt = & arg[14];
1671
1672 if (8 != VG_(strlen)(opt)) {
1673 VG_(message)(Vg_UserMsg,
1674 "--trace-flags argument must have 8 digits");
1675 VG_(bad_option)(arg);
1676 }
1677 for (j = 0; j < 8; j++) {
1678 if ('0' == opt[j]) { /* do nothing */ }
1679 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1680 else {
1681 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1682 "contain 0s and 1s");
1683 VG_(bad_option)(arg);
1684 }
1685 }
1686 }
1687
1688 /* "stuvwxyz" --> stuvwxyz (binary) */
1689 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001690 Int j;
nethercote71980f02004-01-24 18:18:54 +00001691 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001692
sewardj2a99cf62004-11-24 10:44:19 +00001693 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001694 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001695 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001696 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001697 }
sewardj8b635a42004-11-22 19:01:47 +00001698 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001699 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001700 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001701 else {
sewardjfa8ec112005-01-19 11:55:34 +00001702 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001703 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001704 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001705 }
1706 }
1707 }
sewardjde4a1d02002-03-22 01:27:54 +00001708
njn45270a22005-03-27 01:00:11 +00001709 else VG_NUM_CLO (arg, "--trace-notbelow", VG_(clo_trace_notbelow))
sewardjc771b292004-11-30 18:55:21 +00001710
sewardjd153fae2005-01-10 17:24:47 +00001711 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1712 VG_(clo_gen_suppressions) = 0;
1713 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1714 VG_(clo_gen_suppressions) = 1;
1715 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1716 VG_(clo_gen_suppressions) = 2;
1717
nethercote71980f02004-01-24 18:18:54 +00001718 else if ( ! VG_(needs).command_line_options
njn51d827b2005-05-09 01:02:08 +00001719 || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001720 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001721 }
njn8c0b3bb2005-03-12 21:20:39 +00001722 skip_arg:
1723 if (arg != vg_argv[i])
1724 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001725 }
1726
sewardj998d40d2004-12-06 14:24:52 +00001727 /* Make VEX control parameters sane */
1728
1729 if (VG_(clo_vex_control).guest_chase_thresh
1730 >= VG_(clo_vex_control).guest_max_insns)
1731 VG_(clo_vex_control).guest_chase_thresh
1732 = VG_(clo_vex_control).guest_max_insns - 1;
1733
1734 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1735 VG_(clo_vex_control).guest_chase_thresh = 0;
1736
1737 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001738
njnf9ebf672003-05-12 21:41:30 +00001739 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001740 VG_(clo_verbosity) = 0;
1741
nethercote04d0fbc2004-01-26 16:48:06 +00001742 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001743 VG_(message)(Vg_UserMsg, "");
1744 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001745 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001746 VG_(message)(Vg_UserMsg,
1747 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001748 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001749 }
1750
njnbe9b47b2005-05-15 16:22:58 +00001751 if (VG_(clo_gen_suppressions) > 0 &&
1752 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
1753 VG_(message)(Vg_UserMsg,
1754 "Can't use --gen-suppressions= with this tool,");
1755 VG_(message)(Vg_UserMsg,
1756 "as it doesn't generate errors.");
1757 VG_(bad_option)("--gen-suppressions=");
1758 }
1759
sewardj71bc3cb2005-05-19 00:25:45 +00001760 /* If we've been asked to emit XML, mash around various other
1761 options so as to constrain the output somewhat, and to remove
1762 any need for user input during the run. */
1763 if (VG_(clo_xml)) {
1764 /* Disable suppression generation (requires user input) */
1765 VG_(clo_gen_suppressions) = 0;
1766 /* Disable attaching to GDB (requires user input) */
1767 VG_(clo_db_attach) = False;
1768 /* Set a known verbosity level */
1769 VG_(clo_verbosity) = 1;
1770 /* Disable error limits (this might be a bad idea!) */
1771 VG_(clo_error_limit) = False;
1772 /* Disable emulation warnings */
1773 VG_(clo_show_emwarns) = False;
1774 /* Disable waiting for GDB to debug Valgrind */
1775 VG_(clo_wait_for_gdb) = False;
1776 /* No file-descriptor leak checking yet */
1777 VG_(clo_track_fds) = False;
1778 /* Also, we want to set options for the leak checker, but that
1779 will have to be done in Memcheck's flag-handling code, not
1780 here. */
1781 }
1782
njnbe9b47b2005-05-15 16:22:58 +00001783 /* All non-logging-related options have been checked. If the logging
1784 option specified is ok, we can switch to it, as we know we won't
1785 have to generate any other command-line-related error messages.
1786 (So far we should be still attached to stderr, so we can show on
1787 the terminal any problems to do with processing command line
1788 opts.)
1789
1790 So set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001791 should be connected to whatever sink has been selected, and we
1792 indiscriminately chuck stuff into it without worrying what the
1793 nature of it is. Oh the wonder of Unix streams. */
1794
njnbe9b47b2005-05-15 16:22:58 +00001795 vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
1796 vg_assert(VG_(logging_to_socket) == False);
sewardj4cf05692002-10-27 20:28:29 +00001797
njnbe9b47b2005-05-15 16:22:58 +00001798 switch (log_to) {
sewardj73cf3bc2002-11-03 03:20:15 +00001799
sewardj4cf05692002-10-27 20:28:29 +00001800 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001801 vg_assert(VG_(clo_log_name) == NULL);
1802 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001803 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001804
sewardj4cf05692002-10-27 20:28:29 +00001805 case VgLogTo_File: {
1806 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001807 Int seq = 0;
1808 Int pid = VG_(getpid)();
1809
nethercotef8548672004-06-21 12:42:35 +00001810 vg_assert(VG_(clo_log_name) != NULL);
1811 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001812
nethercote71980f02004-01-24 18:18:54 +00001813 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001814 if (seq == 0)
1815 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001816 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001817 else
1818 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001819 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001820 seq++;
1821
njnbe9b47b2005-05-15 16:22:58 +00001822 // EXCL: it will fail with EEXIST if the file already exists.
nethercotef8548672004-06-21 12:42:35 +00001823 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001824 = VG_(open)(logfilename,
1825 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1826 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001827 if (eventually_log_fd >= 0) {
1828 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001829 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001830 } else {
njnbe9b47b2005-05-15 16:22:58 +00001831 // If the file already existed, we try the next name. If it
1832 // was some other file error, we give up.
nethercotef8548672004-06-21 12:42:35 +00001833 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001834 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001835 "Can't create/open log file '%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001836 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001837 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001838 "--log-file=<file> (didn't work out for some reason.)");
njnbe9b47b2005-05-15 16:22:58 +00001839 /*NOTREACHED*/
jsgff3c3f1a2003-10-14 22:13:28 +00001840 }
1841 }
1842 }
sewardj603d4102005-01-11 14:01:02 +00001843 break; /* switch (VG_(clo_log_to)) */
1844 }
1845
1846 case VgLogTo_FileExactly: {
sewardj603d4102005-01-11 14:01:02 +00001847 vg_assert(VG_(clo_log_name) != NULL);
1848 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
sewardj603d4102005-01-11 14:01:02 +00001849
1850 eventually_log_fd
njnbe9b47b2005-05-15 16:22:58 +00001851 = VG_(open)(VG_(clo_log_name),
sewardj603d4102005-01-11 14:01:02 +00001852 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1853 VKI_S_IRUSR|VKI_S_IWUSR);
1854 if (eventually_log_fd >= 0) {
1855 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
njnbe9b47b2005-05-15 16:22:58 +00001856 } else {
sewardj603d4102005-01-11 14:01:02 +00001857 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001858 "Can't create/open log file '%s'; giving up!",
sewardj603d4102005-01-11 14:01:02 +00001859 VG_(clo_log_name));
1860 VG_(bad_option)(
1861 "--log-file-exactly=<file> (didn't work out for some reason.)");
1862 /*NOTREACHED*/
1863 }
1864 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001865 }
1866
1867 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001868 vg_assert(VG_(clo_log_name) != NULL);
1869 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1870 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1871 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001872 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001873 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001874 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001875 "of '%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001876 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001877 "--log-socket=");
njnbe9b47b2005-05-15 16:22:58 +00001878 /*NOTREACHED*/
sewardj4cf05692002-10-27 20:28:29 +00001879 }
nethercotef8548672004-06-21 12:42:35 +00001880 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001881 VG_(message)(Vg_UserMsg,
njn02bc4b82005-05-15 17:28:26 +00001882 "valgrind: failed to connect to logging server '%s'.",
nethercotef8548672004-06-21 12:42:35 +00001883 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001884 VG_(message)(Vg_UserMsg,
1885 "Log messages will sent to stderr instead." );
1886 VG_(message)(Vg_UserMsg,
1887 "" );
1888 /* We don't change anything here. */
njnbe9b47b2005-05-15 16:22:58 +00001889 vg_assert(VG_(clo_log_fd) == 2);
sewardj570f8902002-11-03 11:44:36 +00001890 } else {
nethercotef8548672004-06-21 12:42:35 +00001891 vg_assert(eventually_log_fd > 0);
1892 VG_(clo_log_fd) = eventually_log_fd;
njnbe9b47b2005-05-15 16:22:58 +00001893 VG_(logging_to_socket) = True;
sewardj570f8902002-11-03 11:44:36 +00001894 }
sewardj73cf3bc2002-11-03 03:20:15 +00001895 break;
1896 }
sewardj4cf05692002-10-27 20:28:29 +00001897 }
1898
sewardj71bc3cb2005-05-19 00:25:45 +00001899
1900 /* Check that the requested tool actually supports XML output. */
1901 if (VG_(clo_xml) && 0 != VG_(strcmp)(toolname, "memcheck")) {
1902 VG_(clo_xml) = False;
1903 VG_(message)(Vg_UserMsg,
1904 "Currently only Memcheck supports XML output.");
1905 VG_(bad_option)("--xml=yes");
1906 /*NOTREACHED*/
1907 }
1908
njnbe9b47b2005-05-15 16:22:58 +00001909 // Move log_fd into the safe range, so it doesn't conflict with any app fds.
1910 // XXX: this is more or less duplicating the behaviour of the calls to
1911 // VG_(safe_fd)() above, although this does not close the original fd.
1912 // Perhaps the VG_(safe_fd)() calls above should be removed, and this
1913 // code should be replaced with a call to VG_(safe_fd)(). --njn
thughesad1c9562004-06-26 11:27:52 +00001914 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001915 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001916 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1917 else {
nethercotef8548672004-06-21 12:42:35 +00001918 VG_(clo_log_fd) = eventually_log_fd;
1919 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001920 }
1921
sewardj4cf05692002-10-27 20:28:29 +00001922 /* Ok, the logging sink is running now. Print a suitable preamble.
1923 If logging to file or a socket, write details of parent PID and
1924 command line args, to help people trying to interpret the
1925 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001926
sewardj71bc3cb2005-05-19 00:25:45 +00001927 if (VG_(clo_xml)) {
1928 VG_(message)(Vg_UserMsg, "");
sewardj8665d8e2005-06-01 17:35:23 +00001929 VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>");
1930 VG_(message)(Vg_UserMsg, "");
sewardj71bc3cb2005-05-19 00:25:45 +00001931 VG_(message)(Vg_UserMsg, "<valgrindoutput>");
1932 VG_(message)(Vg_UserMsg, "");
1933 VG_(message)(Vg_UserMsg, "<protocolversion>1</protocolversion>");
1934 VG_(message)(Vg_UserMsg, "");
1935 }
1936
1937 HChar* xpre = VG_(clo_xml) ? "<preamble>" : "";
1938 HChar* xpost = VG_(clo_xml) ? "</preamble>" : "";
1939
sewardj83adf412002-05-01 01:25:45 +00001940 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001941 /* Tool details */
sewardj71bc3cb2005-05-19 00:25:45 +00001942 VG_(message)(Vg_UserMsg, "%s%s%s%s, %s.%s",
1943 xpre,
njnd04b7c62002-10-03 14:05:52 +00001944 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001945 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001946 NULL == VG_(details).version
1947 ? (Char*)"" : VG_(details).version,
sewardj71bc3cb2005-05-19 00:25:45 +00001948 VG_(details).description,
1949 xpost);
1950 VG_(message)(Vg_UserMsg, "%s%s%s",
1951 xpre, VG_(details).copyright_author, xpost);
sewardj3b2736a2002-03-24 12:18:35 +00001952
njnd04b7c62002-10-03 14:05:52 +00001953 /* Core details */
1954 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001955 "%sUsing LibVEX rev %s, a library for dynamic binary translation.%s",
1956 xpre, LibVEX_Version(), xpost );
sewardjc7025332004-12-13 18:30:39 +00001957 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001958 "%sCopyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.%s",
1959 xpre, xpost );
sewardjc7025332004-12-13 18:30:39 +00001960 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001961 "%sUsing valgrind-%s, a dynamic binary instrumentation framework.%s",
1962 xpre, VERSION, xpost);
sewardjde4a1d02002-03-22 01:27:54 +00001963 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001964 "%sCopyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.%s",
1965 xpre, xpost );
njnd04b7c62002-10-03 14:05:52 +00001966 }
1967
njnbe9b47b2005-05-15 16:22:58 +00001968 if (VG_(clo_verbosity) > 0 && log_to != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001969 VG_(message)(Vg_UserMsg, "");
1970 VG_(message)(Vg_UserMsg,
1971 "My PID = %d, parent PID = %d. Prog and args are:",
1972 VG_(getpid)(), VG_(getppid)() );
1973 for (i = 0; i < VG_(client_argc); i++)
1974 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1975 }
sewardj71bc3cb2005-05-19 00:25:45 +00001976 else
1977 if (VG_(clo_xml)) {
1978 VG_(message)(Vg_UserMsg, "");
1979 VG_(message)(Vg_UserMsg, "<pid>%d</pid>", VG_(getpid)());
1980 VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>", VG_(getppid)());
sewardj7c9e57c2005-05-24 14:21:45 +00001981 VG_(message)(Vg_UserMsg, "<tool>%s</tool>", toolname);
sewardj71bc3cb2005-05-19 00:25:45 +00001982 VG_(message)(Vg_UserMsg, "");
1983 VG_(message)(Vg_UserMsg, "<argv>");
sewardj8665d8e2005-06-01 17:35:23 +00001984 for (i = 0; i < VG_(client_argc); i++) {
1985 HChar* tag = i==0 ? "exe" : "arg";
1986 VG_(message)(Vg_UserMsg, " <%s>%s</%s>",
1987 tag, VG_(client_argv)[i], tag);
1988 }
sewardj71bc3cb2005-05-19 00:25:45 +00001989 VG_(message)(Vg_UserMsg, "</argv>");
1990 }
sewardj4cf05692002-10-27 20:28:29 +00001991
sewardjde4a1d02002-03-22 01:27:54 +00001992 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001993 Int fd;
njnbe9b47b2005-05-15 16:22:58 +00001994 if (log_to != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00001995 VG_(message)(Vg_DebugMsg, "");
1996 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
1997 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00001998 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00001999 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002000
njn1fd5eb22005-03-13 05:43:23 +00002001 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002002 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002003 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002004 }
nethercotea70f7352004-04-18 12:08:46 +00002005
njn1fd5eb22005-03-13 05:43:23 +00002006 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002007 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2008 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002009 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002010 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00002011# define BUF_LEN 256
nethercotea70f7352004-04-18 12:08:46 +00002012 Char version_buf[BUF_LEN];
2013 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
njnbe9b47b2005-05-15 16:22:58 +00002014 vg_assert(n <= BUF_LEN);
nethercotea70f7352004-04-18 12:08:46 +00002015 if (n > 0) {
2016 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002017 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002018 } else {
njn1fd5eb22005-03-13 05:43:23 +00002019 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002020 }
2021 VG_(close)(fd);
sewardj71bc3cb2005-05-19 00:25:45 +00002022# undef BUF_LEN
nethercotea70f7352004-04-18 12:08:46 +00002023 }
sewardjde4a1d02002-03-22 01:27:54 +00002024 }
2025
fitzhardinge98abfc72003-12-16 02:05:15 +00002026 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002027 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002028 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002029 needs one, load the default */
2030 static const Char default_supp[] = "default.supp";
2031 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2032 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2033 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2034 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2035 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002036 }
2037}
2038
nethercotef6a1d502004-08-09 12:21:57 +00002039// Build the string for VALGRINDCLO.
2040Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2041{
2042 /* If we're tracing the children, then we need to start it
2043 with our starter+arguments, which are copied into VALGRINDCLO,
2044 except the --exec= option is changed if present.
2045 */
2046 Int i;
2047 Char *exec;
2048 Char *cp;
2049 Char *optvar;
2050 Int optlen, execlen;
2051
2052 // All these allocated blocks are not free - because we're either
2053 // going to exec, or panic when we fail.
2054
2055 // Create --exec= option: "--exec=<exename>"
2056 exec = VG_(arena_malloc)(VG_AR_CORE,
2057 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2058 vg_assert(NULL != exec);
2059 VG_(sprintf)(exec, "--exec=%s", exename);
2060
2061 // Allocate space for optvar (may overestimate by counting --exec twice,
2062 // no matter)
2063 optlen = 1;
2064 for (i = 0; i < vg_argc; i++)
2065 optlen += VG_(strlen)(vg_argv[i]) + 1;
2066 optlen += VG_(strlen)(exec)+1;
2067 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2068
2069 // Copy all valgrind args except the old --exec (if present)
2070 // VG_CLO_SEP is the separator.
2071 cp = optvar;
2072 for (i = 1; i < vg_argc; i++) {
2073 Char *arg = vg_argv[i];
2074
2075 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2076 // don't copy existing --exec= arg
2077 } else if (VG_(strcmp)(arg, "--") == 0) {
2078 // stop at "--"
2079 break;
2080 } else {
2081 // copy non "--exec" arg
2082 Int len = VG_(strlen)(arg);
2083 VG_(memcpy)(cp, arg, len);
2084 cp += len;
2085 *cp++ = VG_CLO_SEP;
2086 }
2087 }
2088 // Add the new --exec= option
2089 execlen = VG_(strlen)(exec);
2090 VG_(memcpy)(cp, exec, execlen);
2091 cp += execlen;
2092 *cp++ = VG_CLO_SEP;
2093
2094 *cp = '\0';
2095
2096 return optvar;
2097}
2098
2099// Build "/proc/self/fd/<execfd>".
2100Char* VG_(build_child_exename)( void )
2101{
2102 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2103 vg_assert(NULL != exename);
2104 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2105 return exename;
2106}
2107
sewardjde4a1d02002-03-22 01:27:54 +00002108
nethercote71980f02004-01-24 18:18:54 +00002109/*====================================================================*/
2110/*=== File descriptor setup ===*/
2111/*====================================================================*/
2112
2113static void setup_file_descriptors(void)
2114{
2115 struct vki_rlimit rl;
2116
2117 /* Get the current file descriptor limits. */
2118 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2119 rl.rlim_cur = 1024;
2120 rl.rlim_max = 1024;
2121 }
2122
2123 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002124 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2125 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002126 } else {
2127 rl.rlim_cur = rl.rlim_max;
2128 }
2129
2130 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002131 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2132 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002133
2134 /* Update the soft limit. */
2135 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2136
nethercotef6a1d502004-08-09 12:21:57 +00002137 if (vgexecfd != -1)
2138 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002139 if (VG_(clexecfd) != -1)
2140 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2141}
2142
nethercote71980f02004-01-24 18:18:54 +00002143/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002144/*=== Initialise program data/text, etc. ===*/
2145/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002146
sewardjb5f6f512005-03-10 23:59:00 +00002147static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2148 UInt dev, UInt ino, ULong foffset,
2149 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002150{
nethercote71980f02004-01-24 18:18:54 +00002151 /* Only record valgrind mappings for now, without loading any
2152 symbols. This is so we know where the free space is before we
2153 start allocating more memory (note: heap is OK, it's just mmap
2154 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002155 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
sewardj8c615892005-04-25 02:38:28 +00002156 VG_(debugLog)(2, "main",
2157 "valgrind-seg: %p-%p prot 0x%x file=%s\n",
njna4469a72005-05-08 02:06:33 +00002158 (void*)start, (void*)(start+size), prot, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002159 VG_(map_file_segment)(start, size, prot,
sewardj8c615892005-04-25 02:38:28 +00002160 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2161 dev, ino, foffset, filename);
sewardjb5f6f512005-03-10 23:59:00 +00002162 /* update VG_(valgrind_last) if it looks wrong */
2163 if (start+size > VG_(valgrind_last))
sewardj8c615892005-04-25 02:38:28 +00002164 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002165 }
sewardjde4a1d02002-03-22 01:27:54 +00002166}
2167
nethercote71980f02004-01-24 18:18:54 +00002168// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002169Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002170
sewardjb5f6f512005-03-10 23:59:00 +00002171/*
2172 This second pass adds in client mappings, and loads symbol tables
2173 for all interesting mappings. The trouble is that things can
2174 change as we go, because we're calling the Tool to track memory as
2175 we find it.
2176
2177 So for Valgrind mappings, we don't replace any mappings which
2178 aren't still identical (which will include the .so mappings, so we
2179 will load their symtabs)>
2180 */
2181static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2182 UInt dev, UInt ino, ULong foffset,
2183 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002184{
nethercote71980f02004-01-24 18:18:54 +00002185 UInt flags;
2186 Bool is_stack_segment;
2187 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002188
nethercote71980f02004-01-24 18:18:54 +00002189 is_stack_segment
2190 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002191
sewardj8c615892005-04-25 02:38:28 +00002192 VG_(debugLog)(2, "main",
2193 "any-seg: %p-%p prot 0x%x stack=%d file=%s\n",
njna4469a72005-05-08 02:06:33 +00002194 (void*)start, (void*)(start+size), prot, is_stack_segment,
2195 filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002196
nethercote71980f02004-01-24 18:18:54 +00002197 if (is_stack_segment)
2198 flags = SF_STACK | SF_GROWDOWN;
2199 else
2200 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002201
nethercote71980f02004-01-24 18:18:54 +00002202 if (filename != NULL)
2203 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002204
sewardjb5f6f512005-03-10 23:59:00 +00002205#if 0
2206 // This needs to be fixed properly. jrs 20050307
2207 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2208 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002209
sewardjb5f6f512005-03-10 23:59:00 +00002210 /* We have to be a bit careful about inserting new mappings into
2211 the Valgrind part of the address space. We're actively
2212 changing things as we parse these mappings, particularly in
2213 shadow memory, and so we don't want to overwrite those
2214 changes. Therefore, we only insert/update a mapping if it is
2215 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002216
sewardjb5f6f512005-03-10 23:59:00 +00002217 NOTE: we're only talking about the Segment list mapping
2218 metadata; this doesn't actually mmap anything more. */
2219 if (filename || (s && s->addr == start && s->len == size)) {
2220 flags |= SF_VALGRIND;
2221 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2222 } else {
2223 /* assert range is already mapped */
2224 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2225 }
2226 } else
2227#endif
2228 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2229
2230 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2231 VG_TRACK( new_mem_startup, start, size,
2232 !!(prot & VKI_PROT_READ),
2233 !!(prot & VKI_PROT_WRITE),
2234 !!(prot & VKI_PROT_EXEC));
2235 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002236
nethercote71980f02004-01-24 18:18:54 +00002237 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002238 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002239 vg_assert(0 != r_esp);
2240 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002241 if (0) {
2242 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002243 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002244 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2245 r_esp, start+size);
2246 }
nethercote71980f02004-01-24 18:18:54 +00002247 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002248 // what's this for?
2249 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002250 }
sewardjde4a1d02002-03-22 01:27:54 +00002251}
2252
2253
nethercote71980f02004-01-24 18:18:54 +00002254/*====================================================================*/
2255/*=== Sanity check machinery (permanently engaged) ===*/
2256/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002257
2258/* A fast sanity check -- suitable for calling circa once per
2259 millisecond. */
2260
nethercote885dd912004-08-03 23:14:00 +00002261void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002262{
sewardjb5f6f512005-03-10 23:59:00 +00002263 ThreadId tid;
2264
njn37cea302002-09-30 11:24:00 +00002265 VGP_PUSHCC(VgpCoreCheapSanity);
2266
nethercote27fec902004-06-16 21:26:32 +00002267 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002268
2269 /* --- First do all the tests that we can do quickly. ---*/
2270
nethercote297effd2004-08-02 15:07:57 +00002271 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002272
njn25e49d8e72002-09-23 09:36:25 +00002273 /* Check stuff pertaining to the memory check system. */
2274
2275 /* Check that nobody has spuriously claimed that the first or
2276 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002277 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002278 VGP_PUSHCC(VgpToolCheapSanity);
njn51d827b2005-05-09 01:02:08 +00002279 vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002280 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002281 }
njn25e49d8e72002-09-23 09:36:25 +00002282
2283 /* --- Now some more expensive checks. ---*/
2284
2285 /* Once every 25 times, check some more expensive stuff. */
2286 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002287 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002288 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002289
njn37cea302002-09-30 11:24:00 +00002290 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002291 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002292
2293# if 0
2294 { void zzzmemscan(void); zzzmemscan(); }
2295# endif
2296
nethercote297effd2004-08-02 15:07:57 +00002297 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002298 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002299
2300 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002301 VGP_PUSHCC(VgpToolExpensiveSanity);
njn51d827b2005-05-09 01:02:08 +00002302 vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
njn4be0a692004-11-22 18:10:36 +00002303 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002304 }
sewardjb5f6f512005-03-10 23:59:00 +00002305
2306 /* Check that Segments and /proc/self/maps match up */
2307 //vg_assert(VG_(sanity_check_memory)());
2308
2309 /* Look for stack overruns. Visit all threads. */
2310 for(tid = 1; tid < VG_N_THREADS; tid++) {
njn990e90c2005-04-05 02:49:09 +00002311 SSizeT remains;
sewardjb5f6f512005-03-10 23:59:00 +00002312
2313 if (VG_(threads)[tid].status == VgTs_Empty ||
2314 VG_(threads)[tid].status == VgTs_Zombie)
2315 continue;
2316
2317 remains = VGA_(stack_unused)(tid);
2318 if (remains < VKI_PAGE_SIZE)
sewardj71bc3cb2005-05-19 00:25:45 +00002319 VG_(message)(Vg_DebugMsg,
2320 "WARNING: Thread %d is within %d bytes "
2321 "of running out of stack!",
2322 tid, remains);
sewardjb5f6f512005-03-10 23:59:00 +00002323 }
2324
njn25e49d8e72002-09-23 09:36:25 +00002325 /*
nethercote297effd2004-08-02 15:07:57 +00002326 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002327 */
njn37cea302002-09-30 11:24:00 +00002328 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002329 }
2330
nethercote27fec902004-06-16 21:26:32 +00002331 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002332 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002333 /* Check sanity of the low-level memory manager. Note that bugs
2334 in the client's code can cause this to fail, so we don't do
2335 this check unless specially asked for. And because it's
2336 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002337 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002338 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002339 }
njn37cea302002-09-30 11:24:00 +00002340 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002341}
nethercote71980f02004-01-24 18:18:54 +00002342
2343
2344/*====================================================================*/
2345/*=== main() ===*/
2346/*====================================================================*/
2347
nethercotec314eba2004-07-15 12:59:41 +00002348/*
2349 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002350 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002351 loads the client executable (and the dynamic linker, if necessary)
2352 into the client part, and calls into Valgrind proper.
2353
2354 The code is careful not to allow spurious mappings to appear in the
2355 wrong parts of the address space. In particular, to make sure
2356 dlopen puts things in the right place, it will pad out the forbidden
2357 chunks of address space so that dlopen is forced to put things where
2358 we want them.
2359
2360 The memory map it creates is:
2361
njn311c5d82005-05-15 21:03:42 +00002362 client_base +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002363 | client address space |
2364 : :
2365 : :
2366 | client stack |
2367 client_end +-------------------------+
2368 | redzone |
2369 shadow_base +-------------------------+
2370 | |
nethercote996901a2004-08-03 13:29:09 +00002371 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002372 | (may be 0 sized) |
2373 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002374 valgrind_base +-------------------------+
2375 | kickstart executable |
2376 | valgrind heap vvvvvvvvv| (barely used)
2377 - -
2378 | valgrind .so files |
2379 | and mappings |
2380 - -
2381 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002382 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002383 : kernel :
2384
2385 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2386 VG_(mmap)(), we need to build the segment skip-list, so we know where
2387 we can put things. However, building that structure requires
2388 allocating memory. So we need to a bootstrapping process. It's done
2389 by making VG_(arena_malloc)() have a special static superblock that's
2390 used for the first 1MB's worth of allocations. This is enough to
2391 build the segment skip-list.
2392*/
2393
thughes4ad52d02004-06-27 17:37:21 +00002394
sewardj1cf558c2005-04-25 01:36:56 +00002395/* This may be needed before m_mylibc is OK to run. */
2396static Int local_strcmp ( const HChar* s1, const HChar* s2 )
2397{
2398 while (True) {
2399 if (*s1 == 0 && *s2 == 0) return 0;
2400 if (*s1 == 0) return -1;
2401 if (*s2 == 0) return 1;
2402
2403 if (*(UChar*)s1 < *(UChar*)s2) return -1;
2404 if (*(UChar*)s1 > *(UChar*)s2) return 1;
2405
2406 s1++; s2++;
2407 }
2408}
2409
2410
sewardjb5f6f512005-03-10 23:59:00 +00002411int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002412{
2413 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002414 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002415 const char *exec = NULL;
2416 char *preload; /* tool-specific LD_PRELOAD .so */
2417 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002418 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002419 struct exeinfo info;
2420 ToolInfo *toolinfo = NULL;
nethercote71980f02004-01-24 18:18:54 +00002421 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002422 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002423 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002424 struct vki_rlimit zero = { 0, 0 };
sewardj1cf558c2005-04-25 01:36:56 +00002425 Int padfile, loglevel, i;
nethercote71980f02004-01-24 18:18:54 +00002426
2427 //============================================================
2428 // Nb: startup is complex. Prerequisites are shown at every step.
2429 //
2430 // *** Be very careful when messing with the order ***
2431 //============================================================
2432
sewardj1cf558c2005-04-25 01:36:56 +00002433 //--------------------------------------------------------------
2434 // Start up the logging mechanism
2435 // p: none
2436 //--------------------------------------------------------------
2437 /* Start the debugging-log system ASAP. First find out how many
2438 "-d"s were specified. This is a pre-scan of the command line. */
2439 loglevel = 0;
2440 for (i = 1; i < argc; i++) {
sewardj10759312005-05-30 23:52:47 +00002441 if (argv[i][0] != '-')
2442 break;
2443 if (0 == local_strcmp(argv[i], "--"))
2444 break;
2445 if (0 == local_strcmp(argv[i], "-d"))
2446 loglevel++;
sewardj1cf558c2005-04-25 01:36:56 +00002447 }
2448
2449 /* ... and start the debug logger. Now we can safely emit logging
2450 messages all through startup. */
sewardj10759312005-05-30 23:52:47 +00002451 VG_(debugLog_startup)(loglevel, "Stage 2 (main)");
sewardj1cf558c2005-04-25 01:36:56 +00002452
nethercotef4928da2004-06-15 10:54:40 +00002453 //============================================================
2454 // Command line argument handling order:
2455 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002456 // (including the tool-specific usage)
2457 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002458 // * Then, if client is missing, abort with error msg
2459 // * Then, if any cmdline args are bad, abort with error msg
2460 //============================================================
2461
fitzhardingeb50068f2004-02-24 23:42:55 +00002462 // Get the current process datasize rlimit, and set it to zero.
2463 // This prevents any internal uses of brk() from having any effect.
2464 // We remember the old value so we can restore it on exec, so that
2465 // child processes will have a reasonable brk value.
2466 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2467 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2468 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002469
2470 // Get the current process stack rlimit.
2471 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2472
nethercote71980f02004-01-24 18:18:54 +00002473 //--------------------------------------------------------------
2474 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002475 // p: none
nethercote71980f02004-01-24 18:18:54 +00002476 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002477 VG_(debugLog)(1, "main", "Doing scan_auxv()\n");
nethercotec25c4492004-10-18 11:52:17 +00002478 {
sewardj1fbc1a52005-04-25 02:05:54 +00002479 void* init_sp = argv - 1;
2480 padfile = scan_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +00002481 }
2482
2483 //--------------------------------------------------------------
2484 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002485 // p: none
nethercote71980f02004-01-24 18:18:54 +00002486 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002487 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002488 if (cp != NULL)
2489 VG_(libdir) = cp;
2490 }
2491
2492 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002493 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2494 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002495 // p: none
nethercote71980f02004-01-24 18:18:54 +00002496 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002497 VG_(debugLog)(1, "main", "Preprocess command line opts\n");
nethercotef6a1d502004-08-09 12:21:57 +00002498 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002499 pre_process_cmd_line_options(&need_help, &tool, &exec);
2500
sewardj10759312005-05-30 23:52:47 +00002501 /* If this process was created by exec done by another Valgrind
2502 process, the arguments will only show up at this point. Hence
2503 we need to also snoop around in vg_argv to see if anyone is
2504 asking for debug logging. */
2505 if (loglevel == 0) {
2506 for (i = 1; i < vg_argc; i++) {
2507 if (vg_argv[i][0] != '-')
2508 break;
2509 if (0 == local_strcmp(vg_argv[i], "--"))
2510 break;
2511 if (0 == local_strcmp(vg_argv[i], "-d"))
2512 loglevel++;
2513 }
2514 VG_(debugLog_startup)(loglevel, "Stage 2 (second go)");
2515 }
2516
nethercote71980f02004-01-24 18:18:54 +00002517 //==============================================================
2518 // Nb: once a tool is specified, the tool.so must be loaded even if
2519 // they specified --help or didn't specify a client program.
2520 //==============================================================
2521
2522 //--------------------------------------------------------------
2523 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002524 // p: set-libdir [for VG_(libdir)]
2525 // p: pre_process_cmd_line_options() [for 'tool']
2526 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002527 VG_(debugLog)(1, "main", "Loading tool\n");
njn8a97c6d2005-03-31 04:37:24 +00002528 load_tool(tool, &toolinfo, &preload);
nethercote71980f02004-01-24 18:18:54 +00002529
2530 //==============================================================
2531 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002532 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002533 //==============================================================
2534
2535 //--------------------------------------------------------------
2536 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002537 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002538 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002539 VG_(debugLog)(1, "main", "Laying out remaining space\n");
nethercote31779c72004-07-30 21:50:15 +00002540 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002541
2542 //--------------------------------------------------------------
2543 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002544 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2545 // p: layout_remaining_space [so there's space]
2546 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002547 VG_(debugLog)(1, "main", "Loading client\n");
nethercotef4928da2004-06-15 10:54:40 +00002548 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002549
2550 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002551 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002552 // p: layout_remaining_space() [everything must be mapped in before now]
2553 // p: load_client() [ditto]
2554 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002555 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2556 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //--------------------------------------------------------------
2559 // Set up client's environment
2560 // p: set-libdir [for VG_(libdir)]
2561 // p: load_tool() [for 'preload']
2562 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002563 VG_(debugLog)(1, "main", "Setup client env\n");
sewardjb5f6f512005-03-10 23:59:00 +00002564 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002565
2566 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002567 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002568 // p: load_client() [for 'info']
2569 // p: fix_environment() [for 'env']
2570 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002571 VG_(debugLog)(1, "main", "Setup client stack\n");
nethercotec25c4492004-10-18 11:52:17 +00002572 {
sewardj1fbc1a52005-04-25 02:05:54 +00002573 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002574
sewardj1fbc1a52005-04-25 02:05:54 +00002575 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2576 &client_auxv);
2577 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002578 }
nethercote71980f02004-01-24 18:18:54 +00002579
sewardj1fbc1a52005-04-25 02:05:54 +00002580 VG_(debugLog)(2, "main",
2581 "Client info: "
2582 "entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2583 (void*)client_eip, (void*)sp_at_startup, vg_argc,
2584 (void*)VG_(brk_base) );
nethercote71980f02004-01-24 18:18:54 +00002585
2586 //==============================================================
2587 // Finished setting up operating environment. Now initialise
2588 // Valgrind. (This is where the old VG_(main)() started.)
2589 //==============================================================
2590
2591 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002592 // setup file descriptors
2593 // p: n/a
2594 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002595 VG_(debugLog)(1, "main", "Setup file descriptors\n");
nethercote71980f02004-01-24 18:18:54 +00002596 setup_file_descriptors();
2597
2598 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002599 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002600 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002601 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002602 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 1)\n");
nethercotec314eba2004-07-15 12:59:41 +00002603 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2604
2605 //==============================================================
2606 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2607 //==============================================================
2608
2609 //--------------------------------------------------------------
2610 // Init tool: pre_clo_init, process cmd line, post_clo_init
2611 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
njn8a97c6d2005-03-31 04:37:24 +00002612 // p: load_tool() [for 'toolinfo']
nethercotec314eba2004-07-15 12:59:41 +00002613 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2614 // p: parse_procselfmaps [so VG segments are setup so tool can
2615 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002616 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002617 VG_(debugLog)(1, "main", "Initialise the tool\n");
njnd2252832004-11-26 10:53:33 +00002618 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002619 VG_(sanity_check_needs)();
2620
nethercotef4928da2004-06-15 10:54:40 +00002621 // If --tool and --help/--help-debug was given, now give the core+tool
2622 // help message
nethercotef4928da2004-06-15 10:54:40 +00002623 if (need_help) {
2624 usage(/*--help-debug?*/2 == need_help);
2625 }
nethercotec314eba2004-07-15 12:59:41 +00002626 process_cmd_line_options(client_auxv, tool);
2627
njn51d827b2005-05-09 01:02:08 +00002628 VG_TDICT_CALL(tool_post_clo_init);
nethercotef4928da2004-06-15 10:54:40 +00002629
2630 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002631 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002632 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002633 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002634 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002635 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002636 VG_(debugLog)(1, "main", "Parse /proc/self/maps (round 2)\n");
nethercote4ad74312004-10-26 09:59:49 +00002637 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002638 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002639 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002640
sewardj21c6d0f2005-05-02 10:33:44 +00002641#if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
nethercotec314eba2004-07-15 12:59:41 +00002642 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002643 // Protect client trampoline page (which is also sysinfo stuff)
2644 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002645 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002646 {
2647 Segment *seg;
2648 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2649 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
sewardj21c6d0f2005-05-02 10:33:44 +00002650
sewardjb5f6f512005-03-10 23:59:00 +00002651 /* Make sure this segment isn't treated as stack */
2652 seg = VG_(find_segment)(VG_(client_trampoline_code));
2653 if (seg)
2654 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2655 }
sewardj21c6d0f2005-05-02 10:33:44 +00002656#endif
sewardjb5f6f512005-03-10 23:59:00 +00002657
nethercotec314eba2004-07-15 12:59:41 +00002658 //==============================================================
2659 // Can use VG_(map)() after segments set up
2660 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002661
2662 //--------------------------------------------------------------
2663 // Allow GDB attach
2664 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2665 //--------------------------------------------------------------
2666 /* Hook to delay things long enough so we can get the pid and
2667 attach GDB in another shell. */
2668 if (VG_(clo_wait_for_gdb)) {
sewardj1fbc1a52005-04-25 02:05:54 +00002669 VG_(debugLog)(1, "main", "Wait for GDB\n");
sewardj93ab8572005-02-06 14:10:40 +00002670 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2671 /* jrs 20050206: I don't understand why this works on x86. On
2672 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2673 work. */
2674 /* do "jump *$eip" to skip this in gdb (x86) */
2675 //VG_(do_syscall0)(__NR_pause);
2676 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002677 }
2678
sewardjb5d320c2005-03-13 18:57:15 +00002679 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002680 // Search for file descriptors that are inherited from our parent
2681 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2682 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002683 if (VG_(clo_track_fds)) {
2684 VG_(debugLog)(1, "main", "Init preopened fds\n");
nethercote71980f02004-01-24 18:18:54 +00002685 VG_(init_preopened_fds)();
sewardj1fbc1a52005-04-25 02:05:54 +00002686 }
nethercote71980f02004-01-24 18:18:54 +00002687
2688 //--------------------------------------------------------------
2689 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002690 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2691 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002692 VG_(debugLog)(1, "main", "Initialise scheduler\n");
nethercote71980f02004-01-24 18:18:54 +00002693 VG_(scheduler_init)();
2694
2695 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002696 // Initialise the pthread model
2697 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002698 // load_client() [for 'client_eip']
2699 // setup_client_stack() [for 'sp_at_startup']
2700 // setup_scheduler() [for the rest of state 1 stuff]
2701 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002702 VG_(debugLog)(1, "main", "Initialise thread 1's state\n");
sewardj2a99cf62004-11-24 10:44:19 +00002703 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002704
2705 // Tell the tool that we just wrote to the registers.
2706 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2707 sizeof(VexGuestArchState));
2708
sewardj2a99cf62004-11-24 10:44:19 +00002709 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002710 // Initialise the pthread model
2711 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002712 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002713 //if (VG_(clo_model_pthreads))
2714 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002715
2716 //--------------------------------------------------------------
2717 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002718 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002719 //--------------------------------------------------------------
2720 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
sewardj1fbc1a52005-04-25 02:05:54 +00002721 VG_(debugLog)(1, "main", "Initialise signal management\n");
nethercote71980f02004-01-24 18:18:54 +00002722 VG_(sigstartup_actions)();
2723
2724 //--------------------------------------------------------------
2725 // Perhaps we're profiling Valgrind?
2726 // p: process_cmd_line_options() [for VG_(clo_profile)]
2727 // p: others?
2728 //
2729 // XXX: this seems to be broken? It always says the tool wasn't built
2730 // for profiling; vg_profile.c's functions don't seem to be overriding
2731 // vg_dummy_profile.c's?
2732 //
2733 // XXX: want this as early as possible. Looking for --profile
2734 // in pre_process_cmd_line_options() could get it earlier.
2735 //--------------------------------------------------------------
2736 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002737 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002738
2739 VGP_PUSHCC(VgpStartup);
2740
2741 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002742 // Read suppression file
2743 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2744 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002745 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2746 VG_(debugLog)(1, "main", "Load suppressions\n");
nethercote71980f02004-01-24 18:18:54 +00002747 VG_(load_suppressions)();
sewardj1fbc1a52005-04-25 02:05:54 +00002748 }
nethercote71980f02004-01-24 18:18:54 +00002749
2750 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002751 // Initialise translation table and translation cache
2752 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2753 // aren't identified as part of the client, which would waste
2754 // > 20M of virtual address space.]
2755 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002756 VG_(debugLog)(1, "main", "Initialise TT/TC\n");
nethercote71980f02004-01-24 18:18:54 +00002757 VG_(init_tt_tc)();
2758
2759 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002760 // Read debug info to find glibc entry points to intercept
2761 // p: parse_procselfmaps? [XXX for debug info?]
2762 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2763 //--------------------------------------------------------------
sewardj1fbc1a52005-04-25 02:05:54 +00002764 VG_(debugLog)(1, "main", "Initialise redirects\n");
sewardjb5d320c2005-03-13 18:57:15 +00002765 VG_(setup_code_redirect_table)();
2766
2767 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002768 // Verbosity message
2769 // p: end_rdtsc_calibration [so startup message is printed first]
2770 //--------------------------------------------------------------
sewardj71bc3cb2005-05-19 00:25:45 +00002771 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml))
nethercote71980f02004-01-24 18:18:54 +00002772 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2773 if (VG_(clo_verbosity) > 0)
2774 VG_(message)(Vg_UserMsg, "");
2775
2776 //--------------------------------------------------------------
2777 // Setup pointercheck
njn04e16982005-05-31 00:23:43 +00002778 // p: layout_remaining_space() [for VG_(client_{base,end})]
nethercote71980f02004-01-24 18:18:54 +00002779 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2780 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002781 if (VG_(clo_pointercheck))
njn04e16982005-05-31 00:23:43 +00002782 VG_(clo_pointercheck) =
2783 VGA_(setup_pointercheck)( VG_(client_base), VG_(client_end));
nethercote71980f02004-01-24 18:18:54 +00002784
nethercote71980f02004-01-24 18:18:54 +00002785 //--------------------------------------------------------------
2786 // Run!
2787 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002788 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002789
sewardj71bc3cb2005-05-19 00:25:45 +00002790 if (VG_(clo_xml)) {
2791 VG_(message)(Vg_UserMsg, "<status>RUNNING</status>");
2792 VG_(message)(Vg_UserMsg, "");
2793 }
2794
sewardj1fbc1a52005-04-25 02:05:54 +00002795 VG_(debugLog)(1, "main", "Running thread 1\n");
sewardj1d887112005-05-30 21:44:08 +00002796 /* As a result of the following call, the last thread standing
2797 eventually winds up running VG_(shutdown_actions_NORETURN) just
2798 below. */
2799 VGP_(main_thread_wrapper_NORETURN)(1);
nethercote71980f02004-01-24 18:18:54 +00002800
sewardj1d887112005-05-30 21:44:08 +00002801 /*NOTREACHED*/
2802 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +00002803}
2804
2805
2806/* Do everything which needs doing when the last thread exits */
sewardj1d887112005-05-30 21:44:08 +00002807void VG_(shutdown_actions_NORETURN) ( ThreadId tid,
2808 VgSchedReturnCode tids_schedretcode )
sewardjb5f6f512005-03-10 23:59:00 +00002809{
sewardj1d887112005-05-30 21:44:08 +00002810 VG_(debugLog)(1, "main", "entering VG_(shutdown_actions_NORETURN)\n");
2811
2812 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +00002813 vg_assert(VG_(is_running_thread)(tid));
2814
2815 // Wait for all other threads to exit.
2816 VGA_(reap_threads)(tid);
2817
2818 VG_(clo_model_pthreads) = False;
2819
2820 // Clean the client up before the final report
2821 VGA_(final_tidyup)(tid);
2822
2823 // OK, done
2824 VG_(exit_thread)(tid);
2825
2826 /* should be no threads left */
2827 vg_assert(VG_(count_living_threads)() == 0);
2828
2829 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002830 //--------------------------------------------------------------
2831 // Finalisation: cleanup, messages, etc. Order no so important, only
2832 // affects what order the messages come.
2833 //--------------------------------------------------------------
2834 if (VG_(clo_verbosity) > 0)
2835 VG_(message)(Vg_UserMsg, "");
2836
sewardj71bc3cb2005-05-19 00:25:45 +00002837 if (VG_(clo_xml)) {
sewardj9f297ca2005-05-20 02:29:52 +00002838 if (VG_(needs).core_errors || VG_(needs).tool_errors) {
2839 VG_(show_error_counts_as_XML)();
2840 VG_(message)(Vg_UserMsg, "");
2841 }
sewardj71bc3cb2005-05-19 00:25:45 +00002842 VG_(message)(Vg_UserMsg, "<status>FINISHED</status>");
2843 VG_(message)(Vg_UserMsg, "");
2844 }
2845
nethercote71980f02004-01-24 18:18:54 +00002846 /* Print out file descriptor summary and stats. */
2847 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002848 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002849
njn95ec8702004-11-22 16:46:13 +00002850 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002851 VG_(show_all_errors)();
2852
njn51d827b2005-05-09 01:02:08 +00002853 VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
nethercote71980f02004-01-24 18:18:54 +00002854
sewardj71bc3cb2005-05-19 00:25:45 +00002855 if (VG_(clo_xml)) {
2856 VG_(message)(Vg_UserMsg, "");
2857 VG_(message)(Vg_UserMsg, "</valgrindoutput>");
2858 VG_(message)(Vg_UserMsg, "");
2859 }
2860
nethercote885dd912004-08-03 23:14:00 +00002861 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002862
2863 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002864 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002865
nethercote71980f02004-01-24 18:18:54 +00002866 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002867 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002868 if (VG_(clo_profile_flags) > 0)
2869 VG_(show_BB_profile)();
2870
sewardj8b635a42004-11-22 19:01:47 +00002871 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002872 if (0)
2873 LibVEX_ShowAllocStats();
sewardj1d887112005-05-30 21:44:08 +00002874
2875 /* Ok, finally exit in the os-specific way. In short, if the
2876 (last) thread exited by calling sys_exit, do likewise; if the
2877 (last) thread stopped due to a fatal signal, terminate the
2878 entire system with that same fatal signal. */
2879 VGO_(terminate_NORETURN)( tid, tids_schedretcode );
njne96be672005-05-08 19:08:54 +00002880}
sewardj8b635a42004-11-22 19:01:47 +00002881
sewardjde4a1d02002-03-22 01:27:54 +00002882/*--------------------------------------------------------------------*/
njn04e16982005-05-31 00:23:43 +00002883/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00002884/*--------------------------------------------------------------------*/