blob: c901cf9e9573e1717cf3780d4620ce5a143d1e25 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
njnd01fef72005-03-25 23:35:48 +000035#include "pub_core_execontext.h"
nethercote71980f02004-01-24 18:18:54 +000036
37#include <dirent.h>
38#include <dlfcn.h>
39#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000040#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000041#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000042#include <string.h>
43#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000046#include <sys/wait.h>
47#include <unistd.h>
48
sewardjb5f6f512005-03-10 23:59:00 +000049#include "memcheck/memcheck.h"
50
thughes74b8de22004-04-22 18:12:31 +000051#ifndef AT_DCACHEBSIZE
52#define AT_DCACHEBSIZE 19
53#endif /* AT_DCACHEBSIZE */
54
55#ifndef AT_ICACHEBSIZE
56#define AT_ICACHEBSIZE 20
57#endif /* AT_ICACHEBSIZE */
58
59#ifndef AT_UCACHEBSIZE
60#define AT_UCACHEBSIZE 21
61#endif /* AT_UCACHEBSIZE */
62
nethercote71980f02004-01-24 18:18:54 +000063#ifndef AT_SYSINFO
64#define AT_SYSINFO 32
65#endif /* AT_SYSINFO */
66
67#ifndef AT_SYSINFO_EHDR
68#define AT_SYSINFO_EHDR 33
69#endif /* AT_SYSINFO_EHDR */
70
71#ifndef AT_SECURE
72#define AT_SECURE 23 /* secure mode boolean */
73#endif /* AT_SECURE */
74
nethercote71980f02004-01-24 18:18:54 +000075/* redzone gap between client address space and shadow */
76#define REDZONE_SIZE (1 * 1024*1024)
77
78/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000079#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000080
nethercotee2097312004-06-27 12:29:56 +000081/* Proportion of client space for its heap (rest is for mmaps + stack) */
82#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000083
njn14319cc2005-03-13 06:26:22 +000084/* Number of file descriptors that Valgrind tries to reserve for
85 it's own use - just a small constant. */
86#define N_RESERVED_FDS (10)
87
88/* Default debugger command. */
89#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
90
nethercote71980f02004-01-24 18:18:54 +000091/*====================================================================*/
92/*=== Global entities not referenced from generated code ===*/
93/*====================================================================*/
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000096 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000097 ------------------------------------------------------------------ */
98
nethercote71980f02004-01-24 18:18:54 +000099/* Client address space, lowest to highest (see top of ume.c) */
100Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(client_end);
102Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000103Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000104Addr VG_(clstk_base);
105Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000106
107Addr VG_(brk_base); /* start of brk */
108Addr VG_(brk_limit); /* current brk */
109
nethercote996901a2004-08-03 13:29:09 +0000110Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000112
113Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000114
nethercote820bd8c2004-09-07 23:04:49 +0000115// Note that VG_(valgrind_last) names the last byte of the section, whereas
116// the VG_(*_end) vars name the byte one past the end of the section.
117Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000118
nethercote73b526f2004-10-31 18:48:21 +0000119struct vki_rlimit VG_(client_rlimit_data);
120struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000121
fitzhardinge98abfc72003-12-16 02:05:15 +0000122/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000123static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000124
125/* client executable */
126Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000127
128/* Path to library directory */
129const Char *VG_(libdir) = VG_LIBDIR;
130
131/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000132static Int vg_argc;
133static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000134
sewardjb5f6f512005-03-10 23:59:00 +0000135/* The master thread the one which will be responsible for mopping
136 everything up at exit. Normally it is tid 1, since that's the
137 first thread created, but it may be something else after a
138 fork(). */
139ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000140
thughesad1c9562004-06-26 11:27:52 +0000141/* Application-visible file descriptor limits */
142Int VG_(fd_soft_limit) = -1;
143Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000144
nethercote4ad74312004-10-26 09:59:49 +0000145/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000146 envp[] as extracted from the client's stack at startup-time. */
147Int VG_(client_argc);
148Char** VG_(client_argv);
149Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000150
njn16de5572004-11-27 14:27:21 +0000151// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000152OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000153
sewardj51ac0872004-12-21 01:20:49 +0000154/* Indicates what arch and subarch we are running on. */
155VexArch VG_(vex_arch) = VexArch_INVALID;
156VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
157
158
sewardjde4a1d02002-03-22 01:27:54 +0000159/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000160 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000161 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* Counts downwards in VG_(run_innerloop). */
164UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000165
166/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000167ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/* Tell the logging mechanism whether we are logging to a file
170 descriptor or a socket descriptor. */
171Bool VG_(logging_to_filedes) = True;
172
sewardj73cf3bc2002-11-03 03:20:15 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/*====================================================================*/
175/*=== Counters, for profiling purposes only ===*/
176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000177
sewardjde4a1d02002-03-22 01:27:54 +0000178/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000179static UInt sanity_fast_count = 0;
180static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000181
nethercote3a42fb82004-08-03 18:08:50 +0000182static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000183{
nethercote3a42fb82004-08-03 18:08:50 +0000184 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000185 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000187 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000188
nethercote3a42fb82004-08-03 18:08:50 +0000189 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000190 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000191
nethercote71980f02004-01-24 18:18:54 +0000192 VG_(message)(Vg_DebugMsg,
193 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000194 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000195
njn9271cbc2005-03-13 05:38:25 +0000196 VG_(print_ExeContext_stats)();
197
nethercote3a42fb82004-08-03 18:08:50 +0000198 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000199 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000200 VG_(message)(Vg_DebugMsg, "");
201 VG_(message)(Vg_DebugMsg,
202 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000203 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000204 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000205 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000206 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000207 }
nethercote71980f02004-01-24 18:18:54 +0000208}
209
210
211/*====================================================================*/
212/*=== Miscellaneous global functions ===*/
213/*====================================================================*/
214
nethercotecf97ffb2004-09-09 13:40:31 +0000215static Int ptrace_setregs(Int pid, ThreadId tid)
216{
sewardj2a99cf62004-11-24 10:44:19 +0000217 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000218}
219
nethercote04d0fbc2004-01-26 16:48:06 +0000220/* Start debugger and get it to attach to this process. Called if the
221 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000222 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000223 meaningfully get the debugger to continue the program, though; to
224 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000225void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000226{
227 Int pid;
228
229 if ((pid = fork()) == 0) {
230 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000231 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000232
233 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000234 Int status;
235 Int res;
236
nethercote71980f02004-01-24 18:18:54 +0000237 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
238 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000239 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000240 kill(pid, SIGSTOP) == 0 &&
241 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000242 Char pidbuf[15];
243 Char file[30];
244 Char buf[100];
245 Char *bufptr;
246 Char *cmdptr;
247
248 VG_(sprintf)(pidbuf, "%d", pid);
249 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
250
251 bufptr = buf;
252 cmdptr = VG_(clo_db_command);
253
254 while (*cmdptr) {
255 switch (*cmdptr) {
256 case '%':
257 switch (*++cmdptr) {
258 case 'f':
259 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
260 bufptr += VG_(strlen)(file);
261 cmdptr++;
262 break;
263 case 'p':
264 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
265 bufptr += VG_(strlen)(pidbuf);
266 cmdptr++;
267 break;
268 default:
269 *bufptr++ = *cmdptr++;
270 break;
271 }
272 break;
273 default:
274 *bufptr++ = *cmdptr++;
275 break;
276 }
277 }
278
279 *bufptr++ = '\0';
280
281 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000282 res = VG_(system)(buf);
283 if (res == 0) {
284 VG_(message)(Vg_UserMsg, "");
285 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000286 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000287 } else {
288 VG_(message)(Vg_UserMsg, "Apparently failed!");
289 VG_(message)(Vg_UserMsg, "");
290 }
291 }
292
nethercote73b526f2004-10-31 18:48:21 +0000293 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000294 VG_(waitpid)(pid, &status, 0);
295 }
296}
297
298
299/* Print some helpful-ish text about unimplemented things, and give
300 up. */
301void VG_(unimplemented) ( Char* msg )
302{
303 VG_(message)(Vg_UserMsg, "");
304 VG_(message)(Vg_UserMsg,
305 "Valgrind detected that your program requires");
306 VG_(message)(Vg_UserMsg,
307 "the following unimplemented functionality:");
308 VG_(message)(Vg_UserMsg, " %s", msg);
309 VG_(message)(Vg_UserMsg,
310 "This may be because the functionality is hard to implement,");
311 VG_(message)(Vg_UserMsg,
312 "or because no reasonable program would behave this way,");
313 VG_(message)(Vg_UserMsg,
314 "or because nobody has yet needed it. In any case, let us know at");
315 VG_(message)(Vg_UserMsg,
316 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
317 VG_(message)(Vg_UserMsg,
318 "");
319 VG_(message)(Vg_UserMsg,
320 "Valgrind has to exit now. Sorry. Bye!");
321 VG_(message)(Vg_UserMsg,
322 "");
323 VG_(pp_sched_status)();
324 VG_(exit)(1);
325}
326
sewardj2a99cf62004-11-24 10:44:19 +0000327/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000328Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000329{
njncf45fd42004-11-24 16:30:22 +0000330 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000331}
332
njn67516132005-03-22 04:02:43 +0000333Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000334{
335 return INSTR_PTR( VG_(threads)[tid].arch );
336}
337
njnea4b28c2004-11-30 16:04:58 +0000338
nethercote71980f02004-01-24 18:18:54 +0000339/*====================================================================*/
340/*=== Check we were launched by stage 1 ===*/
341/*====================================================================*/
342
343/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000344static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000345{
nethercoteebf1d862004-11-01 18:22:05 +0000346 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000347 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000348
349 for (; auxv->a_type != AT_NULL; auxv++)
350 switch(auxv->a_type) {
351 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000352 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000353 found |= 1;
354 break;
355
356 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000357 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000358 found |= 2;
359 break;
nethercote7f390022004-10-25 17:18:24 +0000360
361 case AT_PHDR:
362 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
363 break;
nethercote71980f02004-01-24 18:18:54 +0000364 }
365
nethercote361a14e2004-07-26 11:11:56 +0000366 if ( found != (1|2) ) {
367 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000368 exit(127);
369 }
nethercote31779c72004-07-30 21:50:15 +0000370 vg_assert(padfile >= 0);
371 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000372}
373
374
375/*====================================================================*/
376/*=== Address space determination ===*/
377/*====================================================================*/
378
nethercote7f390022004-10-25 17:18:24 +0000379extern char _start[];
380
nethercote31779c72004-07-30 21:50:15 +0000381static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000382{
nethercotea3c3cf22004-11-01 18:38:00 +0000383 Int ires;
384 void* vres;
385 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000386
nethercote7f390022004-10-25 17:18:24 +0000387 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
388 // this is a workable approximation
389 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000390 VG_(valgrind_base) = PGROUNDDN(&_start);
391 }
392
nethercote820bd8c2004-09-07 23:04:49 +0000393 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000394
nethercote31779c72004-07-30 21:50:15 +0000395 // This gives the client the largest possible address space while
396 // taking into account the tool's shadow needs.
397 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000398 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000399 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000400 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000401 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000402 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000403 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000406 VG_(shadow_end) = VG_(valgrind_base);
407 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000408
nethercotee2097312004-06-27 12:29:56 +0000409#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
410
nethercote71980f02004-01-24 18:18:54 +0000411 if (0)
nethercotee2097312004-06-27 12:29:56 +0000412 VG_(printf)(
413 "client_base %8x (%dMB)\n"
414 "client_mapbase %8x (%dMB)\n"
415 "client_end %8x (%dMB)\n"
416 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000417 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000418 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000419 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000420 VG_(client_base), SEGSIZE(client_base, client_mapbase),
421 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
422 VG_(client_end), SEGSIZE(client_end, shadow_base),
423 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000424 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000425 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
426 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000427 );
428
429#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000430
431 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000432 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000433 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000434 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000435
436 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000437 ires = munmap((void*)VG_(client_base), client_size);
438 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000439
440 // Map shadow memory.
441 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000442 if (shadow_size != 0) {
443 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000444 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000445 if ((void*)-1 == vres) {
446 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000447 "valgrind: Could not allocate address space (%p bytes)\n"
448 "valgrind: for shadow memory\n"
449 "valgrind: Possible causes:\n"
450 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
451 "valgrind: needs at least 1.5GB swap space.\n"
452 "valgrind: - Or, your virtual memory size may be limited (check\n"
453 "valgrind: with 'ulimit -v').\n"
454 "valgrind: - Or, your system may use a kernel that provides only a\n"
455 "valgrind: too-small (eg. 2GB) user address space.\n"
456 , (void*)shadow_size
457 );
nethercoted4722622004-08-30 19:36:42 +0000458 exit(1);
459 }
nethercotee567e702004-07-10 17:49:17 +0000460 }
nethercote71980f02004-01-24 18:18:54 +0000461}
462
463/*====================================================================*/
464/*=== Command line setup ===*/
465/*====================================================================*/
466
467/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
468static char* get_file_clo(char* dir)
469{
470# define FLEN 512
471 Int fd, n;
472 struct stat s1;
473 char* f_clo = NULL;
474 char filename[FLEN];
475
476 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
477 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
478 if ( fd > 0 ) {
479 if ( 0 == fstat(fd, &s1) ) {
480 f_clo = malloc(s1.st_size+1);
481 vg_assert(f_clo);
482 n = read(fd, f_clo, s1.st_size);
483 if (n == -1) n = 0;
484 f_clo[n] = '\0';
485 }
486 close(fd);
487 }
488 return f_clo;
489# undef FLEN
490}
491
492static Int count_args(char* s)
493{
494 Int n = 0;
495 if (s) {
496 char* cp = s;
497 while (True) {
498 // We have alternating sequences: blanks, non-blanks, blanks...
499 // count the non-blanks sequences.
njn0c0f32a2005-03-26 04:14:01 +0000500 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000501 if ( !*cp ) break;
502 n++;
njn0c0f32a2005-03-26 04:14:01 +0000503 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000504 }
505 }
506 return n;
507}
508
509/* add args out of environment, skipping multiple spaces and -- args */
510static char** copy_args( char* s, char** to )
511{
512 if (s) {
513 char* cp = s;
514 while (True) {
515 // We have alternating sequences: blanks, non-blanks, blanks...
516 // copy the non-blanks sequences, and add terminating '\0'
njn0c0f32a2005-03-26 04:14:01 +0000517 while ( VG_(isspace)(*cp) ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000518 if ( !*cp ) break;
519 *to++ = cp;
njn0c0f32a2005-03-26 04:14:01 +0000520 while ( !VG_(isspace)(*cp) && *cp ) cp++;
nethercote71980f02004-01-24 18:18:54 +0000521 if ( *cp ) *cp++ = '\0'; // terminate if necessary
522 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
523 }
524 }
525 return to;
526}
527
528// Augment command line with arguments from environment and .valgrindrc
529// files.
530static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
531{
nethercotef6a1d502004-08-09 12:21:57 +0000532 int vg_argc0 = *vg_argc_inout;
533 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000534
535 char* env_clo = getenv(VALGRINDOPTS);
536 char* f1_clo = get_file_clo( getenv("HOME") );
537 char* f2_clo = get_file_clo(".");
538
539 /* copy any extra args from file or environment, if present */
540 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
541 /* ' ' separated extra options */
542 char **from;
543 char **to;
thughescaca0022004-09-13 10:20:34 +0000544 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
545
546 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
547
nethercote71980f02004-01-24 18:18:54 +0000548 env_arg_count = count_args(env_clo);
549 f1_arg_count = count_args(f1_clo);
550 f2_arg_count = count_args(f2_clo);
551
552 if (0)
553 printf("extra-argc=%d %d %d\n",
554 env_arg_count, f1_arg_count, f2_arg_count);
555
556 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000557 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000558 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000559 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000560 vg_assert(vg_argv0);
561 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000562
563 /* copy argv[0] */
564 *to++ = *from++;
565
566 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
567 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
568 * to override less local ones. */
569 to = copy_args(f1_clo, to);
570 to = copy_args(env_clo, to);
571 to = copy_args(f2_clo, to);
572
573 /* copy original arguments, stopping at command or -- */
574 while (*from) {
575 if (**from != '-')
576 break;
577 if (VG_STREQ(*from, "--")) {
578 from++; /* skip -- */
579 break;
580 }
581 *to++ = *from++;
582 }
583
584 /* add -- */
585 *to++ = "--";
586
nethercotef6a1d502004-08-09 12:21:57 +0000587 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000588
589 /* copy rest of original command line, then NULL */
590 while (*from) *to++ = *from++;
591 *to = NULL;
592 }
593
nethercotef6a1d502004-08-09 12:21:57 +0000594 *vg_argc_inout = vg_argc0;
595 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000596}
597
nethercotef6a1d502004-08-09 12:21:57 +0000598#define VG_CLO_SEP '\01'
599
nethercote71980f02004-01-24 18:18:54 +0000600static void get_command_line( int argc, char** argv,
601 Int* vg_argc_out, Char*** vg_argv_out,
602 char*** cl_argv_out )
603{
nethercotef6a1d502004-08-09 12:21:57 +0000604 int vg_argc0;
605 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000606 char** cl_argv;
607 char* env_clo = getenv(VALGRINDCLO);
608
609 if (env_clo != NULL && *env_clo != '\0') {
610 char *cp;
611 char **cpp;
612
nethercotef6a1d502004-08-09 12:21:57 +0000613 /* OK, VALGRINDCLO is set, which means we must be a child of another
614 Valgrind process using --trace-children, so we're getting all our
615 arguments from VALGRINDCLO, and the entire command line belongs to
616 the client (including argv[0]) */
617 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000618 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000619 if (*cp == VG_CLO_SEP)
620 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000621
nethercotef6a1d502004-08-09 12:21:57 +0000622 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
623 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000624
nethercotef6a1d502004-08-09 12:21:57 +0000625 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000626
627 *cpp++ = "valgrind"; /* nominal argv[0] */
628 *cpp++ = env_clo;
629
nethercotef6a1d502004-08-09 12:21:57 +0000630 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000631 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000632 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000633 *cp++ = '\0'; /* chop it up in place */
634 *cpp++ = cp;
635 }
636 }
637 *cpp = NULL;
638 cl_argv = argv;
639
640 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000641 Bool noaugment = False;
642
nethercote71980f02004-01-24 18:18:54 +0000643 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000644 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000645
nethercotef6a1d502004-08-09 12:21:57 +0000646 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000647 Char* arg = argv[vg_argc0];
648 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000649 break;
sewardjb5f6f512005-03-10 23:59:00 +0000650 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000651 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000652 break;
653 }
sewardjb5f6f512005-03-10 23:59:00 +0000654 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000655 }
nethercotef6a1d502004-08-09 12:21:57 +0000656 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000657
658 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000659 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000660 those extra args will already be present in VALGRINDCLO.
661 (We also don't do it when --command-line-only=yes.) */
662 if (!noaugment)
663 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000664 }
665
666 if (0) {
667 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000668 for (i = 0; i < vg_argc0; i++)
669 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000670 }
671
nethercotef6a1d502004-08-09 12:21:57 +0000672 *vg_argc_out = vg_argc0;
673 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000674 *cl_argv_out = cl_argv;
675}
676
677
678/*====================================================================*/
679/*=== Environment and stack setup ===*/
680/*====================================================================*/
681
682/* Scan a colon-separated list, and call a function on each element.
683 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000684 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000685 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000686
687 This routine will return True if (*func) returns True and False if
688 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000689*/
thughes4ad52d02004-06-27 17:37:21 +0000690static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000691{
692 char *cp, *entry;
693 int end;
694
695 if (colsep == NULL ||
696 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000697 return False;
nethercote71980f02004-01-24 18:18:54 +0000698
699 entry = cp = colsep;
700
701 do {
702 end = (*cp == '\0');
703
704 if (*cp == ':' || *cp == '\0') {
705 char save = *cp;
706
707 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000708 if ((*func)(entry)) {
709 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000710 return True;
thughes21942d92004-07-12 09:35:37 +0000711 }
nethercote71980f02004-01-24 18:18:54 +0000712 *cp = save;
713 entry = cp+1;
714 }
715 cp++;
716 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000717
718 return False;
719}
720
nethercote71980f02004-01-24 18:18:54 +0000721/* Prepare the client's environment. This is basically a copy of our
722 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000723 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000724
sewardjb5f6f512005-03-10 23:59:00 +0000725 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000726
727 Yummy. String hacking in C.
728
729 If this needs to handle any more variables it should be hacked
730 into something table driven.
731 */
732static char **fix_environment(char **origenv, const char *preload)
733{
734 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000735 static const char ld_preload[] = "LD_PRELOAD=";
736 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000737 static const int ld_preload_len = sizeof(ld_preload)-1;
738 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
739 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000740 char *inject_path;
741 int inject_path_len;
742 int vgliblen = strlen(VG_(libdir));
743 char **cpp;
744 char **ret;
745 int envc;
746 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
747
748 /* Find the vg_inject.so; also make room for the tool preload
749 library */
750 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
751 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000752 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000753
754 if (preload)
755 snprintf(inject_path, inject_path_len, "%s/%s:%s",
756 VG_(libdir), inject_so, preload);
757 else
758 snprintf(inject_path, inject_path_len, "%s/%s",
759 VG_(libdir), inject_so);
760
761 /* Count the original size of the env */
762 envc = 0; /* trailing NULL */
763 for (cpp = origenv; cpp && *cpp; cpp++)
764 envc++;
765
766 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000767 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000768 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000769
770 /* copy it over */
771 for (cpp = ret; *origenv; )
772 *cpp++ = *origenv++;
773 *cpp = NULL;
774
775 vg_assert(envc == (cpp - ret));
776
777 /* Walk over the new environment, mashing as we go */
778 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000779 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000780 int len = strlen(*cpp) + inject_path_len;
781 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000782 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000783
784 snprintf(cp, len, "%s%s:%s",
785 ld_preload, inject_path, (*cpp)+ld_preload_len);
786
787 *cpp = cp;
788
789 ld_preload_done = 1;
790 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
791 *cpp = "";
792 }
793 }
794
795 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000796 if (!ld_preload_done) {
797 int len = ld_preload_len + inject_path_len;
798 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000799 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000800
801 snprintf(cp, len, "%s%s",
802 ld_preload, inject_path);
803
804 ret[envc++] = cp;
805 }
806
sewardjb5f6f512005-03-10 23:59:00 +0000807 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000808 ret[envc] = NULL;
809
810 return ret;
811}
812
813extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000814
815/* Add a string onto the string table, and return its address */
816static char *copy_str(char **tab, const char *str)
817{
818 char *cp = *tab;
819 char *orig = cp;
820
821 while(*str)
822 *cp++ = *str++;
823 *cp++ = '\0';
824
825 if (0)
nethercote545fe672004-11-01 16:52:43 +0000826 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000827
828 *tab = cp;
829
830 return orig;
831}
832
833/*
834 This sets up the client's initial stack, containing the args,
835 environment and aux vector.
836
837 The format of the stack is:
838
839 higher address +-----------------+
840 | Trampoline code |
841 +-----------------+
842 | |
843 : string table :
844 | |
845 +-----------------+
846 | AT_NULL |
847 - -
848 | auxv |
849 +-----------------+
850 | NULL |
851 - -
852 | envp |
853 +-----------------+
854 | NULL |
855 - -
856 | argv |
857 +-----------------+
858 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000859 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000860 | undefined |
861 : :
862 */
nethercotec25c4492004-10-18 11:52:17 +0000863static Addr setup_client_stack(void* init_sp,
864 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000865 const struct exeinfo *info,
866 UInt** client_auxv)
867{
nethercotee567e702004-07-10 17:49:17 +0000868 void* res;
nethercote71980f02004-01-24 18:18:54 +0000869 char **cpp;
870 char *strtab; /* string table */
871 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000872 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000873 struct ume_auxv *auxv;
874 const struct ume_auxv *orig_auxv;
875 const struct ume_auxv *cauxv;
876 unsigned stringsize; /* total size of strings in bytes */
877 unsigned auxsize; /* total size of auxv in bytes */
878 int argc; /* total argc */
879 int envc; /* total number of env vars */
880 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000881 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000882
883 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000884 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000885
886 /* ==================== compute sizes ==================== */
887
888 /* first of all, work out how big the client stack will be */
889 stringsize = 0;
890
891 /* paste on the extra args if the loader needs them (ie, the #!
892 interpreter and its argument) */
893 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000894 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000895 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000896 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000897 }
nethercoted6a56872004-07-26 15:32:47 +0000898 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000899 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000900 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000901 }
902
903 /* now scan the args we're given... */
904 for (cpp = orig_argv; *cpp; cpp++) {
905 argc++;
906 stringsize += strlen(*cpp) + 1;
907 }
908
909 /* ...and the environment */
910 envc = 0;
911 for (cpp = orig_envp; cpp && *cpp; cpp++) {
912 envc++;
913 stringsize += strlen(*cpp) + 1;
914 }
915
916 /* now, how big is the auxv? */
917 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
918 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
919 if (cauxv->a_type == AT_PLATFORM)
920 stringsize += strlen(cauxv->u.a_ptr) + 1;
921 auxsize += sizeof(*cauxv);
922 }
923
924 /* OK, now we know how big the client stack is */
925 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000926 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000927 sizeof(char **)*argc + /* argv */
928 sizeof(char **) + /* terminal NULL */
929 sizeof(char **)*envc + /* envp */
930 sizeof(char **) + /* terminal NULL */
931 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000932 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000933 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000934
sewardj79048ce2005-02-18 08:28:32 +0000935 if (0) VG_(printf)("stacksize = %d\n", stacksize);
936
nethercotef84f6952004-07-15 14:58:33 +0000937 // decide where stack goes!
938 VG_(clstk_end) = VG_(client_end);
939
nethercote73b526f2004-10-31 18:48:21 +0000940 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000941
nethercote71980f02004-01-24 18:18:54 +0000942 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000943 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000944 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
945
nethercote71980f02004-01-24 18:18:54 +0000946 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000947 stringbase = strtab = (char *)(VG_(client_trampoline_code)
948 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000949
950 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000951
sewardj79048ce2005-02-18 08:28:32 +0000952 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000953 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000954 "clstk_base %p\n"
955 "clstk_end %p\n",
956 stringsize, auxsize, stacksize,
957 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000958
nethercote71980f02004-01-24 18:18:54 +0000959 /* ==================== allocate space ==================== */
960
961 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000962 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000963 PROT_READ | PROT_WRITE | PROT_EXEC,
964 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
965 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000966
967 /* ==================== copy client stack ==================== */
968
nethercotea3c3cf22004-11-01 18:38:00 +0000969 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000970
971 /* --- argc --- */
972 *ptr++ = argc; /* client argc */
973
974 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000975 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000976 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000977 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000978 }
nethercoted6a56872004-07-26 15:32:47 +0000979 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000980 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000981 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000982 }
983 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000984 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000985 }
986 *ptr++ = 0;
987
988 /* --- envp --- */
989 VG_(client_envp) = (Char **)ptr;
990 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000991 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000992 *ptr++ = 0;
993
994 /* --- auxv --- */
995 auxv = (struct ume_auxv *)ptr;
996 *client_auxv = (UInt *)auxv;
997
998 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
999 /* copy the entry... */
1000 *auxv = *orig_auxv;
1001
1002 /* ...and fix up the copy */
1003 switch(auxv->a_type) {
1004 case AT_PHDR:
1005 if (info->phdr == 0)
1006 auxv->a_type = AT_IGNORE;
1007 else
1008 auxv->u.a_val = info->phdr;
1009 break;
1010
1011 case AT_PHNUM:
1012 if (info->phdr == 0)
1013 auxv->a_type = AT_IGNORE;
1014 else
1015 auxv->u.a_val = info->phnum;
1016 break;
1017
1018 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001019 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001020 break;
1021
1022 case AT_PLATFORM: /* points to a platform description string */
1023 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1024 break;
1025
1026 case AT_ENTRY:
1027 auxv->u.a_val = info->entry;
1028 break;
1029
1030 case AT_IGNORE:
1031 case AT_EXECFD:
1032 case AT_PHENT:
1033 case AT_PAGESZ:
1034 case AT_FLAGS:
1035 case AT_NOTELF:
1036 case AT_UID:
1037 case AT_EUID:
1038 case AT_GID:
1039 case AT_EGID:
1040 case AT_CLKTCK:
1041 case AT_HWCAP:
1042 case AT_FPUCW:
1043 case AT_DCACHEBSIZE:
1044 case AT_ICACHEBSIZE:
1045 case AT_UCACHEBSIZE:
1046 /* All these are pointerless, so we don't need to do anything
1047 about them. */
1048 break;
1049
1050 case AT_SECURE:
1051 /* If this is 1, then it means that this program is running
1052 suid, and therefore the dynamic linker should be careful
1053 about LD_PRELOAD, etc. However, since stage1 (the thing
1054 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001055 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001056 set AT_SECURE to 0. */
1057 auxv->u.a_val = 0;
1058 break;
1059
1060 case AT_SYSINFO:
1061 /* Leave this unmolested for now, but we'll update it later
1062 when we set up the client trampoline code page */
1063 break;
1064
1065 case AT_SYSINFO_EHDR:
1066 /* Trash this, because we don't reproduce it */
1067 auxv->a_type = AT_IGNORE;
1068 break;
1069
1070 default:
1071 /* stomp out anything we don't know about */
1072 if (0)
nethercote545fe672004-11-01 16:52:43 +00001073 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001074 auxv->a_type = AT_IGNORE;
1075 break;
1076
1077 }
1078 }
1079 *auxv = *orig_auxv;
1080 vg_assert(auxv->a_type == AT_NULL);
1081
njnc6168192004-11-29 13:54:10 +00001082// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1083// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001084#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001085 /* --- trampoline page --- */
1086 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1087 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001088#endif
nethercotef84f6952004-07-15 14:58:33 +00001089
nethercote71980f02004-01-24 18:18:54 +00001090 vg_assert((strtab-stringbase) == stringsize);
1091
nethercote5ee67ca2004-06-22 14:00:09 +00001092 /* We know the initial ESP is pointing at argc/argv */
1093 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001094 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001095
sewardj79048ce2005-02-18 08:28:32 +00001096 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001097 return cl_esp;
1098}
1099
1100/*====================================================================*/
1101/*=== Find executable ===*/
1102/*====================================================================*/
1103
thughes4ad52d02004-06-27 17:37:21 +00001104static const char* executable_name;
1105
1106static Bool match_executable(const char *entry) {
1107 char buf[strlen(entry) + strlen(executable_name) + 2];
1108
1109 /* empty PATH element means . */
1110 if (*entry == '\0')
1111 entry = ".";
1112
1113 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1114
1115 if (access(buf, R_OK|X_OK) == 0) {
1116 executable_name = strdup(buf);
1117 vg_assert(NULL != executable_name);
1118 return True;
1119 }
1120 return False;
1121}
1122
nethercote71980f02004-01-24 18:18:54 +00001123static const char* find_executable(const char* exec)
1124{
1125 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001126 executable_name = exec;
1127 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001128 /* no '/' - we need to search the path */
1129 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001130 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001131 }
thughes4ad52d02004-06-27 17:37:21 +00001132 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001133}
1134
1135
1136/*====================================================================*/
1137/*=== Loading tools ===*/
1138/*====================================================================*/
1139
1140static void list_tools(void)
1141{
1142 DIR *dir = opendir(VG_(libdir));
1143 struct dirent *de;
1144 int first = 1;
1145
1146 if (dir == NULL) {
1147 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001148 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001149 return;
1150 }
1151
nethercotef4928da2004-06-15 10:54:40 +00001152 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001153 int len = strlen(de->d_name);
1154
njn063c5402004-11-22 16:58:05 +00001155 /* look for vgtool_TOOL.so names */
1156 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1157 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001158 VG_STREQ(de->d_name + len - 3, ".so")) {
1159 if (first) {
1160 fprintf(stderr, "Available tools:\n");
1161 first = 0;
1162 }
1163 de->d_name[len-3] = '\0';
1164 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001165 }
1166 }
1167
1168 closedir(dir);
1169
1170 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001171 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1172 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001173}
1174
1175
1176/* Find and load a tool, and check it looks ok. Also looks to see if there's
1177 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1178static void load_tool( const char *toolname, void** handle_out,
1179 ToolInfo** toolinfo_out, char **preloadpath_out )
1180{
1181 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001182 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001183 char buf[len];
1184 void* handle;
1185 ToolInfo* toolinfo;
1186 char* preloadpath = NULL;
1187 Int* vg_malloc_redzonep;
1188
1189 // XXX: allowing full paths for --tool option -- does it make sense?
1190 // Doesn't allow for vgpreload_<tool>.so.
1191
1192 if (strchr(toolname, '/') != 0) {
1193 /* toolname contains '/', and so must be a pathname */
1194 handle = dlopen(toolname, RTLD_NOW);
1195 } else {
1196 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001197 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001198 handle = dlopen(buf, RTLD_NOW);
1199
1200 if (handle != NULL) {
1201 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1202 if (access(buf, R_OK) == 0) {
1203 preloadpath = strdup(buf);
1204 vg_assert(NULL != preloadpath);
1205 }
1206 }
1207 }
1208
1209 ok = (NULL != handle);
1210 if (!ok) {
1211 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1212 goto bad_load;
1213 }
1214
njn26f02512004-11-22 18:33:15 +00001215 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001216 ok = (NULL != toolinfo);
1217 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001218 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001219 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1220 goto bad_load;
1221 }
1222
1223 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1224 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001225 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001226 if (!ok) {
1227 fprintf(stderr, "Error:\n"
1228 " Tool and core interface versions do not match.\n"
1229 " Interface version used by core is: %d.%d (size %d)\n"
1230 " Interface version used by tool is: %d.%d (size %d)\n"
1231 " The major version numbers must match.\n",
1232 VG_CORE_INTERFACE_MAJOR_VERSION,
1233 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001234 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001235 toolinfo->interface_major_version,
1236 toolinfo->interface_minor_version,
1237 toolinfo->sizeof_ToolInfo);
1238 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1239 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 else
nethercote996901a2004-08-03 13:29:09 +00001242 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001243 goto bad_load;
1244 }
1245
1246 // Set redzone size for V's allocator
1247 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1248 if ( NULL != vg_malloc_redzonep ) {
1249 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1250 }
1251
1252 vg_assert(NULL != handle && NULL != toolinfo);
1253 *handle_out = handle;
1254 *toolinfo_out = toolinfo;
1255 *preloadpath_out = preloadpath;
1256 return;
1257
1258
1259 bad_load:
1260 if (handle != NULL)
1261 dlclose(handle);
1262
nethercotef4928da2004-06-15 10:54:40 +00001263 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001264 list_tools();
1265 exit(127);
1266}
1267
nethercotef4928da2004-06-15 10:54:40 +00001268
1269/*====================================================================*/
1270/*=== Command line errors ===*/
1271/*====================================================================*/
1272
1273static void abort_msg ( void )
1274{
nethercotef8548672004-06-21 12:42:35 +00001275 VG_(clo_log_to) = VgLogTo_Fd;
1276 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001277}
1278
1279void VG_(bad_option) ( Char* opt )
1280{
1281 abort_msg();
1282 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1283 VG_(printf)("valgrind: Use --help for more information.\n");
1284 VG_(exit)(1);
1285}
1286
nethercotef4928da2004-06-15 10:54:40 +00001287static void missing_prog ( void )
1288{
1289 abort_msg();
1290 VG_(printf)("valgrind: no program specified\n");
1291 VG_(printf)("valgrind: Use --help for more information.\n");
1292 VG_(exit)(1);
1293}
1294
1295static void config_error ( Char* msg )
1296{
1297 abort_msg();
1298 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1299 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1300 VG_(exit)(1);
1301}
1302
1303
nethercote71980f02004-01-24 18:18:54 +00001304/*====================================================================*/
1305/*=== Loading the client ===*/
1306/*====================================================================*/
1307
nethercotef4928da2004-06-15 10:54:40 +00001308static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001309 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1310{
1311 // If they didn't specify an executable with --exec, and didn't specify
1312 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001313 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001314 if (cl_argv[0] == NULL ||
1315 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1316 {
nethercotef4928da2004-06-15 10:54:40 +00001317 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001318 }
1319 }
1320
1321 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001322 info->exe_base = VG_(client_base);
1323 info->exe_end = VG_(client_end);
1324 info->argv = cl_argv;
1325
nethercotef4928da2004-06-15 10:54:40 +00001326 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001327 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001328 // Totally zero 'info' before continuing.
1329 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001330 } else {
1331 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001332 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001333 ret = do_exec(exec, info);
1334 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001335 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1336 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001337 exit(127);
1338 }
1339 }
1340
1341 /* Copy necessary bits of 'info' that were filled in */
1342 *client_eip = info->init_eip;
1343 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1344}
1345
nethercote969ecf12004-10-13 17:29:01 +00001346/*====================================================================*/
1347/*=== Address space unpadding ===*/
1348/*====================================================================*/
1349
1350typedef struct {
1351 char* killpad_start;
1352 char* killpad_end;
1353 struct stat* killpad_padstat;
1354} killpad_extra;
1355
1356static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1357 int maj, int min, int ino, void* ex)
1358{
1359 killpad_extra* extra = ex;
1360 void *b, *e;
1361 int res;
1362
1363 vg_assert(NULL != extra->killpad_padstat);
1364
1365 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1366 extra->killpad_padstat->st_ino != ino)
1367 return 1;
1368
1369 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1370 return 1;
1371
1372 if (segstart <= extra->killpad_start)
1373 b = extra->killpad_start;
1374 else
1375 b = segstart;
1376
1377 if (segend >= extra->killpad_end)
1378 e = extra->killpad_end;
1379 else
1380 e = segend;
1381
1382 res = munmap(b, (char *)e-(char *)b);
1383 vg_assert(0 == res);
1384
1385 return 1;
1386}
1387
1388// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001389static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001390{
1391 static struct stat padstat;
1392 killpad_extra extra;
1393 int res;
1394
sewardjb5f6f512005-03-10 23:59:00 +00001395 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001396
1397 res = fstat(padfile, &padstat);
1398 vg_assert(0 == res);
1399 extra.killpad_padstat = &padstat;
1400 extra.killpad_start = start;
1401 extra.killpad_end = end;
1402 foreach_map(killpad, &extra);
1403}
1404
sewardj2c5ffbe2005-03-12 13:32:06 +00001405static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001406{
1407 int res = close(padfile);
1408 vg_assert(0 == res);
1409}
1410
nethercote71980f02004-01-24 18:18:54 +00001411
1412/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001413/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001414/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001415
njn25e49d8e72002-09-23 09:36:25 +00001416/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001417VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001418Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001419Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001420Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001421Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001422Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001423Int VG_(clo_verbosity) = 1;
1424Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001425Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001426
nethercotef1e5e152004-09-01 23:58:16 +00001427/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001428 fd is initially stdout, for --help, but gets moved to stderr by default
1429 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001430VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001431Int VG_(clo_log_fd) = 1;
1432Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001433
thughes6233a382004-08-21 11:10:44 +00001434Bool VG_(clo_time_stamp) = False;
1435
sewardj6024b212003-07-13 10:54:33 +00001436Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001437Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001438Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001439Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001440UChar VG_(clo_trace_flags) = 0; // 00000000b
1441UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001442Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001443Bool VG_(clo_trace_syscalls) = False;
1444Bool VG_(clo_trace_signals) = False;
1445Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001446Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001447Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001448Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001449Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001450Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001451Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001452Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001453Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001454Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001455Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001456Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001457Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001458Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001459Bool VG_(clo_show_emwarns) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001460
jsgf855d93d2003-10-13 22:26:55 +00001461static Bool VG_(clo_wait_for_gdb) = False;
1462
sewardjde4a1d02002-03-22 01:27:54 +00001463
sewardj2c5ffbe2005-03-12 13:32:06 +00001464static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001465{
njn25e49d8e72002-09-23 09:36:25 +00001466 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001467"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001468"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001469" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001470" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001471" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001472" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001473" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001474" -q --quiet run silently; only print error msgs\n"
1475" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001476" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001477" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001478" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001479"\n"
1480" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001481" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001482" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001483" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001484" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001485" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001486"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001487" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001488" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1489" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001490" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001491" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001492" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001493" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001494" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1495" --show-below-main=no|yes continue stack traces below main() [no]\n"
1496" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001497" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001498" --db-attach=no|yes start debugger when errors detected? [no]\n"
1499" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1500" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001501"\n";
njn7cf0bd32002-06-08 13:36:03 +00001502
njn25e49d8e72002-09-23 09:36:25 +00001503 Char* usage2 =
1504"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001505" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001506" --sanity-level=<number> level of sanity checking to do [1]\n"
1507" --single-step=no|yes translate each instr separately? [no]\n"
1508" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001509" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001510" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001511" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1512" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001513" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001514" --trace-syscalls=no|yes show all system calls? [no]\n"
1515" --trace-signals=no|yes show signal handling details? [no]\n"
1516" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001518" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001519#if 0
1520" --model-pthreads=yes|no model the pthreads library [no]\n"
1521#endif
1522" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001523"\n"
1524" --vex-iropt-verbosity 0 .. 9 [0]\n"
1525" --vex-iropt-level 0 .. 2 [2]\n"
1526" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001527" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1528" --vex-guest-max-insns 1 .. 100 [50]\n"
1529" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1530"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001531" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001532" 1000 0000 show conversion into IR\n"
1533" 0100 0000 show after initial opt\n"
1534" 0010 0000 show after instrumentation\n"
1535" 0001 0000 show after second opt\n"
1536" 0000 1000 show after tree building\n"
1537" 0000 0100 show selecting insns\n"
1538" 0000 0010 show after reg-alloc\n"
1539" 0000 0001 show final assembly\n"
1540"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001541" debugging options for Valgrind tools that report errors\n"
1542" --dump-error=<number> show translation for basic block associated\n"
1543" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001544"\n";
njn3e884182003-04-15 13:03:23 +00001545
1546 Char* usage3 =
1547"\n"
nethercote71980f02004-01-24 18:18:54 +00001548" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001549"\n"
njn53612422005-03-12 16:22:54 +00001550" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001551" and licensed under the GNU General Public License, version 2.\n"
1552" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001553"\n"
nethercote137bc552003-11-14 17:47:54 +00001554" Tools are copyright and licensed by their authors. See each\n"
1555" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001556"\n";
njn7cf0bd32002-06-08 13:36:03 +00001557
fitzhardinge98abfc72003-12-16 02:05:15 +00001558 VG_(printf)(usage1);
1559 if (VG_(details).name) {
1560 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001561 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001562 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001563 else
1564 VG_(printf)(" (none)\n");
1565 }
nethercote6c999f22004-01-31 22:55:15 +00001566 if (debug_help) {
1567 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001568
nethercote6c999f22004-01-31 22:55:15 +00001569 if (VG_(details).name) {
1570 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1571
1572 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001573 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001574 else
1575 VG_(printf)(" (none)\n");
1576 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001577 }
nethercote421281e2003-11-20 16:20:55 +00001578 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001579 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001580}
sewardjde4a1d02002-03-22 01:27:54 +00001581
nethercote71980f02004-01-24 18:18:54 +00001582static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001583 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001584{
nethercote71980f02004-01-24 18:18:54 +00001585 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001586
sewardj8b635a42004-11-22 19:01:47 +00001587 LibVEX_default_VexControl(& VG_(clo_vex_control));
1588
nethercote71980f02004-01-24 18:18:54 +00001589 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001590 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001593 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001594 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001595
nethercotef6a1d502004-08-09 12:21:57 +00001596 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1597 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001598 *need_help = 1;
1599
nethercotef6a1d502004-08-09 12:21:57 +00001600 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001601 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001602
nethercotef6c99d72004-11-09 14:35:43 +00001603 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001604 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001605
nethercotef6a1d502004-08-09 12:21:57 +00001606 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1607 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001608 }
1609 }
nethercote71980f02004-01-24 18:18:54 +00001610}
1611
nethercote5ee67ca2004-06-22 14:00:09 +00001612static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001613{
nethercotef8548672004-06-21 12:42:35 +00001614 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001615 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001616
nethercotee1730692003-11-20 10:38:07 +00001617 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001618 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001619
sewardj19d81412002-06-03 01:10:40 +00001620 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001621 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001622 config_error("Please use absolute paths in "
1623 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001624
njnc6168192004-11-29 13:54:10 +00001625// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001626#ifdef __x86__
1627 {
sewardjb5f6f512005-03-10 23:59:00 +00001628 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001629 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1630 switch(auxp[0]) {
1631 case AT_SYSINFO:
1632 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1633 break;
1634 }
1635 }
1636 }
1637#endif
sewardjde4a1d02002-03-22 01:27:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001640
nethercotef6a1d502004-08-09 12:21:57 +00001641 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001642 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001643
thughes3bfd5a02004-07-18 08:05:44 +00001644 /* Look for a colon in the switch name */
1645 while (*colon && *colon != ':' && *colon != '=')
1646 colon++;
nethercote71980f02004-01-24 18:18:54 +00001647
1648 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001649 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001650 if (VG_CLO_STREQN(2, arg, "--") &&
1651 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1652 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1653 {
1654 // prefix matches, convert "--toolname:foo" to "--foo"
1655 if (0)
1656 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001657 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001658 arg[0] = '-';
1659 arg[1] = '-';
1660
1661 } else {
1662 // prefix doesn't match, skip to next arg
1663 continue;
1664 }
1665 }
1666
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001668 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001669 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001670 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001671 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001672 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001673 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001674
nethercote71980f02004-01-24 18:18:54 +00001675 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001676 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 else if (VG_CLO_STREQ(arg, "-v") ||
1679 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001680 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001681
nethercote71980f02004-01-24 18:18:54 +00001682 else if (VG_CLO_STREQ(arg, "-q") ||
1683 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001684 VG_(clo_verbosity)--;
1685
nethercote27fec902004-06-16 21:26:32 +00001686 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001687 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1688 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1689 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001690 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001691 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
sewardjb1131a82005-03-19 15:12:21 +00001692 else VG_BOOL_CLO("--show-emwarns", VG_(clo_show_emwarns))
nethercote27fec902004-06-16 21:26:32 +00001693 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1694 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1695 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001696 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001697 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1698 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1699 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1700 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1701 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001702 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001703 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001704 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001705 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001706 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001707
nethercote27fec902004-06-16 21:26:32 +00001708 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1709 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001710
nethercote27fec902004-06-16 21:26:32 +00001711 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1712 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1713 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001714 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1715 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001716
sewardj8b635a42004-11-22 19:01:47 +00001717 else VG_BNUM_CLO("--vex-iropt-verbosity",
1718 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1719 else VG_BNUM_CLO("--vex-iropt-level",
1720 VG_(clo_vex_control).iropt_level, 0, 2)
1721 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1722 VG_(clo_vex_control).iropt_precise_memory_exns)
1723 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1724 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1725 else VG_BNUM_CLO("--vex-guest-max-insns",
1726 VG_(clo_vex_control).guest_max_insns, 1, 100)
1727 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1728 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1729
nethercotef8548672004-06-21 12:42:35 +00001730 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1731 VG_(clo_log_to) = VgLogTo_Fd;
1732 VG_(clo_log_name) = NULL;
1733 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001734 }
1735
nethercotef8548672004-06-21 12:42:35 +00001736 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1737 VG_(clo_log_to) = VgLogTo_File;
1738 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001739 }
njnd6bc3c32005-03-27 00:44:31 +00001740
sewardj603d4102005-01-11 14:01:02 +00001741 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1742 VG_(clo_log_to) = VgLogTo_FileExactly;
1743 VG_(clo_log_name) = &arg[19];
1744 }
sewardjde4a1d02002-03-22 01:27:54 +00001745
nethercotef8548672004-06-21 12:42:35 +00001746 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1747 VG_(clo_log_to) = VgLogTo_Socket;
1748 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001749 }
1750
nethercote71980f02004-01-24 18:18:54 +00001751 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001752 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001753 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001754 VG_(message)(Vg_UserMsg,
1755 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001756 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001757 }
nethercote71980f02004-01-24 18:18:54 +00001758 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001759 VG_(clo_n_suppressions)++;
1760 }
sewardjde4a1d02002-03-22 01:27:54 +00001761
sewardjfa8ec112005-01-19 11:55:34 +00001762 /* "stuvwxyz" --> stuvwxyz (binary) */
1763 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1764 Int j;
1765 char* opt = & arg[14];
1766
1767 if (8 != VG_(strlen)(opt)) {
1768 VG_(message)(Vg_UserMsg,
1769 "--trace-flags argument must have 8 digits");
1770 VG_(bad_option)(arg);
1771 }
1772 for (j = 0; j < 8; j++) {
1773 if ('0' == opt[j]) { /* do nothing */ }
1774 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1775 else {
1776 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1777 "contain 0s and 1s");
1778 VG_(bad_option)(arg);
1779 }
1780 }
1781 }
1782
1783 /* "stuvwxyz" --> stuvwxyz (binary) */
1784 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001785 Int j;
nethercote71980f02004-01-24 18:18:54 +00001786 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001787
sewardj2a99cf62004-11-24 10:44:19 +00001788 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001789 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001790 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001791 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001792 }
sewardj8b635a42004-11-22 19:01:47 +00001793 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001794 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001795 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001796 else {
sewardjfa8ec112005-01-19 11:55:34 +00001797 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001798 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001799 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001800 }
1801 }
1802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
sewardjc771b292004-11-30 18:55:21 +00001804 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1805
sewardjd153fae2005-01-10 17:24:47 +00001806 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1807 VG_(clo_gen_suppressions) = 0;
1808 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1809 VG_(clo_gen_suppressions) = 1;
1810 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1811 VG_(clo_gen_suppressions) = 2;
1812
nethercote71980f02004-01-24 18:18:54 +00001813 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001814 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001815 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001816 }
njn8c0b3bb2005-03-12 21:20:39 +00001817 skip_arg:
1818 if (arg != vg_argv[i])
1819 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
1821
sewardj998d40d2004-12-06 14:24:52 +00001822 /* Make VEX control parameters sane */
1823
1824 if (VG_(clo_vex_control).guest_chase_thresh
1825 >= VG_(clo_vex_control).guest_max_insns)
1826 VG_(clo_vex_control).guest_chase_thresh
1827 = VG_(clo_vex_control).guest_max_insns - 1;
1828
1829 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1830 VG_(clo_vex_control).guest_chase_thresh = 0;
1831
1832 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001833
njnf9ebf672003-05-12 21:41:30 +00001834 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001835 VG_(clo_verbosity) = 0;
1836
nethercote04d0fbc2004-01-26 16:48:06 +00001837 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001838 VG_(message)(Vg_UserMsg, "");
1839 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001840 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(message)(Vg_UserMsg,
1842 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001843 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001844 }
1845
nethercotef8548672004-06-21 12:42:35 +00001846 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001847 should be connected to whatever sink has been selected, and we
1848 indiscriminately chuck stuff into it without worrying what the
1849 nature of it is. Oh the wonder of Unix streams. */
1850
nethercotee1730692003-11-20 10:38:07 +00001851 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001852 the terminal any problems to do with processing command line
1853 opts. */
nethercotef8548672004-06-21 12:42:35 +00001854 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001855 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001856
1857 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001858
sewardj4cf05692002-10-27 20:28:29 +00001859 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(VG_(clo_log_name) == NULL);
1861 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001862 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001863
sewardj4cf05692002-10-27 20:28:29 +00001864 case VgLogTo_File: {
1865 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001866 Int seq = 0;
1867 Int pid = VG_(getpid)();
1868
nethercotef8548672004-06-21 12:42:35 +00001869 vg_assert(VG_(clo_log_name) != NULL);
1870 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001871
nethercote71980f02004-01-24 18:18:54 +00001872 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001873 if (seq == 0)
1874 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001875 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001876 else
1877 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001878 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001879 seq++;
1880
nethercotef8548672004-06-21 12:42:35 +00001881 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001882 = VG_(open)(logfilename,
1883 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1884 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001885 if (eventually_log_fd >= 0) {
1886 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001887 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001888 } else {
nethercotef8548672004-06-21 12:42:35 +00001889 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001890 VG_(message)(Vg_UserMsg,
1891 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001892 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001893 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001894 "--log-file=<file> (didn't work out for some reason.)");
1895 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001896 }
1897 }
1898 }
sewardj603d4102005-01-11 14:01:02 +00001899 break; /* switch (VG_(clo_log_to)) */
1900 }
1901
1902 case VgLogTo_FileExactly: {
1903 Char logfilename[1000];
1904
1905 vg_assert(VG_(clo_log_name) != NULL);
1906 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1907 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1908
1909 eventually_log_fd
1910 = VG_(open)(logfilename,
1911 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1912 VKI_S_IRUSR|VKI_S_IWUSR);
1913 if (eventually_log_fd >= 0) {
1914 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1915 }
1916 else if (eventually_log_fd != -VKI_EEXIST) {
1917 VG_(message)(Vg_UserMsg,
1918 "Can't create/open log file `%s'; giving up!",
1919 VG_(clo_log_name));
1920 VG_(bad_option)(
1921 "--log-file-exactly=<file> (didn't work out for some reason.)");
1922 /*NOTREACHED*/
1923 }
1924 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001925 }
1926
1927 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001928 vg_assert(VG_(clo_log_name) != NULL);
1929 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1930 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1931 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001932 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001933 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001935 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001937 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001938 }
nethercotef8548672004-06-21 12:42:35 +00001939 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001940 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001941 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001942 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001943 VG_(message)(Vg_UserMsg,
1944 "Log messages will sent to stderr instead." );
1945 VG_(message)(Vg_UserMsg,
1946 "" );
1947 /* We don't change anything here. */
1948 } else {
nethercotef8548672004-06-21 12:42:35 +00001949 vg_assert(eventually_log_fd > 0);
1950 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001951 VG_(logging_to_filedes) = False;
1952 }
sewardj73cf3bc2002-11-03 03:20:15 +00001953 break;
1954 }
1955
sewardj4cf05692002-10-27 20:28:29 +00001956 }
1957
nethercotef8548672004-06-21 12:42:35 +00001958 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001959 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001960 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001961 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1962 else {
nethercotef8548672004-06-21 12:42:35 +00001963 VG_(clo_log_fd) = eventually_log_fd;
1964 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001965 }
1966
sewardj4cf05692002-10-27 20:28:29 +00001967 /* Ok, the logging sink is running now. Print a suitable preamble.
1968 If logging to file or a socket, write details of parent PID and
1969 command line args, to help people trying to interpret the
1970 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001971
sewardj83adf412002-05-01 01:25:45 +00001972 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001973 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001974 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001975 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001976 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001977 NULL == VG_(details).version
1978 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001979 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001980 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001981
njnd04b7c62002-10-03 14:05:52 +00001982 /* Core details */
1983 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001984 "Using LibVEX rev %s, a library for dynamic binary translation.",
1985 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001986 VG_(message)(Vg_UserMsg,
1987 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1988 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001989 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001990 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001992 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001993 }
1994
nethercotec1e395d2003-11-10 13:26:49 +00001995 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001996 VG_(message)(Vg_UserMsg, "");
1997 VG_(message)(Vg_UserMsg,
1998 "My PID = %d, parent PID = %d. Prog and args are:",
1999 VG_(getpid)(), VG_(getppid)() );
2000 for (i = 0; i < VG_(client_argc); i++)
2001 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2002 }
2003
sewardjde4a1d02002-03-22 01:27:54 +00002004 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002005 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002006 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002007 VG_(message)(Vg_DebugMsg, "");
2008 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2009 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002010 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002011 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002012
njn1fd5eb22005-03-13 05:43:23 +00002013 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002014 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002015 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
nethercotea70f7352004-04-18 12:08:46 +00002017
njn1fd5eb22005-03-13 05:43:23 +00002018 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002019 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2020 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002021 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002022 } else {
2023 #define BUF_LEN 256
2024 Char version_buf[BUF_LEN];
2025 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2026 vg_assert(n <= 256);
2027 if (n > 0) {
2028 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002029 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002030 } else {
njn1fd5eb22005-03-13 05:43:23 +00002031 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002032 }
2033 VG_(close)(fd);
2034 #undef BUF_LEN
2035 }
sewardjde4a1d02002-03-22 01:27:54 +00002036 }
2037
fitzhardinge98abfc72003-12-16 02:05:15 +00002038 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002039 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002040 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002041 needs one, load the default */
2042 static const Char default_supp[] = "default.supp";
2043 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2044 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2045 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2046 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2047 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002048 }
sewardj4cf05692002-10-27 20:28:29 +00002049
sewardjd153fae2005-01-10 17:24:47 +00002050 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002051 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002052 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002053 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002054 VG_(message)(Vg_UserMsg,
2055 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002056 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002057 }
sewardjde4a1d02002-03-22 01:27:54 +00002058}
2059
nethercotef6a1d502004-08-09 12:21:57 +00002060// Build the string for VALGRINDCLO.
2061Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2062{
2063 /* If we're tracing the children, then we need to start it
2064 with our starter+arguments, which are copied into VALGRINDCLO,
2065 except the --exec= option is changed if present.
2066 */
2067 Int i;
2068 Char *exec;
2069 Char *cp;
2070 Char *optvar;
2071 Int optlen, execlen;
2072
2073 // All these allocated blocks are not free - because we're either
2074 // going to exec, or panic when we fail.
2075
2076 // Create --exec= option: "--exec=<exename>"
2077 exec = VG_(arena_malloc)(VG_AR_CORE,
2078 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2079 vg_assert(NULL != exec);
2080 VG_(sprintf)(exec, "--exec=%s", exename);
2081
2082 // Allocate space for optvar (may overestimate by counting --exec twice,
2083 // no matter)
2084 optlen = 1;
2085 for (i = 0; i < vg_argc; i++)
2086 optlen += VG_(strlen)(vg_argv[i]) + 1;
2087 optlen += VG_(strlen)(exec)+1;
2088 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2089
2090 // Copy all valgrind args except the old --exec (if present)
2091 // VG_CLO_SEP is the separator.
2092 cp = optvar;
2093 for (i = 1; i < vg_argc; i++) {
2094 Char *arg = vg_argv[i];
2095
2096 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2097 // don't copy existing --exec= arg
2098 } else if (VG_(strcmp)(arg, "--") == 0) {
2099 // stop at "--"
2100 break;
2101 } else {
2102 // copy non "--exec" arg
2103 Int len = VG_(strlen)(arg);
2104 VG_(memcpy)(cp, arg, len);
2105 cp += len;
2106 *cp++ = VG_CLO_SEP;
2107 }
2108 }
2109 // Add the new --exec= option
2110 execlen = VG_(strlen)(exec);
2111 VG_(memcpy)(cp, exec, execlen);
2112 cp += execlen;
2113 *cp++ = VG_CLO_SEP;
2114
2115 *cp = '\0';
2116
2117 return optvar;
2118}
2119
2120// Build "/proc/self/fd/<execfd>".
2121Char* VG_(build_child_exename)( void )
2122{
2123 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2124 vg_assert(NULL != exename);
2125 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2126 return exename;
2127}
2128
sewardjde4a1d02002-03-22 01:27:54 +00002129
nethercote71980f02004-01-24 18:18:54 +00002130/*====================================================================*/
2131/*=== File descriptor setup ===*/
2132/*====================================================================*/
2133
2134static void setup_file_descriptors(void)
2135{
2136 struct vki_rlimit rl;
2137
2138 /* Get the current file descriptor limits. */
2139 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2140 rl.rlim_cur = 1024;
2141 rl.rlim_max = 1024;
2142 }
2143
2144 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002145 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2146 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002147 } else {
2148 rl.rlim_cur = rl.rlim_max;
2149 }
2150
2151 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002152 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2153 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002154
2155 /* Update the soft limit. */
2156 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2157
nethercotef6a1d502004-08-09 12:21:57 +00002158 if (vgexecfd != -1)
2159 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002160 if (VG_(clexecfd) != -1)
2161 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2162}
2163
nethercote71980f02004-01-24 18:18:54 +00002164/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002165/*=== Initialise program data/text, etc. ===*/
2166/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002167
sewardjb5f6f512005-03-10 23:59:00 +00002168static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2169 UInt dev, UInt ino, ULong foffset,
2170 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002171{
nethercote71980f02004-01-24 18:18:54 +00002172 /* Only record valgrind mappings for now, without loading any
2173 symbols. This is so we know where the free space is before we
2174 start allocating more memory (note: heap is OK, it's just mmap
2175 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002176 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2177 if (0)
2178 VG_(printf)("init1: %p-%p prot %s\n",
2179 start, start+size, VG_(prot_str)(prot));
2180 VG_(map_file_segment)(start, size, prot,
2181 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2182 dev, ino, foffset, filename);
2183 /* update VG_(valgrind_last) if it looks wrong */
2184 if (start+size > VG_(valgrind_last))
2185 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002186 }
sewardjde4a1d02002-03-22 01:27:54 +00002187}
2188
nethercote71980f02004-01-24 18:18:54 +00002189// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002190Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002191
sewardjb5f6f512005-03-10 23:59:00 +00002192/*
2193 This second pass adds in client mappings, and loads symbol tables
2194 for all interesting mappings. The trouble is that things can
2195 change as we go, because we're calling the Tool to track memory as
2196 we find it.
2197
2198 So for Valgrind mappings, we don't replace any mappings which
2199 aren't still identical (which will include the .so mappings, so we
2200 will load their symtabs)>
2201 */
2202static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2203 UInt dev, UInt ino, ULong foffset,
2204 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002205{
nethercote71980f02004-01-24 18:18:54 +00002206 UInt flags;
2207 Bool is_stack_segment;
2208 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002209
nethercote71980f02004-01-24 18:18:54 +00002210 is_stack_segment
2211 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002212
sewardjb5f6f512005-03-10 23:59:00 +00002213 if (0)
2214 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2215 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002216
nethercote71980f02004-01-24 18:18:54 +00002217 if (is_stack_segment)
2218 flags = SF_STACK | SF_GROWDOWN;
2219 else
2220 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002221
nethercote71980f02004-01-24 18:18:54 +00002222 if (filename != NULL)
2223 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002224
sewardjb5f6f512005-03-10 23:59:00 +00002225#if 0
2226 // This needs to be fixed properly. jrs 20050307
2227 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2228 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002229
sewardjb5f6f512005-03-10 23:59:00 +00002230 /* We have to be a bit careful about inserting new mappings into
2231 the Valgrind part of the address space. We're actively
2232 changing things as we parse these mappings, particularly in
2233 shadow memory, and so we don't want to overwrite those
2234 changes. Therefore, we only insert/update a mapping if it is
2235 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002236
sewardjb5f6f512005-03-10 23:59:00 +00002237 NOTE: we're only talking about the Segment list mapping
2238 metadata; this doesn't actually mmap anything more. */
2239 if (filename || (s && s->addr == start && s->len == size)) {
2240 flags |= SF_VALGRIND;
2241 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2242 } else {
2243 /* assert range is already mapped */
2244 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2245 }
2246 } else
2247#endif
2248 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2249
2250 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2251 VG_TRACK( new_mem_startup, start, size,
2252 !!(prot & VKI_PROT_READ),
2253 !!(prot & VKI_PROT_WRITE),
2254 !!(prot & VKI_PROT_EXEC));
2255 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002256
nethercote71980f02004-01-24 18:18:54 +00002257 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002258 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002259 vg_assert(0 != r_esp);
2260 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002261 if (0) {
2262 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002263 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002264 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2265 r_esp, start+size);
2266 }
nethercote71980f02004-01-24 18:18:54 +00002267 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002268 // what's this for?
2269 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002270 }
sewardjde4a1d02002-03-22 01:27:54 +00002271}
2272
2273
nethercote71980f02004-01-24 18:18:54 +00002274/*====================================================================*/
2275/*=== Sanity check machinery (permanently engaged) ===*/
2276/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002277
2278/* A fast sanity check -- suitable for calling circa once per
2279 millisecond. */
2280
nethercote885dd912004-08-03 23:14:00 +00002281void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002282{
sewardjb5f6f512005-03-10 23:59:00 +00002283 ThreadId tid;
2284
njn37cea302002-09-30 11:24:00 +00002285 VGP_PUSHCC(VgpCoreCheapSanity);
2286
nethercote27fec902004-06-16 21:26:32 +00002287 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002288
2289 /* --- First do all the tests that we can do quickly. ---*/
2290
nethercote297effd2004-08-02 15:07:57 +00002291 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002292
njn25e49d8e72002-09-23 09:36:25 +00002293 /* Check stuff pertaining to the memory check system. */
2294
2295 /* Check that nobody has spuriously claimed that the first or
2296 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002297 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002298 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002299 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002300 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002301 }
njn25e49d8e72002-09-23 09:36:25 +00002302
2303 /* --- Now some more expensive checks. ---*/
2304
2305 /* Once every 25 times, check some more expensive stuff. */
2306 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002307 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002308 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002309
njn37cea302002-09-30 11:24:00 +00002310 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002311 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002312
2313# if 0
2314 { void zzzmemscan(void); zzzmemscan(); }
2315# endif
2316
nethercote297effd2004-08-02 15:07:57 +00002317 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002318 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002319
2320 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002321 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002322 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002323 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002324 }
sewardjb5f6f512005-03-10 23:59:00 +00002325
2326 /* Check that Segments and /proc/self/maps match up */
2327 //vg_assert(VG_(sanity_check_memory)());
2328
2329 /* Look for stack overruns. Visit all threads. */
2330 for(tid = 1; tid < VG_N_THREADS; tid++) {
2331 Int remains;
2332
2333 if (VG_(threads)[tid].status == VgTs_Empty ||
2334 VG_(threads)[tid].status == VgTs_Zombie)
2335 continue;
2336
2337 remains = VGA_(stack_unused)(tid);
2338 if (remains < VKI_PAGE_SIZE)
2339 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2340 tid, remains);
2341 }
2342
njn25e49d8e72002-09-23 09:36:25 +00002343 /*
nethercote297effd2004-08-02 15:07:57 +00002344 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002345 */
njn37cea302002-09-30 11:24:00 +00002346 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002347 }
2348
nethercote27fec902004-06-16 21:26:32 +00002349 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002350 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002351 /* Check sanity of the low-level memory manager. Note that bugs
2352 in the client's code can cause this to fail, so we don't do
2353 this check unless specially asked for. And because it's
2354 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002355 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002356 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002357 }
njn37cea302002-09-30 11:24:00 +00002358 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002359}
nethercote71980f02004-01-24 18:18:54 +00002360
2361
2362/*====================================================================*/
2363/*=== main() ===*/
2364/*====================================================================*/
2365
nethercotec314eba2004-07-15 12:59:41 +00002366/*
2367 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002368 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002369 loads the client executable (and the dynamic linker, if necessary)
2370 into the client part, and calls into Valgrind proper.
2371
2372 The code is careful not to allow spurious mappings to appear in the
2373 wrong parts of the address space. In particular, to make sure
2374 dlopen puts things in the right place, it will pad out the forbidden
2375 chunks of address space so that dlopen is forced to put things where
2376 we want them.
2377
2378 The memory map it creates is:
2379
njn80950732005-03-26 00:18:45 +00002380 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002381 | client address space |
2382 : :
2383 : :
2384 | client stack |
2385 client_end +-------------------------+
2386 | redzone |
2387 shadow_base +-------------------------+
2388 | |
nethercote996901a2004-08-03 13:29:09 +00002389 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002390 | (may be 0 sized) |
2391 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002392 valgrind_base +-------------------------+
2393 | kickstart executable |
2394 | valgrind heap vvvvvvvvv| (barely used)
2395 - -
2396 | valgrind .so files |
2397 | and mappings |
2398 - -
2399 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002400 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002401 : kernel :
2402
2403 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2404 VG_(mmap)(), we need to build the segment skip-list, so we know where
2405 we can put things. However, building that structure requires
2406 allocating memory. So we need to a bootstrapping process. It's done
2407 by making VG_(arena_malloc)() have a special static superblock that's
2408 used for the first 1MB's worth of allocations. This is enough to
2409 build the segment skip-list.
2410*/
2411
nethercote31779c72004-07-30 21:50:15 +00002412static int prmap(char *start, char *end, const char *perm, off_t off,
2413 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002414 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2415 start, end, perm, maj, min, ino);
2416 return True;
2417}
2418
sewardjb5f6f512005-03-10 23:59:00 +00002419int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002420{
2421 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002422 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002423 const char *exec = NULL;
2424 char *preload; /* tool-specific LD_PRELOAD .so */
2425 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002426 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002427 struct exeinfo info;
2428 ToolInfo *toolinfo = NULL;
2429 void *tool_dlhandle;
2430 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002431 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002432 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002433 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002434 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002435
2436 //============================================================
2437 // Nb: startup is complex. Prerequisites are shown at every step.
2438 //
2439 // *** Be very careful when messing with the order ***
2440 //============================================================
2441
nethercotef4928da2004-06-15 10:54:40 +00002442 //============================================================
2443 // Command line argument handling order:
2444 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002445 // (including the tool-specific usage)
2446 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002447 // * Then, if client is missing, abort with error msg
2448 // * Then, if any cmdline args are bad, abort with error msg
2449 //============================================================
2450
fitzhardingeb50068f2004-02-24 23:42:55 +00002451 // Get the current process datasize rlimit, and set it to zero.
2452 // This prevents any internal uses of brk() from having any effect.
2453 // We remember the old value so we can restore it on exec, so that
2454 // child processes will have a reasonable brk value.
2455 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2456 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2457 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002458
2459 // Get the current process stack rlimit.
2460 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2461
nethercote71980f02004-01-24 18:18:54 +00002462 //--------------------------------------------------------------
2463 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002464 // p: none
nethercote71980f02004-01-24 18:18:54 +00002465 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002466 {
2467 void* init_sp = argv - 1;
2468 padfile = scan_auxv(init_sp);
2469 }
nethercote71980f02004-01-24 18:18:54 +00002470 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002471 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002472 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002473 }
2474
2475 //--------------------------------------------------------------
2476 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002477 // p: none
nethercote71980f02004-01-24 18:18:54 +00002478 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002479 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002480 if (cp != NULL)
2481 VG_(libdir) = cp;
2482 }
2483
2484 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002485 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2486 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002487 // p: none
nethercote71980f02004-01-24 18:18:54 +00002488 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002489 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002490 pre_process_cmd_line_options(&need_help, &tool, &exec);
2491
2492 //==============================================================
2493 // Nb: once a tool is specified, the tool.so must be loaded even if
2494 // they specified --help or didn't specify a client program.
2495 //==============================================================
2496
2497 //--------------------------------------------------------------
2498 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002499 // p: set-libdir [for VG_(libdir)]
2500 // p: pre_process_cmd_line_options() [for 'tool']
2501 //--------------------------------------------------------------
2502 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2503
2504 //==============================================================
2505 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002506 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002507 //==============================================================
2508
2509 //--------------------------------------------------------------
2510 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002511 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002512 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002513 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002514
2515 //--------------------------------------------------------------
2516 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002517 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2518 // p: layout_remaining_space [so there's space]
2519 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002520 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002521
2522 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002523 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002524 // p: layout_remaining_space() [everything must be mapped in before now]
2525 // p: load_client() [ditto]
2526 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002527 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2528 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002529
2530 //--------------------------------------------------------------
2531 // Set up client's environment
2532 // p: set-libdir [for VG_(libdir)]
2533 // p: load_tool() [for 'preload']
2534 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002535 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002536
2537 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002538 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002539 // p: load_client() [for 'info']
2540 // p: fix_environment() [for 'env']
2541 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002542 {
2543 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002544
nethercote4ad74312004-10-26 09:59:49 +00002545 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2546 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002547 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002548 }
nethercote71980f02004-01-24 18:18:54 +00002549
2550 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002551 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002552 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002553 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002554
2555 //==============================================================
2556 // Finished setting up operating environment. Now initialise
2557 // Valgrind. (This is where the old VG_(main)() started.)
2558 //==============================================================
2559
2560 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002561 // setup file descriptors
2562 // p: n/a
2563 //--------------------------------------------------------------
2564 setup_file_descriptors();
2565
2566 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002567 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002568 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002569 //--------------------------------------------------------------
2570 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2571
2572 //==============================================================
2573 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2574 //==============================================================
2575
2576 //--------------------------------------------------------------
2577 // Init tool: pre_clo_init, process cmd line, post_clo_init
2578 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2579 // p: load_tool() [for 'tool']
2580 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2581 // p: parse_procselfmaps [so VG segments are setup so tool can
2582 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002583 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002584 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002585 VG_(tool_init_dlsym)(tool_dlhandle);
2586 VG_(sanity_check_needs)();
2587
nethercotef4928da2004-06-15 10:54:40 +00002588 // If --tool and --help/--help-debug was given, now give the core+tool
2589 // help message
nethercotef4928da2004-06-15 10:54:40 +00002590 if (need_help) {
2591 usage(/*--help-debug?*/2 == need_help);
2592 }
nethercotec314eba2004-07-15 12:59:41 +00002593 process_cmd_line_options(client_auxv, tool);
2594
njn26f02512004-11-22 18:33:15 +00002595 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002596
2597 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002598 // Determine CPU architecture and subarchitecture
2599 // p: none
2600 //--------------------------------------------------------------
2601 { Bool ok = VGA_(getArchAndSubArch)(
2602 & VG_(vex_arch), & VG_(vex_subarch) );
2603 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002604 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002605 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002606 VG_(printf)(" Supported CPUs are:\n");
2607 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2608 "AMD Athlon or above)\n");
2609 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002610 VG_(exit)(1);
2611 }
2612 if (VG_(clo_verbosity) > 2) {
2613 VG_(message)(Vg_DebugMsg,
2614 "Host CPU: arch = %s, subarch = %s",
2615 LibVEX_ppVexArch( VG_(vex_arch) ),
2616 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2617 }
2618 }
2619
2620 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002621 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002622 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002623 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002624 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002625 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002626 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002627 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002628 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002629
sewardja4da2f32005-03-02 14:06:08 +00002630#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002631 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002632 // Protect client trampoline page (which is also sysinfo stuff)
2633 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002634 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002635 {
2636 Segment *seg;
2637 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2638 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002639#endif
sewardjb5f6f512005-03-10 23:59:00 +00002640 /* Make sure this segment isn't treated as stack */
2641 seg = VG_(find_segment)(VG_(client_trampoline_code));
2642 if (seg)
2643 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2644 }
2645
nethercotec314eba2004-07-15 12:59:41 +00002646 //==============================================================
2647 // Can use VG_(map)() after segments set up
2648 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002649
2650 //--------------------------------------------------------------
2651 // Allow GDB attach
2652 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2653 //--------------------------------------------------------------
2654 /* Hook to delay things long enough so we can get the pid and
2655 attach GDB in another shell. */
2656 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002657 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2658 /* jrs 20050206: I don't understand why this works on x86. On
2659 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2660 work. */
2661 /* do "jump *$eip" to skip this in gdb (x86) */
2662 //VG_(do_syscall0)(__NR_pause);
2663 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002664 }
2665
sewardjb5d320c2005-03-13 18:57:15 +00002666 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002667 // Search for file descriptors that are inherited from our parent
2668 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2669 //--------------------------------------------------------------
2670 if (VG_(clo_track_fds))
2671 VG_(init_preopened_fds)();
2672
2673 //--------------------------------------------------------------
2674 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002675 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2676 //--------------------------------------------------------------
2677 VG_(scheduler_init)();
2678
2679 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002680 // Initialise the pthread model
2681 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002682 // load_client() [for 'client_eip']
2683 // setup_client_stack() [for 'sp_at_startup']
2684 // setup_scheduler() [for the rest of state 1 stuff]
2685 //--------------------------------------------------------------
2686 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002687
2688 // Tell the tool that we just wrote to the registers.
2689 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2690 sizeof(VexGuestArchState));
2691
2692 // Record the instr ptr offset, for use by asm code.
njn35172bc2005-03-26 00:04:03 +00002693 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, VGA_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002694
2695 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002696 // Initialise the pthread model
2697 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002698 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002699 //if (VG_(clo_model_pthreads))
2700 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002701
2702 //--------------------------------------------------------------
2703 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002704 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002705 //--------------------------------------------------------------
2706 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2707 VG_(sigstartup_actions)();
2708
2709 //--------------------------------------------------------------
2710 // Perhaps we're profiling Valgrind?
2711 // p: process_cmd_line_options() [for VG_(clo_profile)]
2712 // p: others?
2713 //
2714 // XXX: this seems to be broken? It always says the tool wasn't built
2715 // for profiling; vg_profile.c's functions don't seem to be overriding
2716 // vg_dummy_profile.c's?
2717 //
2718 // XXX: want this as early as possible. Looking for --profile
2719 // in pre_process_cmd_line_options() could get it earlier.
2720 //--------------------------------------------------------------
2721 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002722 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002723
2724 VGP_PUSHCC(VgpStartup);
2725
2726 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002727 // Read suppression file
2728 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2729 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002730 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002731 VG_(load_suppressions)();
2732
2733 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002734 // Initialise translation table and translation cache
2735 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2736 // aren't identified as part of the client, which would waste
2737 // > 20M of virtual address space.]
2738 //--------------------------------------------------------------
2739 VG_(init_tt_tc)();
2740
2741 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002742 // Read debug info to find glibc entry points to intercept
2743 // p: parse_procselfmaps? [XXX for debug info?]
2744 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2745 //--------------------------------------------------------------
2746 VG_(setup_code_redirect_table)();
2747
2748 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002749 // Verbosity message
2750 // p: end_rdtsc_calibration [so startup message is printed first]
2751 //--------------------------------------------------------------
2752 if (VG_(clo_verbosity) == 1)
2753 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2754 if (VG_(clo_verbosity) > 0)
2755 VG_(message)(Vg_UserMsg, "");
2756
2757 //--------------------------------------------------------------
2758 // Setup pointercheck
2759 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2760 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002761 if (VG_(clo_pointercheck))
2762 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002763
nethercote71980f02004-01-24 18:18:54 +00002764 //--------------------------------------------------------------
2765 // Run!
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002768
sewardjb5f6f512005-03-10 23:59:00 +00002769 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002770
sewardjb5f6f512005-03-10 23:59:00 +00002771 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002772
sewardjb5f6f512005-03-10 23:59:00 +00002773 abort();
2774}
2775
2776
2777/* Do everything which needs doing when the last thread exits */
2778void VG_(shutdown_actions)(ThreadId tid)
2779{
2780 vg_assert(tid == VG_(master_tid));
2781 vg_assert(VG_(is_running_thread)(tid));
2782
2783 // Wait for all other threads to exit.
2784 VGA_(reap_threads)(tid);
2785
2786 VG_(clo_model_pthreads) = False;
2787
2788 // Clean the client up before the final report
2789 VGA_(final_tidyup)(tid);
2790
2791 // OK, done
2792 VG_(exit_thread)(tid);
2793
2794 /* should be no threads left */
2795 vg_assert(VG_(count_living_threads)() == 0);
2796
2797 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002798 //--------------------------------------------------------------
2799 // Finalisation: cleanup, messages, etc. Order no so important, only
2800 // affects what order the messages come.
2801 //--------------------------------------------------------------
2802 if (VG_(clo_verbosity) > 0)
2803 VG_(message)(Vg_UserMsg, "");
2804
nethercote71980f02004-01-24 18:18:54 +00002805 /* Print out file descriptor summary and stats. */
2806 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002807 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002808
njn95ec8702004-11-22 16:46:13 +00002809 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002810 VG_(show_all_errors)();
2811
sewardjb5f6f512005-03-10 23:59:00 +00002812 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002813
nethercote885dd912004-08-03 23:14:00 +00002814 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002815
2816 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002817 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002818
nethercote71980f02004-01-24 18:18:54 +00002819 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002820 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002821 if (VG_(clo_profile_flags) > 0)
2822 VG_(show_BB_profile)();
2823
sewardj8b635a42004-11-22 19:01:47 +00002824 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002825 if (0)
2826 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002827
nethercote71980f02004-01-24 18:18:54 +00002828}
2829
sewardjde4a1d02002-03-22 01:27:54 +00002830/*--------------------------------------------------------------------*/
2831/*--- end vg_main.c ---*/
2832/*--------------------------------------------------------------------*/