blob: d49d966c2da332c7aec5ad7797a4aae6c01e3dd6 [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
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 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"
nethercote71980f02004-01-24 18:18:54 +000035
36#include <dirent.h>
37#include <dlfcn.h>
38#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000039#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000040#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000041#include <string.h>
42#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/wait.h>
46#include <unistd.h>
47
sewardjb5f6f512005-03-10 23:59:00 +000048#include "memcheck/memcheck.h"
49
thughes74b8de22004-04-22 18:12:31 +000050#ifndef AT_DCACHEBSIZE
51#define AT_DCACHEBSIZE 19
52#endif /* AT_DCACHEBSIZE */
53
54#ifndef AT_ICACHEBSIZE
55#define AT_ICACHEBSIZE 20
56#endif /* AT_ICACHEBSIZE */
57
58#ifndef AT_UCACHEBSIZE
59#define AT_UCACHEBSIZE 21
60#endif /* AT_UCACHEBSIZE */
61
nethercote71980f02004-01-24 18:18:54 +000062#ifndef AT_SYSINFO
63#define AT_SYSINFO 32
64#endif /* AT_SYSINFO */
65
66#ifndef AT_SYSINFO_EHDR
67#define AT_SYSINFO_EHDR 33
68#endif /* AT_SYSINFO_EHDR */
69
70#ifndef AT_SECURE
71#define AT_SECURE 23 /* secure mode boolean */
72#endif /* AT_SECURE */
73
nethercote71980f02004-01-24 18:18:54 +000074/* redzone gap between client address space and shadow */
75#define REDZONE_SIZE (1 * 1024*1024)
76
77/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000078#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000079
nethercotee2097312004-06-27 12:29:56 +000080/* Proportion of client space for its heap (rest is for mmaps + stack) */
81#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000082
83/*====================================================================*/
84/*=== Global entities not referenced from generated code ===*/
85/*====================================================================*/
86
sewardjde4a1d02002-03-22 01:27:54 +000087/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000088 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000089 ------------------------------------------------------------------ */
90
nethercote71980f02004-01-24 18:18:54 +000091/* Client address space, lowest to highest (see top of ume.c) */
92Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000093Addr VG_(client_end);
94Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000095Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000096Addr VG_(clstk_base);
97Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000098
99Addr VG_(brk_base); /* start of brk */
100Addr VG_(brk_limit); /* current brk */
101
nethercote996901a2004-08-03 13:29:09 +0000102Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000104
105Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000106
nethercote820bd8c2004-09-07 23:04:49 +0000107// Note that VG_(valgrind_last) names the last byte of the section, whereas
108// the VG_(*_end) vars name the byte one past the end of the section.
109Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000110
nethercote73b526f2004-10-31 18:48:21 +0000111struct vki_rlimit VG_(client_rlimit_data);
112struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000113
fitzhardinge98abfc72003-12-16 02:05:15 +0000114/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000115static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000116
117/* client executable */
118Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000119
120/* Path to library directory */
121const Char *VG_(libdir) = VG_LIBDIR;
122
123/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000124static Int vg_argc;
125static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000126
sewardjb5f6f512005-03-10 23:59:00 +0000127/* The master thread the one which will be responsible for mopping
128 everything up at exit. Normally it is tid 1, since that's the
129 first thread created, but it may be something else after a
130 fork(). */
131ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000132
thughesad1c9562004-06-26 11:27:52 +0000133/* Application-visible file descriptor limits */
134Int VG_(fd_soft_limit) = -1;
135Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000136
nethercote4ad74312004-10-26 09:59:49 +0000137/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000138 envp[] as extracted from the client's stack at startup-time. */
139Int VG_(client_argc);
140Char** VG_(client_argv);
141Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000142
njn16de5572004-11-27 14:27:21 +0000143// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000144OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000145
sewardj51ac0872004-12-21 01:20:49 +0000146/* Indicates what arch and subarch we are running on. */
147VexArch VG_(vex_arch) = VexArch_INVALID;
148VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
149
150
sewardjde4a1d02002-03-22 01:27:54 +0000151/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000152 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000153 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
nethercote71980f02004-01-24 18:18:54 +0000155/* Counts downwards in VG_(run_innerloop). */
156UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000157
158/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000159ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161/* Tell the logging mechanism whether we are logging to a file
162 descriptor or a socket descriptor. */
163Bool VG_(logging_to_filedes) = True;
164
sewardj73cf3bc2002-11-03 03:20:15 +0000165
nethercote71980f02004-01-24 18:18:54 +0000166/*====================================================================*/
167/*=== Counters, for profiling purposes only ===*/
168/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000169
sewardjde4a1d02002-03-22 01:27:54 +0000170/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000171static UInt sanity_fast_count = 0;
172static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000173
nethercote3a42fb82004-08-03 18:08:50 +0000174static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000175{
nethercote3a42fb82004-08-03 18:08:50 +0000176 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000177 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000178 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000179 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000182 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000183
nethercote71980f02004-01-24 18:18:54 +0000184 VG_(message)(Vg_DebugMsg,
185 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000186 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000189 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000190 VG_(message)(Vg_DebugMsg, "");
191 VG_(message)(Vg_DebugMsg,
192 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000193 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000194 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000195 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000196 //VG_(print_shadow_stats)();
197 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000198 VG_(message)(Vg_DebugMsg,
199 "------ Valgrind's ExeContext management stats follow ------" );
200 VG_(print_ExeContext_stats)();
201 }
nethercote71980f02004-01-24 18:18:54 +0000202}
203
204
205/*====================================================================*/
206/*=== Miscellaneous global functions ===*/
207/*====================================================================*/
208
nethercotecf97ffb2004-09-09 13:40:31 +0000209static Int ptrace_setregs(Int pid, ThreadId tid)
210{
sewardj2a99cf62004-11-24 10:44:19 +0000211 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000212}
213
nethercote04d0fbc2004-01-26 16:48:06 +0000214/* Start debugger and get it to attach to this process. Called if the
215 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000216 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000217 meaningfully get the debugger to continue the program, though; to
218 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000219void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000220{
221 Int pid;
222
223 if ((pid = fork()) == 0) {
224 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000225 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000226
227 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000228 Int status;
229 Int res;
230
nethercote71980f02004-01-24 18:18:54 +0000231 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
232 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000233 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000234 kill(pid, SIGSTOP) == 0 &&
235 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000236 Char pidbuf[15];
237 Char file[30];
238 Char buf[100];
239 Char *bufptr;
240 Char *cmdptr;
241
242 VG_(sprintf)(pidbuf, "%d", pid);
243 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
244
245 bufptr = buf;
246 cmdptr = VG_(clo_db_command);
247
248 while (*cmdptr) {
249 switch (*cmdptr) {
250 case '%':
251 switch (*++cmdptr) {
252 case 'f':
253 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
254 bufptr += VG_(strlen)(file);
255 cmdptr++;
256 break;
257 case 'p':
258 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
259 bufptr += VG_(strlen)(pidbuf);
260 cmdptr++;
261 break;
262 default:
263 *bufptr++ = *cmdptr++;
264 break;
265 }
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 }
272
273 *bufptr++ = '\0';
274
275 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000276 res = VG_(system)(buf);
277 if (res == 0) {
278 VG_(message)(Vg_UserMsg, "");
279 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000280 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000281 } else {
282 VG_(message)(Vg_UserMsg, "Apparently failed!");
283 VG_(message)(Vg_UserMsg, "");
284 }
285 }
286
nethercote73b526f2004-10-31 18:48:21 +0000287 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000288 VG_(waitpid)(pid, &status, 0);
289 }
290}
291
292
293/* Print some helpful-ish text about unimplemented things, and give
294 up. */
295void VG_(unimplemented) ( Char* msg )
296{
297 VG_(message)(Vg_UserMsg, "");
298 VG_(message)(Vg_UserMsg,
299 "Valgrind detected that your program requires");
300 VG_(message)(Vg_UserMsg,
301 "the following unimplemented functionality:");
302 VG_(message)(Vg_UserMsg, " %s", msg);
303 VG_(message)(Vg_UserMsg,
304 "This may be because the functionality is hard to implement,");
305 VG_(message)(Vg_UserMsg,
306 "or because no reasonable program would behave this way,");
307 VG_(message)(Vg_UserMsg,
308 "or because nobody has yet needed it. In any case, let us know at");
309 VG_(message)(Vg_UserMsg,
310 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
311 VG_(message)(Vg_UserMsg,
312 "");
313 VG_(message)(Vg_UserMsg,
314 "Valgrind has to exit now. Sorry. Bye!");
315 VG_(message)(Vg_UserMsg,
316 "");
317 VG_(pp_sched_status)();
318 VG_(exit)(1);
319}
320
sewardj2a99cf62004-11-24 10:44:19 +0000321/* Get the simulated stack pointer */
322Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000323{
njncf45fd42004-11-24 16:30:22 +0000324 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000325}
326
njnea4b28c2004-11-30 16:04:58 +0000327
nethercote71980f02004-01-24 18:18:54 +0000328/*====================================================================*/
329/*=== Check we were launched by stage 1 ===*/
330/*====================================================================*/
331
332/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000333static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000334{
nethercoteebf1d862004-11-01 18:22:05 +0000335 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000336 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000337
338 for (; auxv->a_type != AT_NULL; auxv++)
339 switch(auxv->a_type) {
340 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000341 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000342 found |= 1;
343 break;
344
345 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000346 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000347 found |= 2;
348 break;
nethercote7f390022004-10-25 17:18:24 +0000349
350 case AT_PHDR:
351 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
352 break;
nethercote71980f02004-01-24 18:18:54 +0000353 }
354
nethercote361a14e2004-07-26 11:11:56 +0000355 if ( found != (1|2) ) {
356 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000357 exit(127);
358 }
nethercote31779c72004-07-30 21:50:15 +0000359 vg_assert(padfile >= 0);
360 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000361}
362
363
364/*====================================================================*/
365/*=== Address space determination ===*/
366/*====================================================================*/
367
nethercote7f390022004-10-25 17:18:24 +0000368extern char _start[];
369
nethercote31779c72004-07-30 21:50:15 +0000370static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000371{
nethercotea3c3cf22004-11-01 18:38:00 +0000372 Int ires;
373 void* vres;
374 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000375
nethercote7f390022004-10-25 17:18:24 +0000376 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
377 // this is a workable approximation
378 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000379 VG_(valgrind_base) = PGROUNDDN(&_start);
380 }
381
nethercote820bd8c2004-09-07 23:04:49 +0000382 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000383
nethercote31779c72004-07-30 21:50:15 +0000384 // This gives the client the largest possible address space while
385 // taking into account the tool's shadow needs.
386 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000387 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000388 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000389 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000390 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000391 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000392 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote31779c72004-07-30 21:50:15 +0000394 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000395 VG_(shadow_end) = VG_(valgrind_base);
396 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000397
nethercotee2097312004-06-27 12:29:56 +0000398#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
399
nethercote71980f02004-01-24 18:18:54 +0000400 if (0)
nethercotee2097312004-06-27 12:29:56 +0000401 VG_(printf)(
402 "client_base %8x (%dMB)\n"
403 "client_mapbase %8x (%dMB)\n"
404 "client_end %8x (%dMB)\n"
405 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000406 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000407 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000408 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000409 VG_(client_base), SEGSIZE(client_base, client_mapbase),
410 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
411 VG_(client_end), SEGSIZE(client_end, shadow_base),
412 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000413 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000414 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
415 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000416 );
417
418#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000419
420 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000421 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000422 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000423 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000424
425 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000426 ires = munmap((void*)VG_(client_base), client_size);
427 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000428
429 // Map shadow memory.
430 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000431 if (shadow_size != 0) {
432 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000433 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000434 if ((void*)-1 == vres) {
435 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000436 "valgrind: Could not allocate address space (%p bytes)\n"
437 "valgrind: for shadow memory\n"
438 "valgrind: Possible causes:\n"
439 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
440 "valgrind: needs at least 1.5GB swap space.\n"
441 "valgrind: - Or, your virtual memory size may be limited (check\n"
442 "valgrind: with 'ulimit -v').\n"
443 "valgrind: - Or, your system may use a kernel that provides only a\n"
444 "valgrind: too-small (eg. 2GB) user address space.\n"
445 , (void*)shadow_size
446 );
nethercoted4722622004-08-30 19:36:42 +0000447 exit(1);
448 }
nethercotee567e702004-07-10 17:49:17 +0000449 }
nethercote71980f02004-01-24 18:18:54 +0000450}
451
452/*====================================================================*/
453/*=== Command line setup ===*/
454/*====================================================================*/
455
456/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
457static char* get_file_clo(char* dir)
458{
459# define FLEN 512
460 Int fd, n;
461 struct stat s1;
462 char* f_clo = NULL;
463 char filename[FLEN];
464
465 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
466 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
467 if ( fd > 0 ) {
468 if ( 0 == fstat(fd, &s1) ) {
469 f_clo = malloc(s1.st_size+1);
470 vg_assert(f_clo);
471 n = read(fd, f_clo, s1.st_size);
472 if (n == -1) n = 0;
473 f_clo[n] = '\0';
474 }
475 close(fd);
476 }
477 return f_clo;
478# undef FLEN
479}
480
nethercotee2097312004-06-27 12:29:56 +0000481#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
482
nethercote71980f02004-01-24 18:18:54 +0000483static Int count_args(char* s)
484{
485 Int n = 0;
486 if (s) {
487 char* cp = s;
488 while (True) {
489 // We have alternating sequences: blanks, non-blanks, blanks...
490 // count the non-blanks sequences.
491 while ( ISSPACE(*cp) ) cp++;
492 if ( !*cp ) break;
493 n++;
494 while ( !ISSPACE(*cp) && *cp ) cp++;
495 }
496 }
497 return n;
498}
499
500/* add args out of environment, skipping multiple spaces and -- args */
501static char** copy_args( char* s, char** to )
502{
503 if (s) {
504 char* cp = s;
505 while (True) {
506 // We have alternating sequences: blanks, non-blanks, blanks...
507 // copy the non-blanks sequences, and add terminating '\0'
508 while ( ISSPACE(*cp) ) cp++;
509 if ( !*cp ) break;
510 *to++ = cp;
511 while ( !ISSPACE(*cp) && *cp ) cp++;
512 if ( *cp ) *cp++ = '\0'; // terminate if necessary
513 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
514 }
515 }
516 return to;
517}
518
nethercotee2097312004-06-27 12:29:56 +0000519#undef ISSPACE
520
nethercote71980f02004-01-24 18:18:54 +0000521// Augment command line with arguments from environment and .valgrindrc
522// files.
523static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
524{
nethercotef6a1d502004-08-09 12:21:57 +0000525 int vg_argc0 = *vg_argc_inout;
526 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000527
528 char* env_clo = getenv(VALGRINDOPTS);
529 char* f1_clo = get_file_clo( getenv("HOME") );
530 char* f2_clo = get_file_clo(".");
531
532 /* copy any extra args from file or environment, if present */
533 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
534 /* ' ' separated extra options */
535 char **from;
536 char **to;
thughescaca0022004-09-13 10:20:34 +0000537 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
538
539 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
540
nethercote71980f02004-01-24 18:18:54 +0000541 env_arg_count = count_args(env_clo);
542 f1_arg_count = count_args(f1_clo);
543 f2_arg_count = count_args(f2_clo);
544
545 if (0)
546 printf("extra-argc=%d %d %d\n",
547 env_arg_count, f1_arg_count, f2_arg_count);
548
549 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000550 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000551 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000552 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000553 vg_assert(vg_argv0);
554 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000555
556 /* copy argv[0] */
557 *to++ = *from++;
558
559 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
560 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
561 * to override less local ones. */
562 to = copy_args(f1_clo, to);
563 to = copy_args(env_clo, to);
564 to = copy_args(f2_clo, to);
565
566 /* copy original arguments, stopping at command or -- */
567 while (*from) {
568 if (**from != '-')
569 break;
570 if (VG_STREQ(*from, "--")) {
571 from++; /* skip -- */
572 break;
573 }
574 *to++ = *from++;
575 }
576
577 /* add -- */
578 *to++ = "--";
579
nethercotef6a1d502004-08-09 12:21:57 +0000580 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000581
582 /* copy rest of original command line, then NULL */
583 while (*from) *to++ = *from++;
584 *to = NULL;
585 }
586
nethercotef6a1d502004-08-09 12:21:57 +0000587 *vg_argc_inout = vg_argc0;
588 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000589}
590
nethercotef6a1d502004-08-09 12:21:57 +0000591#define VG_CLO_SEP '\01'
592
nethercote71980f02004-01-24 18:18:54 +0000593static void get_command_line( int argc, char** argv,
594 Int* vg_argc_out, Char*** vg_argv_out,
595 char*** cl_argv_out )
596{
nethercotef6a1d502004-08-09 12:21:57 +0000597 int vg_argc0;
598 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000599 char** cl_argv;
600 char* env_clo = getenv(VALGRINDCLO);
601
602 if (env_clo != NULL && *env_clo != '\0') {
603 char *cp;
604 char **cpp;
605
nethercotef6a1d502004-08-09 12:21:57 +0000606 /* OK, VALGRINDCLO is set, which means we must be a child of another
607 Valgrind process using --trace-children, so we're getting all our
608 arguments from VALGRINDCLO, and the entire command line belongs to
609 the client (including argv[0]) */
610 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000611 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000612 if (*cp == VG_CLO_SEP)
613 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000614
nethercotef6a1d502004-08-09 12:21:57 +0000615 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
616 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000617
nethercotef6a1d502004-08-09 12:21:57 +0000618 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000619
620 *cpp++ = "valgrind"; /* nominal argv[0] */
621 *cpp++ = env_clo;
622
nethercotef6a1d502004-08-09 12:21:57 +0000623 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000624 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000625 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000626 *cp++ = '\0'; /* chop it up in place */
627 *cpp++ = cp;
628 }
629 }
630 *cpp = NULL;
631 cl_argv = argv;
632
633 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000634 Bool noaugment = False;
635
nethercote71980f02004-01-24 18:18:54 +0000636 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000637 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000638
nethercotef6a1d502004-08-09 12:21:57 +0000639 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000640 Char* arg = argv[vg_argc0];
641 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000642 break;
sewardjb5f6f512005-03-10 23:59:00 +0000643 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000644 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000645 break;
646 }
sewardjb5f6f512005-03-10 23:59:00 +0000647 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000648 }
nethercotef6a1d502004-08-09 12:21:57 +0000649 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000650
651 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000652 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000653 those extra args will already be present in VALGRINDCLO.
654 (We also don't do it when --command-line-only=yes.) */
655 if (!noaugment)
656 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000657 }
658
659 if (0) {
660 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000661 for (i = 0; i < vg_argc0; i++)
662 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000663 }
664
nethercotef6a1d502004-08-09 12:21:57 +0000665 *vg_argc_out = vg_argc0;
666 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000667 *cl_argv_out = cl_argv;
668}
669
670
671/*====================================================================*/
672/*=== Environment and stack setup ===*/
673/*====================================================================*/
674
675/* Scan a colon-separated list, and call a function on each element.
676 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000677 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000678 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000679
680 This routine will return True if (*func) returns True and False if
681 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000682*/
thughes4ad52d02004-06-27 17:37:21 +0000683static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000684{
685 char *cp, *entry;
686 int end;
687
688 if (colsep == NULL ||
689 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000690 return False;
nethercote71980f02004-01-24 18:18:54 +0000691
692 entry = cp = colsep;
693
694 do {
695 end = (*cp == '\0');
696
697 if (*cp == ':' || *cp == '\0') {
698 char save = *cp;
699
700 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000701 if ((*func)(entry)) {
702 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000703 return True;
thughes21942d92004-07-12 09:35:37 +0000704 }
nethercote71980f02004-01-24 18:18:54 +0000705 *cp = save;
706 entry = cp+1;
707 }
708 cp++;
709 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000710
711 return False;
712}
713
nethercote71980f02004-01-24 18:18:54 +0000714/* Prepare the client's environment. This is basically a copy of our
715 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000716 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000717
sewardjb5f6f512005-03-10 23:59:00 +0000718 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000719
720 Yummy. String hacking in C.
721
722 If this needs to handle any more variables it should be hacked
723 into something table driven.
724 */
725static char **fix_environment(char **origenv, const char *preload)
726{
727 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000728 static const char ld_preload[] = "LD_PRELOAD=";
729 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000730 static const int ld_preload_len = sizeof(ld_preload)-1;
731 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
732 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000733 char *inject_path;
734 int inject_path_len;
735 int vgliblen = strlen(VG_(libdir));
736 char **cpp;
737 char **ret;
738 int envc;
739 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
740
741 /* Find the vg_inject.so; also make room for the tool preload
742 library */
743 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
744 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000745 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000746
747 if (preload)
748 snprintf(inject_path, inject_path_len, "%s/%s:%s",
749 VG_(libdir), inject_so, preload);
750 else
751 snprintf(inject_path, inject_path_len, "%s/%s",
752 VG_(libdir), inject_so);
753
754 /* Count the original size of the env */
755 envc = 0; /* trailing NULL */
756 for (cpp = origenv; cpp && *cpp; cpp++)
757 envc++;
758
759 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000760 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000761 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000762
763 /* copy it over */
764 for (cpp = ret; *origenv; )
765 *cpp++ = *origenv++;
766 *cpp = NULL;
767
768 vg_assert(envc == (cpp - ret));
769
770 /* Walk over the new environment, mashing as we go */
771 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000772 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000773 int len = strlen(*cpp) + inject_path_len;
774 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000775 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000776
777 snprintf(cp, len, "%s%s:%s",
778 ld_preload, inject_path, (*cpp)+ld_preload_len);
779
780 *cpp = cp;
781
782 ld_preload_done = 1;
783 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
784 *cpp = "";
785 }
786 }
787
788 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000789 if (!ld_preload_done) {
790 int len = ld_preload_len + inject_path_len;
791 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000792 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000793
794 snprintf(cp, len, "%s%s",
795 ld_preload, inject_path);
796
797 ret[envc++] = cp;
798 }
799
sewardjb5f6f512005-03-10 23:59:00 +0000800 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000801 ret[envc] = NULL;
802
803 return ret;
804}
805
806extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000807
808/* Add a string onto the string table, and return its address */
809static char *copy_str(char **tab, const char *str)
810{
811 char *cp = *tab;
812 char *orig = cp;
813
814 while(*str)
815 *cp++ = *str++;
816 *cp++ = '\0';
817
818 if (0)
nethercote545fe672004-11-01 16:52:43 +0000819 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000820
821 *tab = cp;
822
823 return orig;
824}
825
826/*
827 This sets up the client's initial stack, containing the args,
828 environment and aux vector.
829
830 The format of the stack is:
831
832 higher address +-----------------+
833 | Trampoline code |
834 +-----------------+
835 | |
836 : string table :
837 | |
838 +-----------------+
839 | AT_NULL |
840 - -
841 | auxv |
842 +-----------------+
843 | NULL |
844 - -
845 | envp |
846 +-----------------+
847 | NULL |
848 - -
849 | argv |
850 +-----------------+
851 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000852 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000853 | undefined |
854 : :
855 */
nethercotec25c4492004-10-18 11:52:17 +0000856static Addr setup_client_stack(void* init_sp,
857 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000858 const struct exeinfo *info,
859 UInt** client_auxv)
860{
nethercotee567e702004-07-10 17:49:17 +0000861 void* res;
nethercote71980f02004-01-24 18:18:54 +0000862 char **cpp;
863 char *strtab; /* string table */
864 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000865 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000866 struct ume_auxv *auxv;
867 const struct ume_auxv *orig_auxv;
868 const struct ume_auxv *cauxv;
869 unsigned stringsize; /* total size of strings in bytes */
870 unsigned auxsize; /* total size of auxv in bytes */
871 int argc; /* total argc */
872 int envc; /* total number of env vars */
873 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000874 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000875
876 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000877 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000878
879 /* ==================== compute sizes ==================== */
880
881 /* first of all, work out how big the client stack will be */
882 stringsize = 0;
883
884 /* paste on the extra args if the loader needs them (ie, the #!
885 interpreter and its argument) */
886 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000887 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000888 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000889 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000890 }
nethercoted6a56872004-07-26 15:32:47 +0000891 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000892 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000893 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000894 }
895
896 /* now scan the args we're given... */
897 for (cpp = orig_argv; *cpp; cpp++) {
898 argc++;
899 stringsize += strlen(*cpp) + 1;
900 }
901
902 /* ...and the environment */
903 envc = 0;
904 for (cpp = orig_envp; cpp && *cpp; cpp++) {
905 envc++;
906 stringsize += strlen(*cpp) + 1;
907 }
908
909 /* now, how big is the auxv? */
910 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
911 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
912 if (cauxv->a_type == AT_PLATFORM)
913 stringsize += strlen(cauxv->u.a_ptr) + 1;
914 auxsize += sizeof(*cauxv);
915 }
916
917 /* OK, now we know how big the client stack is */
918 stacksize =
919 sizeof(int) + /* argc */
920 sizeof(char **)*argc + /* argv */
921 sizeof(char **) + /* terminal NULL */
922 sizeof(char **)*envc + /* envp */
923 sizeof(char **) + /* terminal NULL */
924 auxsize + /* auxv */
925 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000926 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000927
sewardj79048ce2005-02-18 08:28:32 +0000928 if (0) VG_(printf)("stacksize = %d\n", stacksize);
929
nethercotef84f6952004-07-15 14:58:33 +0000930 // decide where stack goes!
931 VG_(clstk_end) = VG_(client_end);
932
nethercote73b526f2004-10-31 18:48:21 +0000933 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000934
nethercote71980f02004-01-24 18:18:54 +0000935 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000936 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000937 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
938
nethercote71980f02004-01-24 18:18:54 +0000939 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000940 stringbase = strtab = (char *)(VG_(client_trampoline_code)
941 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000942
943 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000944
sewardj79048ce2005-02-18 08:28:32 +0000945 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000946 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000947 "clstk_base %p\n"
948 "clstk_end %p\n",
949 stringsize, auxsize, stacksize,
950 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000951
nethercote71980f02004-01-24 18:18:54 +0000952 /* ==================== allocate space ==================== */
953
954 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000955 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000956 PROT_READ | PROT_WRITE | PROT_EXEC,
957 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
958 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000959
960 /* ==================== copy client stack ==================== */
961
nethercotea3c3cf22004-11-01 18:38:00 +0000962 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000963
964 /* --- argc --- */
965 *ptr++ = argc; /* client argc */
966
967 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000968 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000969 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000970 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000971 }
nethercoted6a56872004-07-26 15:32:47 +0000972 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000973 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000974 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000975 }
976 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000977 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000978 }
979 *ptr++ = 0;
980
981 /* --- envp --- */
982 VG_(client_envp) = (Char **)ptr;
983 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000984 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000985 *ptr++ = 0;
986
987 /* --- auxv --- */
988 auxv = (struct ume_auxv *)ptr;
989 *client_auxv = (UInt *)auxv;
990
991 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
992 /* copy the entry... */
993 *auxv = *orig_auxv;
994
995 /* ...and fix up the copy */
996 switch(auxv->a_type) {
997 case AT_PHDR:
998 if (info->phdr == 0)
999 auxv->a_type = AT_IGNORE;
1000 else
1001 auxv->u.a_val = info->phdr;
1002 break;
1003
1004 case AT_PHNUM:
1005 if (info->phdr == 0)
1006 auxv->a_type = AT_IGNORE;
1007 else
1008 auxv->u.a_val = info->phnum;
1009 break;
1010
1011 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001012 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001013 break;
1014
1015 case AT_PLATFORM: /* points to a platform description string */
1016 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1017 break;
1018
1019 case AT_ENTRY:
1020 auxv->u.a_val = info->entry;
1021 break;
1022
1023 case AT_IGNORE:
1024 case AT_EXECFD:
1025 case AT_PHENT:
1026 case AT_PAGESZ:
1027 case AT_FLAGS:
1028 case AT_NOTELF:
1029 case AT_UID:
1030 case AT_EUID:
1031 case AT_GID:
1032 case AT_EGID:
1033 case AT_CLKTCK:
1034 case AT_HWCAP:
1035 case AT_FPUCW:
1036 case AT_DCACHEBSIZE:
1037 case AT_ICACHEBSIZE:
1038 case AT_UCACHEBSIZE:
1039 /* All these are pointerless, so we don't need to do anything
1040 about them. */
1041 break;
1042
1043 case AT_SECURE:
1044 /* If this is 1, then it means that this program is running
1045 suid, and therefore the dynamic linker should be careful
1046 about LD_PRELOAD, etc. However, since stage1 (the thing
1047 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001048 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001049 set AT_SECURE to 0. */
1050 auxv->u.a_val = 0;
1051 break;
1052
1053 case AT_SYSINFO:
1054 /* Leave this unmolested for now, but we'll update it later
1055 when we set up the client trampoline code page */
1056 break;
1057
1058 case AT_SYSINFO_EHDR:
1059 /* Trash this, because we don't reproduce it */
1060 auxv->a_type = AT_IGNORE;
1061 break;
1062
1063 default:
1064 /* stomp out anything we don't know about */
1065 if (0)
nethercote545fe672004-11-01 16:52:43 +00001066 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001067 auxv->a_type = AT_IGNORE;
1068 break;
1069
1070 }
1071 }
1072 *auxv = *orig_auxv;
1073 vg_assert(auxv->a_type == AT_NULL);
1074
njnc6168192004-11-29 13:54:10 +00001075// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1076// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001077#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001078 /* --- trampoline page --- */
1079 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1080 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001081#endif
nethercotef84f6952004-07-15 14:58:33 +00001082
nethercote71980f02004-01-24 18:18:54 +00001083 vg_assert((strtab-stringbase) == stringsize);
1084
nethercote5ee67ca2004-06-22 14:00:09 +00001085 /* We know the initial ESP is pointing at argc/argv */
1086 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001087 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001088
sewardj79048ce2005-02-18 08:28:32 +00001089 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001090 return cl_esp;
1091}
1092
1093/*====================================================================*/
1094/*=== Find executable ===*/
1095/*====================================================================*/
1096
thughes4ad52d02004-06-27 17:37:21 +00001097static const char* executable_name;
1098
1099static Bool match_executable(const char *entry) {
1100 char buf[strlen(entry) + strlen(executable_name) + 2];
1101
1102 /* empty PATH element means . */
1103 if (*entry == '\0')
1104 entry = ".";
1105
1106 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1107
1108 if (access(buf, R_OK|X_OK) == 0) {
1109 executable_name = strdup(buf);
1110 vg_assert(NULL != executable_name);
1111 return True;
1112 }
1113 return False;
1114}
1115
nethercote71980f02004-01-24 18:18:54 +00001116static const char* find_executable(const char* exec)
1117{
1118 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001119 executable_name = exec;
1120 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001121 /* no '/' - we need to search the path */
1122 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001123 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001124 }
thughes4ad52d02004-06-27 17:37:21 +00001125 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001126}
1127
1128
1129/*====================================================================*/
1130/*=== Loading tools ===*/
1131/*====================================================================*/
1132
1133static void list_tools(void)
1134{
1135 DIR *dir = opendir(VG_(libdir));
1136 struct dirent *de;
1137 int first = 1;
1138
1139 if (dir == NULL) {
1140 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001141 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001142 return;
1143 }
1144
nethercotef4928da2004-06-15 10:54:40 +00001145 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001146 int len = strlen(de->d_name);
1147
njn063c5402004-11-22 16:58:05 +00001148 /* look for vgtool_TOOL.so names */
1149 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1150 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001151 VG_STREQ(de->d_name + len - 3, ".so")) {
1152 if (first) {
1153 fprintf(stderr, "Available tools:\n");
1154 first = 0;
1155 }
1156 de->d_name[len-3] = '\0';
1157 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001158 }
1159 }
1160
1161 closedir(dir);
1162
1163 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001164 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1165 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001166}
1167
1168
1169/* Find and load a tool, and check it looks ok. Also looks to see if there's
1170 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1171static void load_tool( const char *toolname, void** handle_out,
1172 ToolInfo** toolinfo_out, char **preloadpath_out )
1173{
1174 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001175 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001176 char buf[len];
1177 void* handle;
1178 ToolInfo* toolinfo;
1179 char* preloadpath = NULL;
1180 Int* vg_malloc_redzonep;
1181
1182 // XXX: allowing full paths for --tool option -- does it make sense?
1183 // Doesn't allow for vgpreload_<tool>.so.
1184
1185 if (strchr(toolname, '/') != 0) {
1186 /* toolname contains '/', and so must be a pathname */
1187 handle = dlopen(toolname, RTLD_NOW);
1188 } else {
1189 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001190 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001191 handle = dlopen(buf, RTLD_NOW);
1192
1193 if (handle != NULL) {
1194 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1195 if (access(buf, R_OK) == 0) {
1196 preloadpath = strdup(buf);
1197 vg_assert(NULL != preloadpath);
1198 }
1199 }
1200 }
1201
1202 ok = (NULL != handle);
1203 if (!ok) {
1204 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1205 goto bad_load;
1206 }
1207
njn26f02512004-11-22 18:33:15 +00001208 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001209 ok = (NULL != toolinfo);
1210 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001211 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001212 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1213 goto bad_load;
1214 }
1215
1216 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1217 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001218 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001219 if (!ok) {
1220 fprintf(stderr, "Error:\n"
1221 " Tool and core interface versions do not match.\n"
1222 " Interface version used by core is: %d.%d (size %d)\n"
1223 " Interface version used by tool is: %d.%d (size %d)\n"
1224 " The major version numbers must match.\n",
1225 VG_CORE_INTERFACE_MAJOR_VERSION,
1226 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001227 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001228 toolinfo->interface_major_version,
1229 toolinfo->interface_minor_version,
1230 toolinfo->sizeof_ToolInfo);
1231 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1232 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001233 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001234 else
nethercote996901a2004-08-03 13:29:09 +00001235 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001236 goto bad_load;
1237 }
1238
1239 // Set redzone size for V's allocator
1240 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1241 if ( NULL != vg_malloc_redzonep ) {
1242 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1243 }
1244
1245 vg_assert(NULL != handle && NULL != toolinfo);
1246 *handle_out = handle;
1247 *toolinfo_out = toolinfo;
1248 *preloadpath_out = preloadpath;
1249 return;
1250
1251
1252 bad_load:
1253 if (handle != NULL)
1254 dlclose(handle);
1255
nethercotef4928da2004-06-15 10:54:40 +00001256 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001257 list_tools();
1258 exit(127);
1259}
1260
nethercotef4928da2004-06-15 10:54:40 +00001261
1262/*====================================================================*/
1263/*=== Command line errors ===*/
1264/*====================================================================*/
1265
1266static void abort_msg ( void )
1267{
nethercotef8548672004-06-21 12:42:35 +00001268 VG_(clo_log_to) = VgLogTo_Fd;
1269 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001270}
1271
1272void VG_(bad_option) ( Char* opt )
1273{
1274 abort_msg();
1275 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1276 VG_(printf)("valgrind: Use --help for more information.\n");
1277 VG_(exit)(1);
1278}
1279
nethercotef4928da2004-06-15 10:54:40 +00001280static void missing_prog ( void )
1281{
1282 abort_msg();
1283 VG_(printf)("valgrind: no program specified\n");
1284 VG_(printf)("valgrind: Use --help for more information.\n");
1285 VG_(exit)(1);
1286}
1287
1288static void config_error ( Char* msg )
1289{
1290 abort_msg();
1291 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1292 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1293 VG_(exit)(1);
1294}
1295
1296
nethercote71980f02004-01-24 18:18:54 +00001297/*====================================================================*/
1298/*=== Loading the client ===*/
1299/*====================================================================*/
1300
nethercotef4928da2004-06-15 10:54:40 +00001301static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001302 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1303{
1304 // If they didn't specify an executable with --exec, and didn't specify
1305 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001306 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001307 if (cl_argv[0] == NULL ||
1308 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1309 {
nethercotef4928da2004-06-15 10:54:40 +00001310 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001311 }
1312 }
1313
1314 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001315 info->exe_base = VG_(client_base);
1316 info->exe_end = VG_(client_end);
1317 info->argv = cl_argv;
1318
nethercotef4928da2004-06-15 10:54:40 +00001319 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001320 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001321 // Totally zero 'info' before continuing.
1322 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001323 } else {
1324 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001325 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001326 ret = do_exec(exec, info);
1327 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001328 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1329 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001330 exit(127);
1331 }
1332 }
1333
1334 /* Copy necessary bits of 'info' that were filled in */
1335 *client_eip = info->init_eip;
1336 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1337}
1338
nethercote969ecf12004-10-13 17:29:01 +00001339/*====================================================================*/
1340/*=== Address space unpadding ===*/
1341/*====================================================================*/
1342
1343typedef struct {
1344 char* killpad_start;
1345 char* killpad_end;
1346 struct stat* killpad_padstat;
1347} killpad_extra;
1348
1349static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1350 int maj, int min, int ino, void* ex)
1351{
1352 killpad_extra* extra = ex;
1353 void *b, *e;
1354 int res;
1355
1356 vg_assert(NULL != extra->killpad_padstat);
1357
1358 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1359 extra->killpad_padstat->st_ino != ino)
1360 return 1;
1361
1362 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1363 return 1;
1364
1365 if (segstart <= extra->killpad_start)
1366 b = extra->killpad_start;
1367 else
1368 b = segstart;
1369
1370 if (segend >= extra->killpad_end)
1371 e = extra->killpad_end;
1372 else
1373 e = segend;
1374
1375 res = munmap(b, (char *)e-(char *)b);
1376 vg_assert(0 == res);
1377
1378 return 1;
1379}
1380
1381// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001382static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001383{
1384 static struct stat padstat;
1385 killpad_extra extra;
1386 int res;
1387
sewardjb5f6f512005-03-10 23:59:00 +00001388 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001389
1390 res = fstat(padfile, &padstat);
1391 vg_assert(0 == res);
1392 extra.killpad_padstat = &padstat;
1393 extra.killpad_start = start;
1394 extra.killpad_end = end;
1395 foreach_map(killpad, &extra);
1396}
1397
sewardj2c5ffbe2005-03-12 13:32:06 +00001398static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001399{
1400 int res = close(padfile);
1401 vg_assert(0 == res);
1402}
1403
nethercote71980f02004-01-24 18:18:54 +00001404
1405/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001406/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001407/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001408
njn25e49d8e72002-09-23 09:36:25 +00001409/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001410VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001411Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001412Bool VG_(clo_db_attach) = False;
1413Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001414Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001415Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001416Int VG_(clo_verbosity) = 1;
1417Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001418Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001419
nethercotef1e5e152004-09-01 23:58:16 +00001420/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001421 fd is initially stdout, for --help, but gets moved to stderr by default
1422 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001423VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001424Int VG_(clo_log_fd) = 1;
1425Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001426
thughes6233a382004-08-21 11:10:44 +00001427Bool VG_(clo_time_stamp) = False;
1428
sewardj6024b212003-07-13 10:54:33 +00001429Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001430Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001431Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001432Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001433UChar VG_(clo_trace_flags) = 0; // 00000000b
1434UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001435Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001436Bool VG_(clo_trace_syscalls) = False;
1437Bool VG_(clo_trace_signals) = False;
1438Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001439Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001440Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001441Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001442Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001443Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001444Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001445Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001446Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001447Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001448Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001449Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001450Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001451Bool VG_(clo_model_pthreads) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001452
jsgf855d93d2003-10-13 22:26:55 +00001453static Bool VG_(clo_wait_for_gdb) = False;
1454
sewardjde4a1d02002-03-22 01:27:54 +00001455
sewardj2c5ffbe2005-03-12 13:32:06 +00001456static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001457{
njn25e49d8e72002-09-23 09:36:25 +00001458 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001459"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001460"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001461" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001462" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001463" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001464" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001465" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001466" -q --quiet run silently; only print error msgs\n"
1467" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001468" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001469" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001470" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001471"\n"
1472" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001473" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001474" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001475" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001476" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001477"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001478" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001479" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1480" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001481" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001482" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1484" --num-callers=<number> show <num> callers in stack traces [4]\n"
1485" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1486" --show-below-main=no|yes continue stack traces below main() [no]\n"
1487" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001488" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001489" --db-attach=no|yes start debugger when errors detected? [no]\n"
1490" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1491" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001492"\n";
njn7cf0bd32002-06-08 13:36:03 +00001493
njn25e49d8e72002-09-23 09:36:25 +00001494 Char* usage2 =
1495"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001496" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001497" --sanity-level=<number> level of sanity checking to do [1]\n"
1498" --single-step=no|yes translate each instr separately? [no]\n"
1499" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001500" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001501" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001502" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1503" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001504" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001505" --trace-syscalls=no|yes show all system calls? [no]\n"
1506" --trace-signals=no|yes show signal handling details? [no]\n"
1507" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001508" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001509" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001510#if 0
1511" --model-pthreads=yes|no model the pthreads library [no]\n"
1512#endif
1513" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001514"\n"
1515" --vex-iropt-verbosity 0 .. 9 [0]\n"
1516" --vex-iropt-level 0 .. 2 [2]\n"
1517" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001518" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1519" --vex-guest-max-insns 1 .. 100 [50]\n"
1520" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1521"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001522" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001523" 1000 0000 show conversion into IR\n"
1524" 0100 0000 show after initial opt\n"
1525" 0010 0000 show after instrumentation\n"
1526" 0001 0000 show after second opt\n"
1527" 0000 1000 show after tree building\n"
1528" 0000 0100 show selecting insns\n"
1529" 0000 0010 show after reg-alloc\n"
1530" 0000 0001 show final assembly\n"
1531"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001532" debugging options for Valgrind tools that report errors\n"
1533" --dump-error=<number> show translation for basic block associated\n"
1534" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001535"\n";
njn3e884182003-04-15 13:03:23 +00001536
1537 Char* usage3 =
1538"\n"
nethercote71980f02004-01-24 18:18:54 +00001539" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001540"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001541" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001542" and licensed under the GNU General Public License, version 2.\n"
1543" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001544"\n"
nethercote137bc552003-11-14 17:47:54 +00001545" Tools are copyright and licensed by their authors. See each\n"
1546" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n";
njn7cf0bd32002-06-08 13:36:03 +00001548
fitzhardinge98abfc72003-12-16 02:05:15 +00001549 VG_(printf)(usage1);
1550 if (VG_(details).name) {
1551 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001552 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001553 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001554 else
1555 VG_(printf)(" (none)\n");
1556 }
nethercote6c999f22004-01-31 22:55:15 +00001557 if (debug_help) {
1558 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559
nethercote6c999f22004-01-31 22:55:15 +00001560 if (VG_(details).name) {
1561 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1562
1563 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001564 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001565 else
1566 VG_(printf)(" (none)\n");
1567 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001568 }
nethercote421281e2003-11-20 16:20:55 +00001569 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001570 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001571}
sewardjde4a1d02002-03-22 01:27:54 +00001572
nethercote71980f02004-01-24 18:18:54 +00001573static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001574 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001575{
nethercote71980f02004-01-24 18:18:54 +00001576 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001577
sewardj8b635a42004-11-22 19:01:47 +00001578 LibVEX_default_VexControl(& VG_(clo_vex_control));
1579
nethercote71980f02004-01-24 18:18:54 +00001580 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001581 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001582
nethercotef6a1d502004-08-09 12:21:57 +00001583 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001584 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001585 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001586
nethercotef6a1d502004-08-09 12:21:57 +00001587 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1588 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001589 *need_help = 1;
1590
nethercotef6a1d502004-08-09 12:21:57 +00001591 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001592 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001593
nethercotef6c99d72004-11-09 14:35:43 +00001594 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001595 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001596
nethercotef6a1d502004-08-09 12:21:57 +00001597 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1598 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001599 }
1600 }
nethercote71980f02004-01-24 18:18:54 +00001601}
1602
nethercote5ee67ca2004-06-22 14:00:09 +00001603static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001604{
nethercotef8548672004-06-21 12:42:35 +00001605 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001606 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001607
nethercotee1730692003-11-20 10:38:07 +00001608 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001609 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001610
sewardj19d81412002-06-03 01:10:40 +00001611 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001612 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001613 config_error("Please use absolute paths in "
1614 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001615
njnc6168192004-11-29 13:54:10 +00001616// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001617#ifdef __x86__
1618 {
sewardjb5f6f512005-03-10 23:59:00 +00001619 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001620 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1621 switch(auxp[0]) {
1622 case AT_SYSINFO:
1623 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1624 break;
1625 }
1626 }
1627 }
1628#endif
sewardjde4a1d02002-03-22 01:27:54 +00001629
nethercotef6a1d502004-08-09 12:21:57 +00001630 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001631
nethercotef6a1d502004-08-09 12:21:57 +00001632 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001633 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001634
thughes3bfd5a02004-07-18 08:05:44 +00001635 /* Look for a colon in the switch name */
1636 while (*colon && *colon != ':' && *colon != '=')
1637 colon++;
nethercote71980f02004-01-24 18:18:54 +00001638
1639 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001640 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001641 if (VG_CLO_STREQN(2, arg, "--") &&
1642 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1643 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1644 {
1645 // prefix matches, convert "--toolname:foo" to "--foo"
1646 if (0)
1647 VG_(printf)("tool-specific arg: %s\n", arg);
1648 arg += toolname_len + 1;
1649 arg[0] = '-';
1650 arg[1] = '-';
1651
1652 } else {
1653 // prefix doesn't match, skip to next arg
1654 continue;
1655 }
1656 }
1657
fitzhardinge98abfc72003-12-16 02:05:15 +00001658 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001659 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001660 continue;
nethercote71980f02004-01-24 18:18:54 +00001661 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001662 continue;
sewardjb5f6f512005-03-10 23:59:00 +00001663 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
1664 continue;
fitzhardinge98abfc72003-12-16 02:05:15 +00001665
nethercote71980f02004-01-24 18:18:54 +00001666 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 continue;
nethercote27fec902004-06-16 21:26:32 +00001668
nethercote71980f02004-01-24 18:18:54 +00001669 else if (VG_CLO_STREQ(arg, "-v") ||
1670 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001671 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001672
nethercote71980f02004-01-24 18:18:54 +00001673 else if (VG_CLO_STREQ(arg, "-q") ||
1674 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001675 VG_(clo_verbosity)--;
1676
nethercote27fec902004-06-16 21:26:32 +00001677 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001678 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1679 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1680 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001681 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001682 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
nethercote27fec902004-06-16 21:26:32 +00001683 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1684 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1685 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001686 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001687 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1688 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1689 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1690 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1691 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001692 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001693 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001694 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001695 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001696 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001697
nethercote27fec902004-06-16 21:26:32 +00001698 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1699 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001700
nethercote27fec902004-06-16 21:26:32 +00001701 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1702 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1703 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001704 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1705 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001706
sewardj8b635a42004-11-22 19:01:47 +00001707 else VG_BNUM_CLO("--vex-iropt-verbosity",
1708 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1709 else VG_BNUM_CLO("--vex-iropt-level",
1710 VG_(clo_vex_control).iropt_level, 0, 2)
1711 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1712 VG_(clo_vex_control).iropt_precise_memory_exns)
1713 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1714 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1715 else VG_BNUM_CLO("--vex-guest-max-insns",
1716 VG_(clo_vex_control).guest_max_insns, 1, 100)
1717 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1718 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1719
nethercotef8548672004-06-21 12:42:35 +00001720 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001721 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001722 VG_(clo_log_to) = VgLogTo_Fd;
1723 VG_(clo_log_name) = NULL;
1724 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1725 }
1726 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1727 VG_(clo_log_to) = VgLogTo_Fd;
1728 VG_(clo_log_name) = NULL;
1729 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001730 }
1731
nethercotef8548672004-06-21 12:42:35 +00001732 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001733 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001734 VG_(clo_log_to) = VgLogTo_File;
1735 VG_(clo_log_name) = &arg[10];
1736 }
1737 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1738 VG_(clo_log_to) = VgLogTo_File;
1739 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +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 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001747 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001748 VG_(clo_log_to) = VgLogTo_Socket;
1749 VG_(clo_log_name) = &arg[12];
1750 }
1751 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1752 VG_(clo_log_to) = VgLogTo_Socket;
1753 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001754 }
1755
nethercote71980f02004-01-24 18:18:54 +00001756 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001757 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001758 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001759 VG_(message)(Vg_UserMsg,
1760 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001761 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001762 }
nethercote71980f02004-01-24 18:18:54 +00001763 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001764 VG_(clo_n_suppressions)++;
1765 }
sewardjde4a1d02002-03-22 01:27:54 +00001766
sewardjfa8ec112005-01-19 11:55:34 +00001767 /* "stuvwxyz" --> stuvwxyz (binary) */
1768 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1769 Int j;
1770 char* opt = & arg[14];
1771
1772 if (8 != VG_(strlen)(opt)) {
1773 VG_(message)(Vg_UserMsg,
1774 "--trace-flags argument must have 8 digits");
1775 VG_(bad_option)(arg);
1776 }
1777 for (j = 0; j < 8; j++) {
1778 if ('0' == opt[j]) { /* do nothing */ }
1779 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1780 else {
1781 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1782 "contain 0s and 1s");
1783 VG_(bad_option)(arg);
1784 }
1785 }
1786 }
1787
1788 /* "stuvwxyz" --> stuvwxyz (binary) */
1789 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001790 Int j;
nethercote71980f02004-01-24 18:18:54 +00001791 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001792
sewardj2a99cf62004-11-24 10:44:19 +00001793 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001794 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001795 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001796 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001797 }
sewardj8b635a42004-11-22 19:01:47 +00001798 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001799 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001800 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001801 else {
sewardjfa8ec112005-01-19 11:55:34 +00001802 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001803 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001804 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001805 }
1806 }
1807 }
sewardjde4a1d02002-03-22 01:27:54 +00001808
sewardjc771b292004-11-30 18:55:21 +00001809 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1810
sewardjd153fae2005-01-10 17:24:47 +00001811 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1812 VG_(clo_gen_suppressions) = 0;
1813 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1814 VG_(clo_gen_suppressions) = 1;
1815 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1816 VG_(clo_gen_suppressions) = 2;
1817
nethercote71980f02004-01-24 18:18:54 +00001818 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001819 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001820 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001821 }
sewardjde4a1d02002-03-22 01:27:54 +00001822 }
1823
sewardj998d40d2004-12-06 14:24:52 +00001824 /* Make VEX control parameters sane */
1825
1826 if (VG_(clo_vex_control).guest_chase_thresh
1827 >= VG_(clo_vex_control).guest_max_insns)
1828 VG_(clo_vex_control).guest_chase_thresh
1829 = VG_(clo_vex_control).guest_max_insns - 1;
1830
1831 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1832 VG_(clo_vex_control).guest_chase_thresh = 0;
1833
1834 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001835
njnf9ebf672003-05-12 21:41:30 +00001836 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001837 VG_(clo_verbosity) = 0;
1838
nethercote04d0fbc2004-01-26 16:48:06 +00001839 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001840 VG_(message)(Vg_UserMsg, "");
1841 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001842 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001843 VG_(message)(Vg_UserMsg,
1844 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001845 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001846 }
1847
nethercotef8548672004-06-21 12:42:35 +00001848 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001849 should be connected to whatever sink has been selected, and we
1850 indiscriminately chuck stuff into it without worrying what the
1851 nature of it is. Oh the wonder of Unix streams. */
1852
nethercotee1730692003-11-20 10:38:07 +00001853 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001854 the terminal any problems to do with processing command line
1855 opts. */
nethercotef8548672004-06-21 12:42:35 +00001856 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001857 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001858
1859 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001860
sewardj4cf05692002-10-27 20:28:29 +00001861 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001862 vg_assert(VG_(clo_log_name) == NULL);
1863 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001864 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001865
sewardj4cf05692002-10-27 20:28:29 +00001866 case VgLogTo_File: {
1867 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001868 Int seq = 0;
1869 Int pid = VG_(getpid)();
1870
nethercotef8548672004-06-21 12:42:35 +00001871 vg_assert(VG_(clo_log_name) != NULL);
1872 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001873
nethercote71980f02004-01-24 18:18:54 +00001874 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001875 if (seq == 0)
1876 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001877 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001878 else
1879 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001880 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001881 seq++;
1882
nethercotef8548672004-06-21 12:42:35 +00001883 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001884 = VG_(open)(logfilename,
1885 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1886 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001887 if (eventually_log_fd >= 0) {
1888 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001889 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001890 } else {
nethercotef8548672004-06-21 12:42:35 +00001891 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001892 VG_(message)(Vg_UserMsg,
1893 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001894 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001895 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001896 "--log-file=<file> (didn't work out for some reason.)");
1897 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001898 }
1899 }
1900 }
sewardj603d4102005-01-11 14:01:02 +00001901 break; /* switch (VG_(clo_log_to)) */
1902 }
1903
1904 case VgLogTo_FileExactly: {
1905 Char logfilename[1000];
1906
1907 vg_assert(VG_(clo_log_name) != NULL);
1908 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1909 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1910
1911 eventually_log_fd
1912 = VG_(open)(logfilename,
1913 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1914 VKI_S_IRUSR|VKI_S_IWUSR);
1915 if (eventually_log_fd >= 0) {
1916 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1917 }
1918 else if (eventually_log_fd != -VKI_EEXIST) {
1919 VG_(message)(Vg_UserMsg,
1920 "Can't create/open log file `%s'; giving up!",
1921 VG_(clo_log_name));
1922 VG_(bad_option)(
1923 "--log-file-exactly=<file> (didn't work out for some reason.)");
1924 /*NOTREACHED*/
1925 }
1926 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001927 }
1928
1929 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001930 vg_assert(VG_(clo_log_name) != NULL);
1931 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1932 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1933 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001935 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001937 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001938 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001939 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001940 }
nethercotef8548672004-06-21 12:42:35 +00001941 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001942 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001943 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001944 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001945 VG_(message)(Vg_UserMsg,
1946 "Log messages will sent to stderr instead." );
1947 VG_(message)(Vg_UserMsg,
1948 "" );
1949 /* We don't change anything here. */
1950 } else {
nethercotef8548672004-06-21 12:42:35 +00001951 vg_assert(eventually_log_fd > 0);
1952 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001953 VG_(logging_to_filedes) = False;
1954 }
sewardj73cf3bc2002-11-03 03:20:15 +00001955 break;
1956 }
1957
sewardj4cf05692002-10-27 20:28:29 +00001958 }
1959
nethercotef8548672004-06-21 12:42:35 +00001960 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001961 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001962 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001963 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1964 else {
nethercotef8548672004-06-21 12:42:35 +00001965 VG_(clo_log_fd) = eventually_log_fd;
1966 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001967 }
1968
sewardj4cf05692002-10-27 20:28:29 +00001969 /* Ok, the logging sink is running now. Print a suitable preamble.
1970 If logging to file or a socket, write details of parent PID and
1971 command line args, to help people trying to interpret the
1972 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001973
sewardj83adf412002-05-01 01:25:45 +00001974 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001975 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001976 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001977 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001978 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001979 NULL == VG_(details).version
1980 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001981 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001982 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001983
njnd04b7c62002-10-03 14:05:52 +00001984 /* Core details */
1985 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001986 "Using LibVEX rev %s, a library for dynamic binary translation.",
1987 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001988 VG_(message)(Vg_UserMsg,
1989 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1990 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001991 "Using valgrind-%s, a dynamic binary instrumentation framework.",
sewardj5a1feda2004-12-17 19:18:02 +00001992 /*VERSION*/ "SVN >= 3207");
sewardjde4a1d02002-03-22 01:27:54 +00001993 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001994 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001995 }
1996
nethercotec1e395d2003-11-10 13:26:49 +00001997 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001998 VG_(message)(Vg_UserMsg, "");
1999 VG_(message)(Vg_UserMsg,
2000 "My PID = %d, parent PID = %d. Prog and args are:",
2001 VG_(getpid)(), VG_(getppid)() );
2002 for (i = 0; i < VG_(client_argc); i++)
2003 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2004 }
2005
sewardjde4a1d02002-03-22 01:27:54 +00002006 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002007 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002008 if (VG_(clo_log_to) != VgLogTo_Fd)
2009 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002010 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002011 VG_(message)(Vg_UserMsg, "Command line");
2012 for (i = 0; i < VG_(client_argc); i++)
2013 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2014
sewardjde4a1d02002-03-22 01:27:54 +00002015 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002016 for (i = 1; i < vg_argc; i++) {
2017 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002018 }
nethercotea70f7352004-04-18 12:08:46 +00002019
2020 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2021 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2022 if (fd < 0) {
2023 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2024 } else {
2025 #define BUF_LEN 256
2026 Char version_buf[BUF_LEN];
2027 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2028 vg_assert(n <= 256);
2029 if (n > 0) {
2030 version_buf[n-1] = '\0';
2031 VG_(message)(Vg_UserMsg, " %s", version_buf);
2032 } else {
2033 VG_(message)(Vg_UserMsg, " (empty?)");
2034 }
2035 VG_(close)(fd);
2036 #undef BUF_LEN
2037 }
sewardjde4a1d02002-03-22 01:27:54 +00002038 }
2039
fitzhardinge98abfc72003-12-16 02:05:15 +00002040 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002041 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002042 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002043 needs one, load the default */
2044 static const Char default_supp[] = "default.supp";
2045 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2046 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2047 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2048 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2049 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002050 }
sewardj4cf05692002-10-27 20:28:29 +00002051
sewardjd153fae2005-01-10 17:24:47 +00002052 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002053 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002054 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002055 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002056 VG_(message)(Vg_UserMsg,
2057 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002058 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002059 }
sewardjde4a1d02002-03-22 01:27:54 +00002060}
2061
nethercotef6a1d502004-08-09 12:21:57 +00002062// Build the string for VALGRINDCLO.
2063Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2064{
2065 /* If we're tracing the children, then we need to start it
2066 with our starter+arguments, which are copied into VALGRINDCLO,
2067 except the --exec= option is changed if present.
2068 */
2069 Int i;
2070 Char *exec;
2071 Char *cp;
2072 Char *optvar;
2073 Int optlen, execlen;
2074
2075 // All these allocated blocks are not free - because we're either
2076 // going to exec, or panic when we fail.
2077
2078 // Create --exec= option: "--exec=<exename>"
2079 exec = VG_(arena_malloc)(VG_AR_CORE,
2080 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2081 vg_assert(NULL != exec);
2082 VG_(sprintf)(exec, "--exec=%s", exename);
2083
2084 // Allocate space for optvar (may overestimate by counting --exec twice,
2085 // no matter)
2086 optlen = 1;
2087 for (i = 0; i < vg_argc; i++)
2088 optlen += VG_(strlen)(vg_argv[i]) + 1;
2089 optlen += VG_(strlen)(exec)+1;
2090 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2091
2092 // Copy all valgrind args except the old --exec (if present)
2093 // VG_CLO_SEP is the separator.
2094 cp = optvar;
2095 for (i = 1; i < vg_argc; i++) {
2096 Char *arg = vg_argv[i];
2097
2098 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2099 // don't copy existing --exec= arg
2100 } else if (VG_(strcmp)(arg, "--") == 0) {
2101 // stop at "--"
2102 break;
2103 } else {
2104 // copy non "--exec" arg
2105 Int len = VG_(strlen)(arg);
2106 VG_(memcpy)(cp, arg, len);
2107 cp += len;
2108 *cp++ = VG_CLO_SEP;
2109 }
2110 }
2111 // Add the new --exec= option
2112 execlen = VG_(strlen)(exec);
2113 VG_(memcpy)(cp, exec, execlen);
2114 cp += execlen;
2115 *cp++ = VG_CLO_SEP;
2116
2117 *cp = '\0';
2118
2119 return optvar;
2120}
2121
2122// Build "/proc/self/fd/<execfd>".
2123Char* VG_(build_child_exename)( void )
2124{
2125 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2126 vg_assert(NULL != exename);
2127 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2128 return exename;
2129}
2130
sewardjde4a1d02002-03-22 01:27:54 +00002131
nethercote71980f02004-01-24 18:18:54 +00002132/*====================================================================*/
2133/*=== File descriptor setup ===*/
2134/*====================================================================*/
2135
2136static void setup_file_descriptors(void)
2137{
2138 struct vki_rlimit rl;
2139
2140 /* Get the current file descriptor limits. */
2141 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2142 rl.rlim_cur = 1024;
2143 rl.rlim_max = 1024;
2144 }
2145
2146 /* Work out where to move the soft limit to. */
2147 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2148 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2149 } else {
2150 rl.rlim_cur = rl.rlim_max;
2151 }
2152
2153 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002154 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2155 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002156
2157 /* Update the soft limit. */
2158 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2159
nethercotef6a1d502004-08-09 12:21:57 +00002160 if (vgexecfd != -1)
2161 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002162 if (VG_(clexecfd) != -1)
2163 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2164}
2165
nethercote71980f02004-01-24 18:18:54 +00002166/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002167/*=== Initialise program data/text, etc. ===*/
2168/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002169
sewardjb5f6f512005-03-10 23:59:00 +00002170static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2171 UInt dev, UInt ino, ULong foffset,
2172 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002173{
nethercote71980f02004-01-24 18:18:54 +00002174 /* Only record valgrind mappings for now, without loading any
2175 symbols. This is so we know where the free space is before we
2176 start allocating more memory (note: heap is OK, it's just mmap
2177 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002178 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2179 if (0)
2180 VG_(printf)("init1: %p-%p prot %s\n",
2181 start, start+size, VG_(prot_str)(prot));
2182 VG_(map_file_segment)(start, size, prot,
2183 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2184 dev, ino, foffset, filename);
2185 /* update VG_(valgrind_last) if it looks wrong */
2186 if (start+size > VG_(valgrind_last))
2187 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002188 }
sewardjde4a1d02002-03-22 01:27:54 +00002189}
2190
nethercote71980f02004-01-24 18:18:54 +00002191// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002192Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002193
sewardjb5f6f512005-03-10 23:59:00 +00002194/*
2195 This second pass adds in client mappings, and loads symbol tables
2196 for all interesting mappings. The trouble is that things can
2197 change as we go, because we're calling the Tool to track memory as
2198 we find it.
2199
2200 So for Valgrind mappings, we don't replace any mappings which
2201 aren't still identical (which will include the .so mappings, so we
2202 will load their symtabs)>
2203 */
2204static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2205 UInt dev, UInt ino, ULong foffset,
2206 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002207{
nethercote71980f02004-01-24 18:18:54 +00002208 UInt flags;
2209 Bool is_stack_segment;
2210 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002211
nethercote71980f02004-01-24 18:18:54 +00002212 is_stack_segment
2213 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002214
sewardjb5f6f512005-03-10 23:59:00 +00002215 if (0)
2216 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2217 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002218
nethercote71980f02004-01-24 18:18:54 +00002219 if (is_stack_segment)
2220 flags = SF_STACK | SF_GROWDOWN;
2221 else
2222 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 if (filename != NULL)
2225 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002226
sewardjb5f6f512005-03-10 23:59:00 +00002227#if 0
2228 // This needs to be fixed properly. jrs 20050307
2229 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2230 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
sewardjb5f6f512005-03-10 23:59:00 +00002232 /* We have to be a bit careful about inserting new mappings into
2233 the Valgrind part of the address space. We're actively
2234 changing things as we parse these mappings, particularly in
2235 shadow memory, and so we don't want to overwrite those
2236 changes. Therefore, we only insert/update a mapping if it is
2237 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002238
sewardjb5f6f512005-03-10 23:59:00 +00002239 NOTE: we're only talking about the Segment list mapping
2240 metadata; this doesn't actually mmap anything more. */
2241 if (filename || (s && s->addr == start && s->len == size)) {
2242 flags |= SF_VALGRIND;
2243 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2244 } else {
2245 /* assert range is already mapped */
2246 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2247 }
2248 } else
2249#endif
2250 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2251
2252 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2253 VG_TRACK( new_mem_startup, start, size,
2254 !!(prot & VKI_PROT_READ),
2255 !!(prot & VKI_PROT_WRITE),
2256 !!(prot & VKI_PROT_EXEC));
2257 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002258
nethercote71980f02004-01-24 18:18:54 +00002259 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002260 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002261 vg_assert(0 != r_esp);
2262 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002263 if (0) {
2264 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002265 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002266 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2267 r_esp, start+size);
2268 }
nethercote71980f02004-01-24 18:18:54 +00002269 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002270 // what's this for?
2271 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002272 }
sewardjde4a1d02002-03-22 01:27:54 +00002273}
2274
2275
nethercote71980f02004-01-24 18:18:54 +00002276/*====================================================================*/
2277/*=== Sanity check machinery (permanently engaged) ===*/
2278/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002279
2280/* A fast sanity check -- suitable for calling circa once per
2281 millisecond. */
2282
nethercote885dd912004-08-03 23:14:00 +00002283void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002284{
sewardjb5f6f512005-03-10 23:59:00 +00002285 ThreadId tid;
2286
njn37cea302002-09-30 11:24:00 +00002287 VGP_PUSHCC(VgpCoreCheapSanity);
2288
nethercote27fec902004-06-16 21:26:32 +00002289 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002290
2291 /* --- First do all the tests that we can do quickly. ---*/
2292
nethercote297effd2004-08-02 15:07:57 +00002293 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002294
njn25e49d8e72002-09-23 09:36:25 +00002295 /* Check stuff pertaining to the memory check system. */
2296
2297 /* Check that nobody has spuriously claimed that the first or
2298 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002299 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002300 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002301 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002302 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002303 }
njn25e49d8e72002-09-23 09:36:25 +00002304
2305 /* --- Now some more expensive checks. ---*/
2306
2307 /* Once every 25 times, check some more expensive stuff. */
2308 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002309 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002310 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002311
njn37cea302002-09-30 11:24:00 +00002312 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002313 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002314
2315# if 0
2316 { void zzzmemscan(void); zzzmemscan(); }
2317# endif
2318
nethercote297effd2004-08-02 15:07:57 +00002319 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002320 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002321
2322 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002323 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002324 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002325 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002326 }
sewardjb5f6f512005-03-10 23:59:00 +00002327
2328 /* Check that Segments and /proc/self/maps match up */
2329 //vg_assert(VG_(sanity_check_memory)());
2330
2331 /* Look for stack overruns. Visit all threads. */
2332 for(tid = 1; tid < VG_N_THREADS; tid++) {
2333 Int remains;
2334
2335 if (VG_(threads)[tid].status == VgTs_Empty ||
2336 VG_(threads)[tid].status == VgTs_Zombie)
2337 continue;
2338
2339 remains = VGA_(stack_unused)(tid);
2340 if (remains < VKI_PAGE_SIZE)
2341 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2342 tid, remains);
2343 }
2344
njn25e49d8e72002-09-23 09:36:25 +00002345 /*
nethercote297effd2004-08-02 15:07:57 +00002346 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002347 */
njn37cea302002-09-30 11:24:00 +00002348 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002349 }
2350
nethercote27fec902004-06-16 21:26:32 +00002351 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002352 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002353 /* Check sanity of the low-level memory manager. Note that bugs
2354 in the client's code can cause this to fail, so we don't do
2355 this check unless specially asked for. And because it's
2356 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002357 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002358 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002359 }
njn37cea302002-09-30 11:24:00 +00002360 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002361}
nethercote71980f02004-01-24 18:18:54 +00002362
2363
2364/*====================================================================*/
2365/*=== main() ===*/
2366/*====================================================================*/
2367
nethercotec314eba2004-07-15 12:59:41 +00002368/*
2369 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002370 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002371 loads the client executable (and the dynamic linker, if necessary)
2372 into the client part, and calls into Valgrind proper.
2373
2374 The code is careful not to allow spurious mappings to appear in the
2375 wrong parts of the address space. In particular, to make sure
2376 dlopen puts things in the right place, it will pad out the forbidden
2377 chunks of address space so that dlopen is forced to put things where
2378 we want them.
2379
2380 The memory map it creates is:
2381
2382 CLIENT_BASE +-------------------------+
2383 | client address space |
2384 : :
2385 : :
2386 | client stack |
2387 client_end +-------------------------+
2388 | redzone |
2389 shadow_base +-------------------------+
2390 | |
nethercote996901a2004-08-03 13:29:09 +00002391 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002392 | (may be 0 sized) |
2393 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002394 valgrind_base +-------------------------+
2395 | kickstart executable |
2396 | valgrind heap vvvvvvvvv| (barely used)
2397 - -
2398 | valgrind .so files |
2399 | and mappings |
2400 - -
2401 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002402 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002403 : kernel :
2404
2405 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2406 VG_(mmap)(), we need to build the segment skip-list, so we know where
2407 we can put things. However, building that structure requires
2408 allocating memory. So we need to a bootstrapping process. It's done
2409 by making VG_(arena_malloc)() have a special static superblock that's
2410 used for the first 1MB's worth of allocations. This is enough to
2411 build the segment skip-list.
2412*/
2413
nethercote31779c72004-07-30 21:50:15 +00002414static int prmap(char *start, char *end, const char *perm, off_t off,
2415 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002416 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2417 start, end, perm, maj, min, ino);
2418 return True;
2419}
2420
sewardjb5f6f512005-03-10 23:59:00 +00002421int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002422{
2423 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002424 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002425 const char *exec = NULL;
2426 char *preload; /* tool-specific LD_PRELOAD .so */
2427 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002428 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002429 struct exeinfo info;
2430 ToolInfo *toolinfo = NULL;
2431 void *tool_dlhandle;
2432 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002433 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002434 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002435 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002436 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002437
2438 //============================================================
2439 // Nb: startup is complex. Prerequisites are shown at every step.
2440 //
2441 // *** Be very careful when messing with the order ***
2442 //============================================================
2443
nethercotef4928da2004-06-15 10:54:40 +00002444 //============================================================
2445 // Command line argument handling order:
2446 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002447 // (including the tool-specific usage)
2448 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002449 // * Then, if client is missing, abort with error msg
2450 // * Then, if any cmdline args are bad, abort with error msg
2451 //============================================================
2452
fitzhardingeb50068f2004-02-24 23:42:55 +00002453 // Get the current process datasize rlimit, and set it to zero.
2454 // This prevents any internal uses of brk() from having any effect.
2455 // We remember the old value so we can restore it on exec, so that
2456 // child processes will have a reasonable brk value.
2457 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2458 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2459 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002460
2461 // Get the current process stack rlimit.
2462 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2463
nethercote71980f02004-01-24 18:18:54 +00002464 //--------------------------------------------------------------
2465 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002466 // p: none
nethercote71980f02004-01-24 18:18:54 +00002467 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002468 {
2469 void* init_sp = argv - 1;
2470 padfile = scan_auxv(init_sp);
2471 }
nethercote71980f02004-01-24 18:18:54 +00002472 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002473 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002474 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002475 }
2476
2477 //--------------------------------------------------------------
2478 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002479 // p: none
nethercote71980f02004-01-24 18:18:54 +00002480 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002481 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002482 if (cp != NULL)
2483 VG_(libdir) = cp;
2484 }
2485
2486 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002487 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2488 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002489 // p: none
nethercote71980f02004-01-24 18:18:54 +00002490 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002491 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002492 pre_process_cmd_line_options(&need_help, &tool, &exec);
2493
2494 //==============================================================
2495 // Nb: once a tool is specified, the tool.so must be loaded even if
2496 // they specified --help or didn't specify a client program.
2497 //==============================================================
2498
2499 //--------------------------------------------------------------
2500 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002501 // p: set-libdir [for VG_(libdir)]
2502 // p: pre_process_cmd_line_options() [for 'tool']
2503 //--------------------------------------------------------------
2504 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2505
2506 //==============================================================
2507 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002508 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002509 //==============================================================
2510
2511 //--------------------------------------------------------------
2512 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002513 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002514 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002515 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002516
2517 //--------------------------------------------------------------
2518 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002519 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2520 // p: layout_remaining_space [so there's space]
2521 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002522 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002523
2524 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002525 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002526 // p: layout_remaining_space() [everything must be mapped in before now]
2527 // p: load_client() [ditto]
2528 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002529 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2530 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002531
2532 //--------------------------------------------------------------
2533 // Set up client's environment
2534 // p: set-libdir [for VG_(libdir)]
2535 // p: load_tool() [for 'preload']
2536 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002537 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002538
2539 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002540 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002541 // p: load_client() [for 'info']
2542 // p: fix_environment() [for 'env']
2543 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002544 {
2545 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002546
nethercote4ad74312004-10-26 09:59:49 +00002547 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2548 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002549 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002550 }
nethercote71980f02004-01-24 18:18:54 +00002551
2552 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002553 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002554 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002555 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002556
2557 //==============================================================
2558 // Finished setting up operating environment. Now initialise
2559 // Valgrind. (This is where the old VG_(main)() started.)
2560 //==============================================================
2561
2562 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002563 // setup file descriptors
2564 // p: n/a
2565 //--------------------------------------------------------------
2566 setup_file_descriptors();
2567
2568 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002569 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002570 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002571 //--------------------------------------------------------------
2572 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2573
2574 //==============================================================
2575 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2576 //==============================================================
2577
2578 //--------------------------------------------------------------
2579 // Init tool: pre_clo_init, process cmd line, post_clo_init
2580 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2581 // p: load_tool() [for 'tool']
2582 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2583 // p: parse_procselfmaps [so VG segments are setup so tool can
2584 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002585 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002586 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002587 VG_(tool_init_dlsym)(tool_dlhandle);
2588 VG_(sanity_check_needs)();
2589
nethercotef4928da2004-06-15 10:54:40 +00002590 // If --tool and --help/--help-debug was given, now give the core+tool
2591 // help message
nethercotef4928da2004-06-15 10:54:40 +00002592 if (need_help) {
2593 usage(/*--help-debug?*/2 == need_help);
2594 }
nethercotec314eba2004-07-15 12:59:41 +00002595 process_cmd_line_options(client_auxv, tool);
2596
njn26f02512004-11-22 18:33:15 +00002597 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002598
2599 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002600 // Determine CPU architecture and subarchitecture
2601 // p: none
2602 //--------------------------------------------------------------
2603 { Bool ok = VGA_(getArchAndSubArch)(
2604 & VG_(vex_arch), & VG_(vex_subarch) );
2605 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002606 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002607 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002608 VG_(printf)(" Supported CPUs are:\n");
2609 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2610 "AMD Athlon or above)\n");
2611 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002612 VG_(exit)(1);
2613 }
2614 if (VG_(clo_verbosity) > 2) {
2615 VG_(message)(Vg_DebugMsg,
2616 "Host CPU: arch = %s, subarch = %s",
2617 LibVEX_ppVexArch( VG_(vex_arch) ),
2618 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2619 }
2620 }
2621
2622 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002623 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002624 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002625 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002626 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002628 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002629 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002630 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002631
sewardja4da2f32005-03-02 14:06:08 +00002632#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002633 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002634 // Protect client trampoline page (which is also sysinfo stuff)
2635 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002636 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002637 {
2638 Segment *seg;
2639 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2640 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002641#endif
nethercotec314eba2004-07-15 12:59:41 +00002642
sewardjb5f6f512005-03-10 23:59:00 +00002643 /* Make sure this segment isn't treated as stack */
2644 seg = VG_(find_segment)(VG_(client_trampoline_code));
2645 if (seg)
2646 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2647 }
2648
nethercotec314eba2004-07-15 12:59:41 +00002649 //==============================================================
2650 // Can use VG_(map)() after segments set up
2651 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002652
2653 //--------------------------------------------------------------
2654 // Allow GDB attach
2655 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2656 //--------------------------------------------------------------
2657 /* Hook to delay things long enough so we can get the pid and
2658 attach GDB in another shell. */
2659 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002660 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2661 /* jrs 20050206: I don't understand why this works on x86. On
2662 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2663 work. */
2664 /* do "jump *$eip" to skip this in gdb (x86) */
2665 //VG_(do_syscall0)(__NR_pause);
2666 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002667 }
2668
nethercote71980f02004-01-24 18:18:54 +00002669 // Search for file descriptors that are inherited from our parent
2670 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2671 //--------------------------------------------------------------
2672 if (VG_(clo_track_fds))
2673 VG_(init_preopened_fds)();
2674
2675 //--------------------------------------------------------------
2676 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002677 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2678 //--------------------------------------------------------------
2679 VG_(scheduler_init)();
2680
2681 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002682 // Initialise the pthread model
2683 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002684 // load_client() [for 'client_eip']
2685 // setup_client_stack() [for 'sp_at_startup']
2686 // setup_scheduler() [for the rest of state 1 stuff]
2687 //--------------------------------------------------------------
2688 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002689
2690 // Tell the tool that we just wrote to the registers.
2691 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2692 sizeof(VexGuestArchState));
2693
2694 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002695 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002696
2697 //--------------------------------------------------------------
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))
2722 VGP_(init_profiling)();
2723
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 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002742 // Verbosity message
2743 // p: end_rdtsc_calibration [so startup message is printed first]
2744 //--------------------------------------------------------------
2745 if (VG_(clo_verbosity) == 1)
2746 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2747 if (VG_(clo_verbosity) > 0)
2748 VG_(message)(Vg_UserMsg, "");
2749
2750 //--------------------------------------------------------------
2751 // Setup pointercheck
2752 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2753 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002754 if (VG_(clo_pointercheck))
2755 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002756
nethercote71980f02004-01-24 18:18:54 +00002757 //--------------------------------------------------------------
2758 // Run!
2759 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002760 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002761
sewardjb5f6f512005-03-10 23:59:00 +00002762 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002763
sewardjb5f6f512005-03-10 23:59:00 +00002764 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002765
sewardjb5f6f512005-03-10 23:59:00 +00002766 abort();
2767}
2768
2769
2770/* Do everything which needs doing when the last thread exits */
2771void VG_(shutdown_actions)(ThreadId tid)
2772{
2773 vg_assert(tid == VG_(master_tid));
2774 vg_assert(VG_(is_running_thread)(tid));
2775
2776 // Wait for all other threads to exit.
2777 VGA_(reap_threads)(tid);
2778
2779 VG_(clo_model_pthreads) = False;
2780
2781 // Clean the client up before the final report
2782 VGA_(final_tidyup)(tid);
2783
2784 // OK, done
2785 VG_(exit_thread)(tid);
2786
2787 /* should be no threads left */
2788 vg_assert(VG_(count_living_threads)() == 0);
2789
2790 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002791 //--------------------------------------------------------------
2792 // Finalisation: cleanup, messages, etc. Order no so important, only
2793 // affects what order the messages come.
2794 //--------------------------------------------------------------
2795 if (VG_(clo_verbosity) > 0)
2796 VG_(message)(Vg_UserMsg, "");
2797
nethercote71980f02004-01-24 18:18:54 +00002798 /* Print out file descriptor summary and stats. */
2799 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002800 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002801
njn95ec8702004-11-22 16:46:13 +00002802 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002803 VG_(show_all_errors)();
2804
sewardjb5f6f512005-03-10 23:59:00 +00002805 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002806
nethercote885dd912004-08-03 23:14:00 +00002807 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002808
2809 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002810 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002811
nethercote71980f02004-01-24 18:18:54 +00002812 if (VG_(clo_profile))
2813 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002814 if (VG_(clo_profile_flags) > 0)
2815 VG_(show_BB_profile)();
2816
sewardj8b635a42004-11-22 19:01:47 +00002817 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002818 if (0)
2819 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002820
nethercote71980f02004-01-24 18:18:54 +00002821}
2822
sewardjde4a1d02002-03-22 01:27:54 +00002823/*--------------------------------------------------------------------*/
2824/*--- end vg_main.c ---*/
2825/*--------------------------------------------------------------------*/