blob: 77ee6bec8e5a1d506cea2f8a3e795ddc409e92ac [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
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
njn9271cbc2005-03-13 05:38:25 +0000188 VG_(print_ExeContext_stats)();
189
nethercote3a42fb82004-08-03 18:08:50 +0000190 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000191 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000192 VG_(message)(Vg_DebugMsg, "");
193 VG_(message)(Vg_DebugMsg,
194 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000195 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000196 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000197 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000198 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000199 }
nethercote71980f02004-01-24 18:18:54 +0000200}
201
202
203/*====================================================================*/
204/*=== Miscellaneous global functions ===*/
205/*====================================================================*/
206
nethercotecf97ffb2004-09-09 13:40:31 +0000207static Int ptrace_setregs(Int pid, ThreadId tid)
208{
sewardj2a99cf62004-11-24 10:44:19 +0000209 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000210}
211
nethercote04d0fbc2004-01-26 16:48:06 +0000212/* Start debugger and get it to attach to this process. Called if the
213 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000214 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000215 meaningfully get the debugger to continue the program, though; to
216 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000217void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000218{
219 Int pid;
220
221 if ((pid = fork()) == 0) {
222 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000223 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000224
225 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000226 Int status;
227 Int res;
228
nethercote71980f02004-01-24 18:18:54 +0000229 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
230 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000231 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000232 kill(pid, SIGSTOP) == 0 &&
233 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000234 Char pidbuf[15];
235 Char file[30];
236 Char buf[100];
237 Char *bufptr;
238 Char *cmdptr;
239
240 VG_(sprintf)(pidbuf, "%d", pid);
241 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
242
243 bufptr = buf;
244 cmdptr = VG_(clo_db_command);
245
246 while (*cmdptr) {
247 switch (*cmdptr) {
248 case '%':
249 switch (*++cmdptr) {
250 case 'f':
251 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
252 bufptr += VG_(strlen)(file);
253 cmdptr++;
254 break;
255 case 'p':
256 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
257 bufptr += VG_(strlen)(pidbuf);
258 cmdptr++;
259 break;
260 default:
261 *bufptr++ = *cmdptr++;
262 break;
263 }
264 break;
265 default:
266 *bufptr++ = *cmdptr++;
267 break;
268 }
269 }
270
271 *bufptr++ = '\0';
272
273 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000274 res = VG_(system)(buf);
275 if (res == 0) {
276 VG_(message)(Vg_UserMsg, "");
277 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000278 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000279 } else {
280 VG_(message)(Vg_UserMsg, "Apparently failed!");
281 VG_(message)(Vg_UserMsg, "");
282 }
283 }
284
nethercote73b526f2004-10-31 18:48:21 +0000285 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000286 VG_(waitpid)(pid, &status, 0);
287 }
288}
289
290
291/* Print some helpful-ish text about unimplemented things, and give
292 up. */
293void VG_(unimplemented) ( Char* msg )
294{
295 VG_(message)(Vg_UserMsg, "");
296 VG_(message)(Vg_UserMsg,
297 "Valgrind detected that your program requires");
298 VG_(message)(Vg_UserMsg,
299 "the following unimplemented functionality:");
300 VG_(message)(Vg_UserMsg, " %s", msg);
301 VG_(message)(Vg_UserMsg,
302 "This may be because the functionality is hard to implement,");
303 VG_(message)(Vg_UserMsg,
304 "or because no reasonable program would behave this way,");
305 VG_(message)(Vg_UserMsg,
306 "or because nobody has yet needed it. In any case, let us know at");
307 VG_(message)(Vg_UserMsg,
308 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
309 VG_(message)(Vg_UserMsg,
310 "");
311 VG_(message)(Vg_UserMsg,
312 "Valgrind has to exit now. Sorry. Bye!");
313 VG_(message)(Vg_UserMsg,
314 "");
315 VG_(pp_sched_status)();
316 VG_(exit)(1);
317}
318
sewardj2a99cf62004-11-24 10:44:19 +0000319/* Get the simulated stack pointer */
320Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000321{
njncf45fd42004-11-24 16:30:22 +0000322 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000323}
324
njnea4b28c2004-11-30 16:04:58 +0000325
nethercote71980f02004-01-24 18:18:54 +0000326/*====================================================================*/
327/*=== Check we were launched by stage 1 ===*/
328/*====================================================================*/
329
330/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000331static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000332{
nethercoteebf1d862004-11-01 18:22:05 +0000333 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000334 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000335
336 for (; auxv->a_type != AT_NULL; auxv++)
337 switch(auxv->a_type) {
338 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000339 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000340 found |= 1;
341 break;
342
343 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000344 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000345 found |= 2;
346 break;
nethercote7f390022004-10-25 17:18:24 +0000347
348 case AT_PHDR:
349 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
350 break;
nethercote71980f02004-01-24 18:18:54 +0000351 }
352
nethercote361a14e2004-07-26 11:11:56 +0000353 if ( found != (1|2) ) {
354 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000355 exit(127);
356 }
nethercote31779c72004-07-30 21:50:15 +0000357 vg_assert(padfile >= 0);
358 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000359}
360
361
362/*====================================================================*/
363/*=== Address space determination ===*/
364/*====================================================================*/
365
nethercote7f390022004-10-25 17:18:24 +0000366extern char _start[];
367
nethercote31779c72004-07-30 21:50:15 +0000368static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000369{
nethercotea3c3cf22004-11-01 18:38:00 +0000370 Int ires;
371 void* vres;
372 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000373
nethercote7f390022004-10-25 17:18:24 +0000374 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
375 // this is a workable approximation
376 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000377 VG_(valgrind_base) = PGROUNDDN(&_start);
378 }
379
nethercote820bd8c2004-09-07 23:04:49 +0000380 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000381
nethercote31779c72004-07-30 21:50:15 +0000382 // This gives the client the largest possible address space while
383 // taking into account the tool's shadow needs.
384 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000385 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000386 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000387 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000388 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000389 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000390 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000391
nethercote31779c72004-07-30 21:50:15 +0000392 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000393 VG_(shadow_end) = VG_(valgrind_base);
394 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000395
nethercotee2097312004-06-27 12:29:56 +0000396#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
397
nethercote71980f02004-01-24 18:18:54 +0000398 if (0)
nethercotee2097312004-06-27 12:29:56 +0000399 VG_(printf)(
400 "client_base %8x (%dMB)\n"
401 "client_mapbase %8x (%dMB)\n"
402 "client_end %8x (%dMB)\n"
403 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000404 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000405 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000406 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000407 VG_(client_base), SEGSIZE(client_base, client_mapbase),
408 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
409 VG_(client_end), SEGSIZE(client_end, shadow_base),
410 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000411 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000412 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
413 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000414 );
415
416#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000417
418 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000419 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000420 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000421 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000422
423 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000424 ires = munmap((void*)VG_(client_base), client_size);
425 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000426
427 // Map shadow memory.
428 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000429 if (shadow_size != 0) {
430 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000431 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000432 if ((void*)-1 == vres) {
433 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000434 "valgrind: Could not allocate address space (%p bytes)\n"
435 "valgrind: for shadow memory\n"
436 "valgrind: Possible causes:\n"
437 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
438 "valgrind: needs at least 1.5GB swap space.\n"
439 "valgrind: - Or, your virtual memory size may be limited (check\n"
440 "valgrind: with 'ulimit -v').\n"
441 "valgrind: - Or, your system may use a kernel that provides only a\n"
442 "valgrind: too-small (eg. 2GB) user address space.\n"
443 , (void*)shadow_size
444 );
nethercoted4722622004-08-30 19:36:42 +0000445 exit(1);
446 }
nethercotee567e702004-07-10 17:49:17 +0000447 }
nethercote71980f02004-01-24 18:18:54 +0000448}
449
450/*====================================================================*/
451/*=== Command line setup ===*/
452/*====================================================================*/
453
454/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
455static char* get_file_clo(char* dir)
456{
457# define FLEN 512
458 Int fd, n;
459 struct stat s1;
460 char* f_clo = NULL;
461 char filename[FLEN];
462
463 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
464 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
465 if ( fd > 0 ) {
466 if ( 0 == fstat(fd, &s1) ) {
467 f_clo = malloc(s1.st_size+1);
468 vg_assert(f_clo);
469 n = read(fd, f_clo, s1.st_size);
470 if (n == -1) n = 0;
471 f_clo[n] = '\0';
472 }
473 close(fd);
474 }
475 return f_clo;
476# undef FLEN
477}
478
nethercotee2097312004-06-27 12:29:56 +0000479#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
480
nethercote71980f02004-01-24 18:18:54 +0000481static Int count_args(char* s)
482{
483 Int n = 0;
484 if (s) {
485 char* cp = s;
486 while (True) {
487 // We have alternating sequences: blanks, non-blanks, blanks...
488 // count the non-blanks sequences.
489 while ( ISSPACE(*cp) ) cp++;
490 if ( !*cp ) break;
491 n++;
492 while ( !ISSPACE(*cp) && *cp ) cp++;
493 }
494 }
495 return n;
496}
497
498/* add args out of environment, skipping multiple spaces and -- args */
499static char** copy_args( char* s, char** to )
500{
501 if (s) {
502 char* cp = s;
503 while (True) {
504 // We have alternating sequences: blanks, non-blanks, blanks...
505 // copy the non-blanks sequences, and add terminating '\0'
506 while ( ISSPACE(*cp) ) cp++;
507 if ( !*cp ) break;
508 *to++ = cp;
509 while ( !ISSPACE(*cp) && *cp ) cp++;
510 if ( *cp ) *cp++ = '\0'; // terminate if necessary
511 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
512 }
513 }
514 return to;
515}
516
nethercotee2097312004-06-27 12:29:56 +0000517#undef ISSPACE
518
nethercote71980f02004-01-24 18:18:54 +0000519// Augment command line with arguments from environment and .valgrindrc
520// files.
521static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
522{
nethercotef6a1d502004-08-09 12:21:57 +0000523 int vg_argc0 = *vg_argc_inout;
524 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000525
526 char* env_clo = getenv(VALGRINDOPTS);
527 char* f1_clo = get_file_clo( getenv("HOME") );
528 char* f2_clo = get_file_clo(".");
529
530 /* copy any extra args from file or environment, if present */
531 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
532 /* ' ' separated extra options */
533 char **from;
534 char **to;
thughescaca0022004-09-13 10:20:34 +0000535 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
536
537 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
538
nethercote71980f02004-01-24 18:18:54 +0000539 env_arg_count = count_args(env_clo);
540 f1_arg_count = count_args(f1_clo);
541 f2_arg_count = count_args(f2_clo);
542
543 if (0)
544 printf("extra-argc=%d %d %d\n",
545 env_arg_count, f1_arg_count, f2_arg_count);
546
547 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000548 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000549 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000550 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000551 vg_assert(vg_argv0);
552 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000553
554 /* copy argv[0] */
555 *to++ = *from++;
556
557 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
558 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
559 * to override less local ones. */
560 to = copy_args(f1_clo, to);
561 to = copy_args(env_clo, to);
562 to = copy_args(f2_clo, to);
563
564 /* copy original arguments, stopping at command or -- */
565 while (*from) {
566 if (**from != '-')
567 break;
568 if (VG_STREQ(*from, "--")) {
569 from++; /* skip -- */
570 break;
571 }
572 *to++ = *from++;
573 }
574
575 /* add -- */
576 *to++ = "--";
577
nethercotef6a1d502004-08-09 12:21:57 +0000578 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000579
580 /* copy rest of original command line, then NULL */
581 while (*from) *to++ = *from++;
582 *to = NULL;
583 }
584
nethercotef6a1d502004-08-09 12:21:57 +0000585 *vg_argc_inout = vg_argc0;
586 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000587}
588
nethercotef6a1d502004-08-09 12:21:57 +0000589#define VG_CLO_SEP '\01'
590
nethercote71980f02004-01-24 18:18:54 +0000591static void get_command_line( int argc, char** argv,
592 Int* vg_argc_out, Char*** vg_argv_out,
593 char*** cl_argv_out )
594{
nethercotef6a1d502004-08-09 12:21:57 +0000595 int vg_argc0;
596 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000597 char** cl_argv;
598 char* env_clo = getenv(VALGRINDCLO);
599
600 if (env_clo != NULL && *env_clo != '\0') {
601 char *cp;
602 char **cpp;
603
nethercotef6a1d502004-08-09 12:21:57 +0000604 /* OK, VALGRINDCLO is set, which means we must be a child of another
605 Valgrind process using --trace-children, so we're getting all our
606 arguments from VALGRINDCLO, and the entire command line belongs to
607 the client (including argv[0]) */
608 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000609 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000610 if (*cp == VG_CLO_SEP)
611 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000612
nethercotef6a1d502004-08-09 12:21:57 +0000613 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
614 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000615
nethercotef6a1d502004-08-09 12:21:57 +0000616 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000617
618 *cpp++ = "valgrind"; /* nominal argv[0] */
619 *cpp++ = env_clo;
620
nethercotef6a1d502004-08-09 12:21:57 +0000621 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000622 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000623 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000624 *cp++ = '\0'; /* chop it up in place */
625 *cpp++ = cp;
626 }
627 }
628 *cpp = NULL;
629 cl_argv = argv;
630
631 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000632 Bool noaugment = False;
633
nethercote71980f02004-01-24 18:18:54 +0000634 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000635 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000636
nethercotef6a1d502004-08-09 12:21:57 +0000637 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000638 Char* arg = argv[vg_argc0];
639 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000640 break;
sewardjb5f6f512005-03-10 23:59:00 +0000641 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000642 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000643 break;
644 }
sewardjb5f6f512005-03-10 23:59:00 +0000645 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000646 }
nethercotef6a1d502004-08-09 12:21:57 +0000647 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000648
649 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000650 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000651 those extra args will already be present in VALGRINDCLO.
652 (We also don't do it when --command-line-only=yes.) */
653 if (!noaugment)
654 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000655 }
656
657 if (0) {
658 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000659 for (i = 0; i < vg_argc0; i++)
660 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000661 }
662
nethercotef6a1d502004-08-09 12:21:57 +0000663 *vg_argc_out = vg_argc0;
664 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000665 *cl_argv_out = cl_argv;
666}
667
668
669/*====================================================================*/
670/*=== Environment and stack setup ===*/
671/*====================================================================*/
672
673/* Scan a colon-separated list, and call a function on each element.
674 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000675 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000676 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000677
678 This routine will return True if (*func) returns True and False if
679 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000680*/
thughes4ad52d02004-06-27 17:37:21 +0000681static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000682{
683 char *cp, *entry;
684 int end;
685
686 if (colsep == NULL ||
687 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000688 return False;
nethercote71980f02004-01-24 18:18:54 +0000689
690 entry = cp = colsep;
691
692 do {
693 end = (*cp == '\0');
694
695 if (*cp == ':' || *cp == '\0') {
696 char save = *cp;
697
698 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000699 if ((*func)(entry)) {
700 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000701 return True;
thughes21942d92004-07-12 09:35:37 +0000702 }
nethercote71980f02004-01-24 18:18:54 +0000703 *cp = save;
704 entry = cp+1;
705 }
706 cp++;
707 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000708
709 return False;
710}
711
nethercote71980f02004-01-24 18:18:54 +0000712/* Prepare the client's environment. This is basically a copy of our
713 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000714 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000715
sewardjb5f6f512005-03-10 23:59:00 +0000716 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000717
718 Yummy. String hacking in C.
719
720 If this needs to handle any more variables it should be hacked
721 into something table driven.
722 */
723static char **fix_environment(char **origenv, const char *preload)
724{
725 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000726 static const char ld_preload[] = "LD_PRELOAD=";
727 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000728 static const int ld_preload_len = sizeof(ld_preload)-1;
729 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
730 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000731 char *inject_path;
732 int inject_path_len;
733 int vgliblen = strlen(VG_(libdir));
734 char **cpp;
735 char **ret;
736 int envc;
737 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
738
739 /* Find the vg_inject.so; also make room for the tool preload
740 library */
741 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
742 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000743 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000744
745 if (preload)
746 snprintf(inject_path, inject_path_len, "%s/%s:%s",
747 VG_(libdir), inject_so, preload);
748 else
749 snprintf(inject_path, inject_path_len, "%s/%s",
750 VG_(libdir), inject_so);
751
752 /* Count the original size of the env */
753 envc = 0; /* trailing NULL */
754 for (cpp = origenv; cpp && *cpp; cpp++)
755 envc++;
756
757 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000758 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000759 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000760
761 /* copy it over */
762 for (cpp = ret; *origenv; )
763 *cpp++ = *origenv++;
764 *cpp = NULL;
765
766 vg_assert(envc == (cpp - ret));
767
768 /* Walk over the new environment, mashing as we go */
769 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000770 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000771 int len = strlen(*cpp) + inject_path_len;
772 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000773 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000774
775 snprintf(cp, len, "%s%s:%s",
776 ld_preload, inject_path, (*cpp)+ld_preload_len);
777
778 *cpp = cp;
779
780 ld_preload_done = 1;
781 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
782 *cpp = "";
783 }
784 }
785
786 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000787 if (!ld_preload_done) {
788 int len = ld_preload_len + inject_path_len;
789 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000790 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000791
792 snprintf(cp, len, "%s%s",
793 ld_preload, inject_path);
794
795 ret[envc++] = cp;
796 }
797
sewardjb5f6f512005-03-10 23:59:00 +0000798 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000799 ret[envc] = NULL;
800
801 return ret;
802}
803
804extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000805
806/* Add a string onto the string table, and return its address */
807static char *copy_str(char **tab, const char *str)
808{
809 char *cp = *tab;
810 char *orig = cp;
811
812 while(*str)
813 *cp++ = *str++;
814 *cp++ = '\0';
815
816 if (0)
nethercote545fe672004-11-01 16:52:43 +0000817 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000818
819 *tab = cp;
820
821 return orig;
822}
823
824/*
825 This sets up the client's initial stack, containing the args,
826 environment and aux vector.
827
828 The format of the stack is:
829
830 higher address +-----------------+
831 | Trampoline code |
832 +-----------------+
833 | |
834 : string table :
835 | |
836 +-----------------+
837 | AT_NULL |
838 - -
839 | auxv |
840 +-----------------+
841 | NULL |
842 - -
843 | envp |
844 +-----------------+
845 | NULL |
846 - -
847 | argv |
848 +-----------------+
849 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000850 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000851 | undefined |
852 : :
853 */
nethercotec25c4492004-10-18 11:52:17 +0000854static Addr setup_client_stack(void* init_sp,
855 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000856 const struct exeinfo *info,
857 UInt** client_auxv)
858{
nethercotee567e702004-07-10 17:49:17 +0000859 void* res;
nethercote71980f02004-01-24 18:18:54 +0000860 char **cpp;
861 char *strtab; /* string table */
862 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000863 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000864 struct ume_auxv *auxv;
865 const struct ume_auxv *orig_auxv;
866 const struct ume_auxv *cauxv;
867 unsigned stringsize; /* total size of strings in bytes */
868 unsigned auxsize; /* total size of auxv in bytes */
869 int argc; /* total argc */
870 int envc; /* total number of env vars */
871 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000872 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000873
874 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000875 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000876
877 /* ==================== compute sizes ==================== */
878
879 /* first of all, work out how big the client stack will be */
880 stringsize = 0;
881
882 /* paste on the extra args if the loader needs them (ie, the #!
883 interpreter and its argument) */
884 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000885 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000886 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000887 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000888 }
nethercoted6a56872004-07-26 15:32:47 +0000889 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000890 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000891 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000892 }
893
894 /* now scan the args we're given... */
895 for (cpp = orig_argv; *cpp; cpp++) {
896 argc++;
897 stringsize += strlen(*cpp) + 1;
898 }
899
900 /* ...and the environment */
901 envc = 0;
902 for (cpp = orig_envp; cpp && *cpp; cpp++) {
903 envc++;
904 stringsize += strlen(*cpp) + 1;
905 }
906
907 /* now, how big is the auxv? */
908 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
909 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
910 if (cauxv->a_type == AT_PLATFORM)
911 stringsize += strlen(cauxv->u.a_ptr) + 1;
912 auxsize += sizeof(*cauxv);
913 }
914
915 /* OK, now we know how big the client stack is */
916 stacksize =
917 sizeof(int) + /* argc */
918 sizeof(char **)*argc + /* argv */
919 sizeof(char **) + /* terminal NULL */
920 sizeof(char **)*envc + /* envp */
921 sizeof(char **) + /* terminal NULL */
922 auxsize + /* auxv */
923 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000924 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000925
sewardj79048ce2005-02-18 08:28:32 +0000926 if (0) VG_(printf)("stacksize = %d\n", stacksize);
927
nethercotef84f6952004-07-15 14:58:33 +0000928 // decide where stack goes!
929 VG_(clstk_end) = VG_(client_end);
930
nethercote73b526f2004-10-31 18:48:21 +0000931 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000932
nethercote71980f02004-01-24 18:18:54 +0000933 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000934 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000935 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
936
nethercote71980f02004-01-24 18:18:54 +0000937 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000938 stringbase = strtab = (char *)(VG_(client_trampoline_code)
939 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000940
941 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000942
sewardj79048ce2005-02-18 08:28:32 +0000943 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000944 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000945 "clstk_base %p\n"
946 "clstk_end %p\n",
947 stringsize, auxsize, stacksize,
948 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000949
nethercote71980f02004-01-24 18:18:54 +0000950 /* ==================== allocate space ==================== */
951
952 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000953 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000954 PROT_READ | PROT_WRITE | PROT_EXEC,
955 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
956 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000957
958 /* ==================== copy client stack ==================== */
959
nethercotea3c3cf22004-11-01 18:38:00 +0000960 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000961
962 /* --- argc --- */
963 *ptr++ = argc; /* client argc */
964
965 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000966 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000967 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000968 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000969 }
nethercoted6a56872004-07-26 15:32:47 +0000970 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000971 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000972 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000973 }
974 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000975 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000976 }
977 *ptr++ = 0;
978
979 /* --- envp --- */
980 VG_(client_envp) = (Char **)ptr;
981 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000982 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000983 *ptr++ = 0;
984
985 /* --- auxv --- */
986 auxv = (struct ume_auxv *)ptr;
987 *client_auxv = (UInt *)auxv;
988
989 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
990 /* copy the entry... */
991 *auxv = *orig_auxv;
992
993 /* ...and fix up the copy */
994 switch(auxv->a_type) {
995 case AT_PHDR:
996 if (info->phdr == 0)
997 auxv->a_type = AT_IGNORE;
998 else
999 auxv->u.a_val = info->phdr;
1000 break;
1001
1002 case AT_PHNUM:
1003 if (info->phdr == 0)
1004 auxv->a_type = AT_IGNORE;
1005 else
1006 auxv->u.a_val = info->phnum;
1007 break;
1008
1009 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001010 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001011 break;
1012
1013 case AT_PLATFORM: /* points to a platform description string */
1014 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1015 break;
1016
1017 case AT_ENTRY:
1018 auxv->u.a_val = info->entry;
1019 break;
1020
1021 case AT_IGNORE:
1022 case AT_EXECFD:
1023 case AT_PHENT:
1024 case AT_PAGESZ:
1025 case AT_FLAGS:
1026 case AT_NOTELF:
1027 case AT_UID:
1028 case AT_EUID:
1029 case AT_GID:
1030 case AT_EGID:
1031 case AT_CLKTCK:
1032 case AT_HWCAP:
1033 case AT_FPUCW:
1034 case AT_DCACHEBSIZE:
1035 case AT_ICACHEBSIZE:
1036 case AT_UCACHEBSIZE:
1037 /* All these are pointerless, so we don't need to do anything
1038 about them. */
1039 break;
1040
1041 case AT_SECURE:
1042 /* If this is 1, then it means that this program is running
1043 suid, and therefore the dynamic linker should be careful
1044 about LD_PRELOAD, etc. However, since stage1 (the thing
1045 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001046 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001047 set AT_SECURE to 0. */
1048 auxv->u.a_val = 0;
1049 break;
1050
1051 case AT_SYSINFO:
1052 /* Leave this unmolested for now, but we'll update it later
1053 when we set up the client trampoline code page */
1054 break;
1055
1056 case AT_SYSINFO_EHDR:
1057 /* Trash this, because we don't reproduce it */
1058 auxv->a_type = AT_IGNORE;
1059 break;
1060
1061 default:
1062 /* stomp out anything we don't know about */
1063 if (0)
nethercote545fe672004-11-01 16:52:43 +00001064 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001065 auxv->a_type = AT_IGNORE;
1066 break;
1067
1068 }
1069 }
1070 *auxv = *orig_auxv;
1071 vg_assert(auxv->a_type == AT_NULL);
1072
njnc6168192004-11-29 13:54:10 +00001073// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1074// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001075#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001076 /* --- trampoline page --- */
1077 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1078 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001079#endif
nethercotef84f6952004-07-15 14:58:33 +00001080
nethercote71980f02004-01-24 18:18:54 +00001081 vg_assert((strtab-stringbase) == stringsize);
1082
nethercote5ee67ca2004-06-22 14:00:09 +00001083 /* We know the initial ESP is pointing at argc/argv */
1084 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001085 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001086
sewardj79048ce2005-02-18 08:28:32 +00001087 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001088 return cl_esp;
1089}
1090
1091/*====================================================================*/
1092/*=== Find executable ===*/
1093/*====================================================================*/
1094
thughes4ad52d02004-06-27 17:37:21 +00001095static const char* executable_name;
1096
1097static Bool match_executable(const char *entry) {
1098 char buf[strlen(entry) + strlen(executable_name) + 2];
1099
1100 /* empty PATH element means . */
1101 if (*entry == '\0')
1102 entry = ".";
1103
1104 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1105
1106 if (access(buf, R_OK|X_OK) == 0) {
1107 executable_name = strdup(buf);
1108 vg_assert(NULL != executable_name);
1109 return True;
1110 }
1111 return False;
1112}
1113
nethercote71980f02004-01-24 18:18:54 +00001114static const char* find_executable(const char* exec)
1115{
1116 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001117 executable_name = exec;
1118 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001119 /* no '/' - we need to search the path */
1120 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001121 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001122 }
thughes4ad52d02004-06-27 17:37:21 +00001123 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001124}
1125
1126
1127/*====================================================================*/
1128/*=== Loading tools ===*/
1129/*====================================================================*/
1130
1131static void list_tools(void)
1132{
1133 DIR *dir = opendir(VG_(libdir));
1134 struct dirent *de;
1135 int first = 1;
1136
1137 if (dir == NULL) {
1138 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001139 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001140 return;
1141 }
1142
nethercotef4928da2004-06-15 10:54:40 +00001143 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001144 int len = strlen(de->d_name);
1145
njn063c5402004-11-22 16:58:05 +00001146 /* look for vgtool_TOOL.so names */
1147 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1148 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001149 VG_STREQ(de->d_name + len - 3, ".so")) {
1150 if (first) {
1151 fprintf(stderr, "Available tools:\n");
1152 first = 0;
1153 }
1154 de->d_name[len-3] = '\0';
1155 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001156 }
1157 }
1158
1159 closedir(dir);
1160
1161 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001162 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1163 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001164}
1165
1166
1167/* Find and load a tool, and check it looks ok. Also looks to see if there's
1168 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1169static void load_tool( const char *toolname, void** handle_out,
1170 ToolInfo** toolinfo_out, char **preloadpath_out )
1171{
1172 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001173 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001174 char buf[len];
1175 void* handle;
1176 ToolInfo* toolinfo;
1177 char* preloadpath = NULL;
1178 Int* vg_malloc_redzonep;
1179
1180 // XXX: allowing full paths for --tool option -- does it make sense?
1181 // Doesn't allow for vgpreload_<tool>.so.
1182
1183 if (strchr(toolname, '/') != 0) {
1184 /* toolname contains '/', and so must be a pathname */
1185 handle = dlopen(toolname, RTLD_NOW);
1186 } else {
1187 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001188 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001189 handle = dlopen(buf, RTLD_NOW);
1190
1191 if (handle != NULL) {
1192 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1193 if (access(buf, R_OK) == 0) {
1194 preloadpath = strdup(buf);
1195 vg_assert(NULL != preloadpath);
1196 }
1197 }
1198 }
1199
1200 ok = (NULL != handle);
1201 if (!ok) {
1202 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1203 goto bad_load;
1204 }
1205
njn26f02512004-11-22 18:33:15 +00001206 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001207 ok = (NULL != toolinfo);
1208 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001209 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001210 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1211 goto bad_load;
1212 }
1213
1214 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1215 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001216 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001217 if (!ok) {
1218 fprintf(stderr, "Error:\n"
1219 " Tool and core interface versions do not match.\n"
1220 " Interface version used by core is: %d.%d (size %d)\n"
1221 " Interface version used by tool is: %d.%d (size %d)\n"
1222 " The major version numbers must match.\n",
1223 VG_CORE_INTERFACE_MAJOR_VERSION,
1224 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001225 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001226 toolinfo->interface_major_version,
1227 toolinfo->interface_minor_version,
1228 toolinfo->sizeof_ToolInfo);
1229 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1230 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001231 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001232 else
nethercote996901a2004-08-03 13:29:09 +00001233 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001234 goto bad_load;
1235 }
1236
1237 // Set redzone size for V's allocator
1238 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1239 if ( NULL != vg_malloc_redzonep ) {
1240 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1241 }
1242
1243 vg_assert(NULL != handle && NULL != toolinfo);
1244 *handle_out = handle;
1245 *toolinfo_out = toolinfo;
1246 *preloadpath_out = preloadpath;
1247 return;
1248
1249
1250 bad_load:
1251 if (handle != NULL)
1252 dlclose(handle);
1253
nethercotef4928da2004-06-15 10:54:40 +00001254 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001255 list_tools();
1256 exit(127);
1257}
1258
nethercotef4928da2004-06-15 10:54:40 +00001259
1260/*====================================================================*/
1261/*=== Command line errors ===*/
1262/*====================================================================*/
1263
1264static void abort_msg ( void )
1265{
nethercotef8548672004-06-21 12:42:35 +00001266 VG_(clo_log_to) = VgLogTo_Fd;
1267 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001268}
1269
1270void VG_(bad_option) ( Char* opt )
1271{
1272 abort_msg();
1273 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1274 VG_(printf)("valgrind: Use --help for more information.\n");
1275 VG_(exit)(1);
1276}
1277
nethercotef4928da2004-06-15 10:54:40 +00001278static void missing_prog ( void )
1279{
1280 abort_msg();
1281 VG_(printf)("valgrind: no program specified\n");
1282 VG_(printf)("valgrind: Use --help for more information.\n");
1283 VG_(exit)(1);
1284}
1285
1286static void config_error ( Char* msg )
1287{
1288 abort_msg();
1289 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1290 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1291 VG_(exit)(1);
1292}
1293
1294
nethercote71980f02004-01-24 18:18:54 +00001295/*====================================================================*/
1296/*=== Loading the client ===*/
1297/*====================================================================*/
1298
nethercotef4928da2004-06-15 10:54:40 +00001299static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001300 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1301{
1302 // If they didn't specify an executable with --exec, and didn't specify
1303 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001304 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001305 if (cl_argv[0] == NULL ||
1306 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1307 {
nethercotef4928da2004-06-15 10:54:40 +00001308 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001309 }
1310 }
1311
1312 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001313 info->exe_base = VG_(client_base);
1314 info->exe_end = VG_(client_end);
1315 info->argv = cl_argv;
1316
nethercotef4928da2004-06-15 10:54:40 +00001317 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001318 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001319 // Totally zero 'info' before continuing.
1320 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001321 } else {
1322 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001323 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001324 ret = do_exec(exec, info);
1325 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001326 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1327 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001328 exit(127);
1329 }
1330 }
1331
1332 /* Copy necessary bits of 'info' that were filled in */
1333 *client_eip = info->init_eip;
1334 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1335}
1336
nethercote969ecf12004-10-13 17:29:01 +00001337/*====================================================================*/
1338/*=== Address space unpadding ===*/
1339/*====================================================================*/
1340
1341typedef struct {
1342 char* killpad_start;
1343 char* killpad_end;
1344 struct stat* killpad_padstat;
1345} killpad_extra;
1346
1347static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1348 int maj, int min, int ino, void* ex)
1349{
1350 killpad_extra* extra = ex;
1351 void *b, *e;
1352 int res;
1353
1354 vg_assert(NULL != extra->killpad_padstat);
1355
1356 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1357 extra->killpad_padstat->st_ino != ino)
1358 return 1;
1359
1360 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1361 return 1;
1362
1363 if (segstart <= extra->killpad_start)
1364 b = extra->killpad_start;
1365 else
1366 b = segstart;
1367
1368 if (segend >= extra->killpad_end)
1369 e = extra->killpad_end;
1370 else
1371 e = segend;
1372
1373 res = munmap(b, (char *)e-(char *)b);
1374 vg_assert(0 == res);
1375
1376 return 1;
1377}
1378
1379// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001380static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001381{
1382 static struct stat padstat;
1383 killpad_extra extra;
1384 int res;
1385
sewardjb5f6f512005-03-10 23:59:00 +00001386 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001387
1388 res = fstat(padfile, &padstat);
1389 vg_assert(0 == res);
1390 extra.killpad_padstat = &padstat;
1391 extra.killpad_start = start;
1392 extra.killpad_end = end;
1393 foreach_map(killpad, &extra);
1394}
1395
sewardj2c5ffbe2005-03-12 13:32:06 +00001396static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001397{
1398 int res = close(padfile);
1399 vg_assert(0 == res);
1400}
1401
nethercote71980f02004-01-24 18:18:54 +00001402
1403/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001404/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001405/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001406
njn25e49d8e72002-09-23 09:36:25 +00001407/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001408VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001409Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001410Bool VG_(clo_db_attach) = False;
1411Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001412Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001413Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001414Int VG_(clo_verbosity) = 1;
1415Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001416Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001417
nethercotef1e5e152004-09-01 23:58:16 +00001418/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001419 fd is initially stdout, for --help, but gets moved to stderr by default
1420 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001421VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001422Int VG_(clo_log_fd) = 1;
1423Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001424
thughes6233a382004-08-21 11:10:44 +00001425Bool VG_(clo_time_stamp) = False;
1426
sewardj6024b212003-07-13 10:54:33 +00001427Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001428Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001429Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001430Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001431UChar VG_(clo_trace_flags) = 0; // 00000000b
1432UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001433Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001434Bool VG_(clo_trace_syscalls) = False;
1435Bool VG_(clo_trace_signals) = False;
1436Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001437Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001438Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001439Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001440Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001441Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001442Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001443Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001444Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001445Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001446Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001447Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001448Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001449Bool VG_(clo_model_pthreads) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001450
jsgf855d93d2003-10-13 22:26:55 +00001451static Bool VG_(clo_wait_for_gdb) = False;
1452
sewardjde4a1d02002-03-22 01:27:54 +00001453
sewardj2c5ffbe2005-03-12 13:32:06 +00001454static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001455{
njn25e49d8e72002-09-23 09:36:25 +00001456 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001457"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001458"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001459" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001460" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001461" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001462" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001463" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001464" -q --quiet run silently; only print error msgs\n"
1465" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001466" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001467" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001468" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001469"\n"
1470" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001471" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001472" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001473" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001474" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001475"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001476" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001477" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1478" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001479" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001480" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001481" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001482" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1484" --show-below-main=no|yes continue stack traces below main() [no]\n"
1485" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001486" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001487" --db-attach=no|yes start debugger when errors detected? [no]\n"
1488" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1489" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001490"\n";
njn7cf0bd32002-06-08 13:36:03 +00001491
njn25e49d8e72002-09-23 09:36:25 +00001492 Char* usage2 =
1493"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001494" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001495" --sanity-level=<number> level of sanity checking to do [1]\n"
1496" --single-step=no|yes translate each instr separately? [no]\n"
1497" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001498" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001499" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001500" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1501" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001502" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001503" --trace-syscalls=no|yes show all system calls? [no]\n"
1504" --trace-signals=no|yes show signal handling details? [no]\n"
1505" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001506" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001507" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001508#if 0
1509" --model-pthreads=yes|no model the pthreads library [no]\n"
1510#endif
1511" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001512"\n"
1513" --vex-iropt-verbosity 0 .. 9 [0]\n"
1514" --vex-iropt-level 0 .. 2 [2]\n"
1515" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001516" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1517" --vex-guest-max-insns 1 .. 100 [50]\n"
1518" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1519"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001520" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001521" 1000 0000 show conversion into IR\n"
1522" 0100 0000 show after initial opt\n"
1523" 0010 0000 show after instrumentation\n"
1524" 0001 0000 show after second opt\n"
1525" 0000 1000 show after tree building\n"
1526" 0000 0100 show selecting insns\n"
1527" 0000 0010 show after reg-alloc\n"
1528" 0000 0001 show final assembly\n"
1529"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001530" debugging options for Valgrind tools that report errors\n"
1531" --dump-error=<number> show translation for basic block associated\n"
1532" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001533"\n";
njn3e884182003-04-15 13:03:23 +00001534
1535 Char* usage3 =
1536"\n"
nethercote71980f02004-01-24 18:18:54 +00001537" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001538"\n"
njn53612422005-03-12 16:22:54 +00001539" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001540" and licensed under the GNU General Public License, version 2.\n"
1541" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001542"\n"
nethercote137bc552003-11-14 17:47:54 +00001543" Tools are copyright and licensed by their authors. See each\n"
1544" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n";
njn7cf0bd32002-06-08 13:36:03 +00001546
fitzhardinge98abfc72003-12-16 02:05:15 +00001547 VG_(printf)(usage1);
1548 if (VG_(details).name) {
1549 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001550 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001551 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001552 else
1553 VG_(printf)(" (none)\n");
1554 }
nethercote6c999f22004-01-31 22:55:15 +00001555 if (debug_help) {
1556 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001557
nethercote6c999f22004-01-31 22:55:15 +00001558 if (VG_(details).name) {
1559 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1560
1561 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001562 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001563 else
1564 VG_(printf)(" (none)\n");
1565 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 }
nethercote421281e2003-11-20 16:20:55 +00001567 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001568 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001569}
sewardjde4a1d02002-03-22 01:27:54 +00001570
nethercote71980f02004-01-24 18:18:54 +00001571static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001572 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001573{
nethercote71980f02004-01-24 18:18:54 +00001574 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001575
sewardj8b635a42004-11-22 19:01:47 +00001576 LibVEX_default_VexControl(& VG_(clo_vex_control));
1577
nethercote71980f02004-01-24 18:18:54 +00001578 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001579 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001580
nethercotef6a1d502004-08-09 12:21:57 +00001581 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001582 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001583 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001584
nethercotef6a1d502004-08-09 12:21:57 +00001585 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1586 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001587 *need_help = 1;
1588
nethercotef6a1d502004-08-09 12:21:57 +00001589 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001590 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6c99d72004-11-09 14:35:43 +00001592 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001593 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001594
nethercotef6a1d502004-08-09 12:21:57 +00001595 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1596 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001597 }
1598 }
nethercote71980f02004-01-24 18:18:54 +00001599}
1600
nethercote5ee67ca2004-06-22 14:00:09 +00001601static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001602{
nethercotef8548672004-06-21 12:42:35 +00001603 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001604 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001605
nethercotee1730692003-11-20 10:38:07 +00001606 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001607 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001608
sewardj19d81412002-06-03 01:10:40 +00001609 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001610 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001611 config_error("Please use absolute paths in "
1612 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001613
njnc6168192004-11-29 13:54:10 +00001614// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001615#ifdef __x86__
1616 {
sewardjb5f6f512005-03-10 23:59:00 +00001617 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001618 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1619 switch(auxp[0]) {
1620 case AT_SYSINFO:
1621 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1622 break;
1623 }
1624 }
1625 }
1626#endif
sewardjde4a1d02002-03-22 01:27:54 +00001627
nethercotef6a1d502004-08-09 12:21:57 +00001628 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001629
nethercotef6a1d502004-08-09 12:21:57 +00001630 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001631 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001632
thughes3bfd5a02004-07-18 08:05:44 +00001633 /* Look for a colon in the switch name */
1634 while (*colon && *colon != ':' && *colon != '=')
1635 colon++;
nethercote71980f02004-01-24 18:18:54 +00001636
1637 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001638 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001639 if (VG_CLO_STREQN(2, arg, "--") &&
1640 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1641 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1642 {
1643 // prefix matches, convert "--toolname:foo" to "--foo"
1644 if (0)
1645 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001646 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001647 arg[0] = '-';
1648 arg[1] = '-';
1649
1650 } else {
1651 // prefix doesn't match, skip to next arg
1652 continue;
1653 }
1654 }
1655
fitzhardinge98abfc72003-12-16 02:05:15 +00001656 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001657 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001658 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001659 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001660 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001661 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001662 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001663
nethercote71980f02004-01-24 18:18:54 +00001664 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001665 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001666
nethercote71980f02004-01-24 18:18:54 +00001667 else if (VG_CLO_STREQ(arg, "-v") ||
1668 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001669 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 else if (VG_CLO_STREQ(arg, "-q") ||
1672 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001673 VG_(clo_verbosity)--;
1674
nethercote27fec902004-06-16 21:26:32 +00001675 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001676 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1677 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1678 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001679 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001680 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
nethercote27fec902004-06-16 21:26:32 +00001681 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1682 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1683 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001684 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001685 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1686 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1687 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1688 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1689 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001690 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001691 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001692 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001693 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001694 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001695
nethercote27fec902004-06-16 21:26:32 +00001696 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1697 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001698
nethercote27fec902004-06-16 21:26:32 +00001699 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1700 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1701 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001702 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1703 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001704
sewardj8b635a42004-11-22 19:01:47 +00001705 else VG_BNUM_CLO("--vex-iropt-verbosity",
1706 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1707 else VG_BNUM_CLO("--vex-iropt-level",
1708 VG_(clo_vex_control).iropt_level, 0, 2)
1709 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1710 VG_(clo_vex_control).iropt_precise_memory_exns)
1711 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1712 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1713 else VG_BNUM_CLO("--vex-guest-max-insns",
1714 VG_(clo_vex_control).guest_max_insns, 1, 100)
1715 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1716 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1717
nethercotef8548672004-06-21 12:42:35 +00001718 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001719 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001720 VG_(clo_log_to) = VgLogTo_Fd;
1721 VG_(clo_log_name) = NULL;
1722 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1723 }
1724 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1725 VG_(clo_log_to) = VgLogTo_Fd;
1726 VG_(clo_log_name) = NULL;
1727 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001728 }
1729
nethercotef8548672004-06-21 12:42:35 +00001730 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001731 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001732 VG_(clo_log_to) = VgLogTo_File;
1733 VG_(clo_log_name) = &arg[10];
1734 }
1735 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1736 VG_(clo_log_to) = VgLogTo_File;
1737 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001738 }
sewardj603d4102005-01-11 14:01:02 +00001739 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1740 VG_(clo_log_to) = VgLogTo_FileExactly;
1741 VG_(clo_log_name) = &arg[19];
1742 }
sewardjde4a1d02002-03-22 01:27:54 +00001743
nethercotef8548672004-06-21 12:42:35 +00001744 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001745 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001746 VG_(clo_log_to) = VgLogTo_Socket;
1747 VG_(clo_log_name) = &arg[12];
1748 }
1749 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1750 VG_(clo_log_to) = VgLogTo_Socket;
1751 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001752 }
1753
nethercote71980f02004-01-24 18:18:54 +00001754 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001755 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001756 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001757 VG_(message)(Vg_UserMsg,
1758 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001759 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001760 }
nethercote71980f02004-01-24 18:18:54 +00001761 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001762 VG_(clo_n_suppressions)++;
1763 }
sewardjde4a1d02002-03-22 01:27:54 +00001764
sewardjfa8ec112005-01-19 11:55:34 +00001765 /* "stuvwxyz" --> stuvwxyz (binary) */
1766 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1767 Int j;
1768 char* opt = & arg[14];
1769
1770 if (8 != VG_(strlen)(opt)) {
1771 VG_(message)(Vg_UserMsg,
1772 "--trace-flags argument must have 8 digits");
1773 VG_(bad_option)(arg);
1774 }
1775 for (j = 0; j < 8; j++) {
1776 if ('0' == opt[j]) { /* do nothing */ }
1777 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1778 else {
1779 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1780 "contain 0s and 1s");
1781 VG_(bad_option)(arg);
1782 }
1783 }
1784 }
1785
1786 /* "stuvwxyz" --> stuvwxyz (binary) */
1787 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001788 Int j;
nethercote71980f02004-01-24 18:18:54 +00001789 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001790
sewardj2a99cf62004-11-24 10:44:19 +00001791 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001792 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001793 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001794 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001795 }
sewardj8b635a42004-11-22 19:01:47 +00001796 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001797 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001798 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001799 else {
sewardjfa8ec112005-01-19 11:55:34 +00001800 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001801 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001802 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001803 }
1804 }
1805 }
sewardjde4a1d02002-03-22 01:27:54 +00001806
sewardjc771b292004-11-30 18:55:21 +00001807 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1808
sewardjd153fae2005-01-10 17:24:47 +00001809 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1810 VG_(clo_gen_suppressions) = 0;
1811 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1812 VG_(clo_gen_suppressions) = 1;
1813 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1814 VG_(clo_gen_suppressions) = 2;
1815
nethercote71980f02004-01-24 18:18:54 +00001816 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001817 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001818 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001819 }
njn8c0b3bb2005-03-12 21:20:39 +00001820 skip_arg:
1821 if (arg != vg_argv[i])
1822 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001823 }
1824
sewardj998d40d2004-12-06 14:24:52 +00001825 /* Make VEX control parameters sane */
1826
1827 if (VG_(clo_vex_control).guest_chase_thresh
1828 >= VG_(clo_vex_control).guest_max_insns)
1829 VG_(clo_vex_control).guest_chase_thresh
1830 = VG_(clo_vex_control).guest_max_insns - 1;
1831
1832 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1833 VG_(clo_vex_control).guest_chase_thresh = 0;
1834
1835 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001836
njnf9ebf672003-05-12 21:41:30 +00001837 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001838 VG_(clo_verbosity) = 0;
1839
nethercote04d0fbc2004-01-26 16:48:06 +00001840 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(message)(Vg_UserMsg, "");
1842 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001843 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001844 VG_(message)(Vg_UserMsg,
1845 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001846 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001847 }
1848
nethercotef8548672004-06-21 12:42:35 +00001849 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001850 should be connected to whatever sink has been selected, and we
1851 indiscriminately chuck stuff into it without worrying what the
1852 nature of it is. Oh the wonder of Unix streams. */
1853
nethercotee1730692003-11-20 10:38:07 +00001854 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001855 the terminal any problems to do with processing command line
1856 opts. */
nethercotef8548672004-06-21 12:42:35 +00001857 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001858 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001859
1860 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001861
sewardj4cf05692002-10-27 20:28:29 +00001862 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001863 vg_assert(VG_(clo_log_name) == NULL);
1864 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001865 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001866
sewardj4cf05692002-10-27 20:28:29 +00001867 case VgLogTo_File: {
1868 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001869 Int seq = 0;
1870 Int pid = VG_(getpid)();
1871
nethercotef8548672004-06-21 12:42:35 +00001872 vg_assert(VG_(clo_log_name) != NULL);
1873 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001874
nethercote71980f02004-01-24 18:18:54 +00001875 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001876 if (seq == 0)
1877 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001878 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001879 else
1880 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001881 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001882 seq++;
1883
nethercotef8548672004-06-21 12:42:35 +00001884 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001885 = VG_(open)(logfilename,
1886 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1887 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001888 if (eventually_log_fd >= 0) {
1889 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001890 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001891 } else {
nethercotef8548672004-06-21 12:42:35 +00001892 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001893 VG_(message)(Vg_UserMsg,
1894 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001895 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001896 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001897 "--log-file=<file> (didn't work out for some reason.)");
1898 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001899 }
1900 }
1901 }
sewardj603d4102005-01-11 14:01:02 +00001902 break; /* switch (VG_(clo_log_to)) */
1903 }
1904
1905 case VgLogTo_FileExactly: {
1906 Char logfilename[1000];
1907
1908 vg_assert(VG_(clo_log_name) != NULL);
1909 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1910 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1911
1912 eventually_log_fd
1913 = VG_(open)(logfilename,
1914 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1915 VKI_S_IRUSR|VKI_S_IWUSR);
1916 if (eventually_log_fd >= 0) {
1917 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1918 }
1919 else if (eventually_log_fd != -VKI_EEXIST) {
1920 VG_(message)(Vg_UserMsg,
1921 "Can't create/open log file `%s'; giving up!",
1922 VG_(clo_log_name));
1923 VG_(bad_option)(
1924 "--log-file-exactly=<file> (didn't work out for some reason.)");
1925 /*NOTREACHED*/
1926 }
1927 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001928 }
1929
1930 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001931 vg_assert(VG_(clo_log_name) != NULL);
1932 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1933 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1934 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001935 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001936 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001937 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001938 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001939 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001940 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001941 }
nethercotef8548672004-06-21 12:42:35 +00001942 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001943 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001944 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001945 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001946 VG_(message)(Vg_UserMsg,
1947 "Log messages will sent to stderr instead." );
1948 VG_(message)(Vg_UserMsg,
1949 "" );
1950 /* We don't change anything here. */
1951 } else {
nethercotef8548672004-06-21 12:42:35 +00001952 vg_assert(eventually_log_fd > 0);
1953 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001954 VG_(logging_to_filedes) = False;
1955 }
sewardj73cf3bc2002-11-03 03:20:15 +00001956 break;
1957 }
1958
sewardj4cf05692002-10-27 20:28:29 +00001959 }
1960
nethercotef8548672004-06-21 12:42:35 +00001961 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001962 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001963 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001964 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1965 else {
nethercotef8548672004-06-21 12:42:35 +00001966 VG_(clo_log_fd) = eventually_log_fd;
1967 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001968 }
1969
sewardj4cf05692002-10-27 20:28:29 +00001970 /* Ok, the logging sink is running now. Print a suitable preamble.
1971 If logging to file or a socket, write details of parent PID and
1972 command line args, to help people trying to interpret the
1973 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001974
sewardj83adf412002-05-01 01:25:45 +00001975 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001976 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001977 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001978 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001979 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001980 NULL == VG_(details).version
1981 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001982 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001983 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001984
njnd04b7c62002-10-03 14:05:52 +00001985 /* Core details */
1986 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001987 "Using LibVEX rev %s, a library for dynamic binary translation.",
1988 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001989 VG_(message)(Vg_UserMsg,
1990 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1991 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001992 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00001993 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00001994 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00001995 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001996 }
1997
nethercotec1e395d2003-11-10 13:26:49 +00001998 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001999 VG_(message)(Vg_UserMsg, "");
2000 VG_(message)(Vg_UserMsg,
2001 "My PID = %d, parent PID = %d. Prog and args are:",
2002 VG_(getpid)(), VG_(getppid)() );
2003 for (i = 0; i < VG_(client_argc); i++)
2004 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2005 }
2006
sewardjde4a1d02002-03-22 01:27:54 +00002007 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002008 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002009 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002010 VG_(message)(Vg_DebugMsg, "");
2011 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2012 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002013 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002014 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002015
njn1fd5eb22005-03-13 05:43:23 +00002016 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002017 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002018 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002019 }
nethercotea70f7352004-04-18 12:08:46 +00002020
njn1fd5eb22005-03-13 05:43:23 +00002021 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002022 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2023 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002024 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002025 } else {
2026 #define BUF_LEN 256
2027 Char version_buf[BUF_LEN];
2028 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2029 vg_assert(n <= 256);
2030 if (n > 0) {
2031 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002032 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002033 } else {
njn1fd5eb22005-03-13 05:43:23 +00002034 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002035 }
2036 VG_(close)(fd);
2037 #undef BUF_LEN
2038 }
sewardjde4a1d02002-03-22 01:27:54 +00002039 }
2040
fitzhardinge98abfc72003-12-16 02:05:15 +00002041 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002042 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002043 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002044 needs one, load the default */
2045 static const Char default_supp[] = "default.supp";
2046 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2047 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2048 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2049 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2050 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002051 }
sewardj4cf05692002-10-27 20:28:29 +00002052
sewardjd153fae2005-01-10 17:24:47 +00002053 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002054 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002055 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002056 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002057 VG_(message)(Vg_UserMsg,
2058 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002059 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002060 }
sewardjde4a1d02002-03-22 01:27:54 +00002061}
2062
nethercotef6a1d502004-08-09 12:21:57 +00002063// Build the string for VALGRINDCLO.
2064Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2065{
2066 /* If we're tracing the children, then we need to start it
2067 with our starter+arguments, which are copied into VALGRINDCLO,
2068 except the --exec= option is changed if present.
2069 */
2070 Int i;
2071 Char *exec;
2072 Char *cp;
2073 Char *optvar;
2074 Int optlen, execlen;
2075
2076 // All these allocated blocks are not free - because we're either
2077 // going to exec, or panic when we fail.
2078
2079 // Create --exec= option: "--exec=<exename>"
2080 exec = VG_(arena_malloc)(VG_AR_CORE,
2081 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2082 vg_assert(NULL != exec);
2083 VG_(sprintf)(exec, "--exec=%s", exename);
2084
2085 // Allocate space for optvar (may overestimate by counting --exec twice,
2086 // no matter)
2087 optlen = 1;
2088 for (i = 0; i < vg_argc; i++)
2089 optlen += VG_(strlen)(vg_argv[i]) + 1;
2090 optlen += VG_(strlen)(exec)+1;
2091 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2092
2093 // Copy all valgrind args except the old --exec (if present)
2094 // VG_CLO_SEP is the separator.
2095 cp = optvar;
2096 for (i = 1; i < vg_argc; i++) {
2097 Char *arg = vg_argv[i];
2098
2099 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2100 // don't copy existing --exec= arg
2101 } else if (VG_(strcmp)(arg, "--") == 0) {
2102 // stop at "--"
2103 break;
2104 } else {
2105 // copy non "--exec" arg
2106 Int len = VG_(strlen)(arg);
2107 VG_(memcpy)(cp, arg, len);
2108 cp += len;
2109 *cp++ = VG_CLO_SEP;
2110 }
2111 }
2112 // Add the new --exec= option
2113 execlen = VG_(strlen)(exec);
2114 VG_(memcpy)(cp, exec, execlen);
2115 cp += execlen;
2116 *cp++ = VG_CLO_SEP;
2117
2118 *cp = '\0';
2119
2120 return optvar;
2121}
2122
2123// Build "/proc/self/fd/<execfd>".
2124Char* VG_(build_child_exename)( void )
2125{
2126 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2127 vg_assert(NULL != exename);
2128 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2129 return exename;
2130}
2131
sewardjde4a1d02002-03-22 01:27:54 +00002132
nethercote71980f02004-01-24 18:18:54 +00002133/*====================================================================*/
2134/*=== File descriptor setup ===*/
2135/*====================================================================*/
2136
2137static void setup_file_descriptors(void)
2138{
2139 struct vki_rlimit rl;
2140
2141 /* Get the current file descriptor limits. */
2142 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2143 rl.rlim_cur = 1024;
2144 rl.rlim_max = 1024;
2145 }
2146
2147 /* Work out where to move the soft limit to. */
2148 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2149 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2150 } else {
2151 rl.rlim_cur = rl.rlim_max;
2152 }
2153
2154 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002155 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2156 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002157
2158 /* Update the soft limit. */
2159 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2160
nethercotef6a1d502004-08-09 12:21:57 +00002161 if (vgexecfd != -1)
2162 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002163 if (VG_(clexecfd) != -1)
2164 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2165}
2166
nethercote71980f02004-01-24 18:18:54 +00002167/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002168/*=== Initialise program data/text, etc. ===*/
2169/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002170
sewardjb5f6f512005-03-10 23:59:00 +00002171static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2172 UInt dev, UInt ino, ULong foffset,
2173 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002174{
nethercote71980f02004-01-24 18:18:54 +00002175 /* Only record valgrind mappings for now, without loading any
2176 symbols. This is so we know where the free space is before we
2177 start allocating more memory (note: heap is OK, it's just mmap
2178 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002179 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2180 if (0)
2181 VG_(printf)("init1: %p-%p prot %s\n",
2182 start, start+size, VG_(prot_str)(prot));
2183 VG_(map_file_segment)(start, size, prot,
2184 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2185 dev, ino, foffset, filename);
2186 /* update VG_(valgrind_last) if it looks wrong */
2187 if (start+size > VG_(valgrind_last))
2188 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002189 }
sewardjde4a1d02002-03-22 01:27:54 +00002190}
2191
nethercote71980f02004-01-24 18:18:54 +00002192// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002193Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002194
sewardjb5f6f512005-03-10 23:59:00 +00002195/*
2196 This second pass adds in client mappings, and loads symbol tables
2197 for all interesting mappings. The trouble is that things can
2198 change as we go, because we're calling the Tool to track memory as
2199 we find it.
2200
2201 So for Valgrind mappings, we don't replace any mappings which
2202 aren't still identical (which will include the .so mappings, so we
2203 will load their symtabs)>
2204 */
2205static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2206 UInt dev, UInt ino, ULong foffset,
2207 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002208{
nethercote71980f02004-01-24 18:18:54 +00002209 UInt flags;
2210 Bool is_stack_segment;
2211 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002212
nethercote71980f02004-01-24 18:18:54 +00002213 is_stack_segment
2214 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
sewardjb5f6f512005-03-10 23:59:00 +00002216 if (0)
2217 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2218 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002219
nethercote71980f02004-01-24 18:18:54 +00002220 if (is_stack_segment)
2221 flags = SF_STACK | SF_GROWDOWN;
2222 else
2223 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002224
nethercote71980f02004-01-24 18:18:54 +00002225 if (filename != NULL)
2226 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002227
sewardjb5f6f512005-03-10 23:59:00 +00002228#if 0
2229 // This needs to be fixed properly. jrs 20050307
2230 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2231 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002232
sewardjb5f6f512005-03-10 23:59:00 +00002233 /* We have to be a bit careful about inserting new mappings into
2234 the Valgrind part of the address space. We're actively
2235 changing things as we parse these mappings, particularly in
2236 shadow memory, and so we don't want to overwrite those
2237 changes. Therefore, we only insert/update a mapping if it is
2238 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002239
sewardjb5f6f512005-03-10 23:59:00 +00002240 NOTE: we're only talking about the Segment list mapping
2241 metadata; this doesn't actually mmap anything more. */
2242 if (filename || (s && s->addr == start && s->len == size)) {
2243 flags |= SF_VALGRIND;
2244 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2245 } else {
2246 /* assert range is already mapped */
2247 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2248 }
2249 } else
2250#endif
2251 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2252
2253 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2254 VG_TRACK( new_mem_startup, start, size,
2255 !!(prot & VKI_PROT_READ),
2256 !!(prot & VKI_PROT_WRITE),
2257 !!(prot & VKI_PROT_EXEC));
2258 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002259
nethercote71980f02004-01-24 18:18:54 +00002260 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002261 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002262 vg_assert(0 != r_esp);
2263 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002264 if (0) {
2265 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002266 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002267 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2268 r_esp, start+size);
2269 }
nethercote71980f02004-01-24 18:18:54 +00002270 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002271 // what's this for?
2272 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002273 }
sewardjde4a1d02002-03-22 01:27:54 +00002274}
2275
2276
nethercote71980f02004-01-24 18:18:54 +00002277/*====================================================================*/
2278/*=== Sanity check machinery (permanently engaged) ===*/
2279/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002280
2281/* A fast sanity check -- suitable for calling circa once per
2282 millisecond. */
2283
nethercote885dd912004-08-03 23:14:00 +00002284void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002285{
sewardjb5f6f512005-03-10 23:59:00 +00002286 ThreadId tid;
2287
njn37cea302002-09-30 11:24:00 +00002288 VGP_PUSHCC(VgpCoreCheapSanity);
2289
nethercote27fec902004-06-16 21:26:32 +00002290 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002291
2292 /* --- First do all the tests that we can do quickly. ---*/
2293
nethercote297effd2004-08-02 15:07:57 +00002294 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002295
njn25e49d8e72002-09-23 09:36:25 +00002296 /* Check stuff pertaining to the memory check system. */
2297
2298 /* Check that nobody has spuriously claimed that the first or
2299 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002300 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002301 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002302 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002303 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002304 }
njn25e49d8e72002-09-23 09:36:25 +00002305
2306 /* --- Now some more expensive checks. ---*/
2307
2308 /* Once every 25 times, check some more expensive stuff. */
2309 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002310 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002311 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002312
njn37cea302002-09-30 11:24:00 +00002313 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002314 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002315
2316# if 0
2317 { void zzzmemscan(void); zzzmemscan(); }
2318# endif
2319
nethercote297effd2004-08-02 15:07:57 +00002320 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002321 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002322
2323 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002324 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002325 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002326 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002327 }
sewardjb5f6f512005-03-10 23:59:00 +00002328
2329 /* Check that Segments and /proc/self/maps match up */
2330 //vg_assert(VG_(sanity_check_memory)());
2331
2332 /* Look for stack overruns. Visit all threads. */
2333 for(tid = 1; tid < VG_N_THREADS; tid++) {
2334 Int remains;
2335
2336 if (VG_(threads)[tid].status == VgTs_Empty ||
2337 VG_(threads)[tid].status == VgTs_Zombie)
2338 continue;
2339
2340 remains = VGA_(stack_unused)(tid);
2341 if (remains < VKI_PAGE_SIZE)
2342 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2343 tid, remains);
2344 }
2345
njn25e49d8e72002-09-23 09:36:25 +00002346 /*
nethercote297effd2004-08-02 15:07:57 +00002347 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002348 */
njn37cea302002-09-30 11:24:00 +00002349 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002350 }
2351
nethercote27fec902004-06-16 21:26:32 +00002352 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002353 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002354 /* Check sanity of the low-level memory manager. Note that bugs
2355 in the client's code can cause this to fail, so we don't do
2356 this check unless specially asked for. And because it's
2357 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002358 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002359 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002360 }
njn37cea302002-09-30 11:24:00 +00002361 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002362}
nethercote71980f02004-01-24 18:18:54 +00002363
2364
2365/*====================================================================*/
2366/*=== main() ===*/
2367/*====================================================================*/
2368
nethercotec314eba2004-07-15 12:59:41 +00002369/*
2370 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002371 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002372 loads the client executable (and the dynamic linker, if necessary)
2373 into the client part, and calls into Valgrind proper.
2374
2375 The code is careful not to allow spurious mappings to appear in the
2376 wrong parts of the address space. In particular, to make sure
2377 dlopen puts things in the right place, it will pad out the forbidden
2378 chunks of address space so that dlopen is forced to put things where
2379 we want them.
2380
2381 The memory map it creates is:
2382
2383 CLIENT_BASE +-------------------------+
2384 | client address space |
2385 : :
2386 : :
2387 | client stack |
2388 client_end +-------------------------+
2389 | redzone |
2390 shadow_base +-------------------------+
2391 | |
nethercote996901a2004-08-03 13:29:09 +00002392 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002393 | (may be 0 sized) |
2394 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002395 valgrind_base +-------------------------+
2396 | kickstart executable |
2397 | valgrind heap vvvvvvvvv| (barely used)
2398 - -
2399 | valgrind .so files |
2400 | and mappings |
2401 - -
2402 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002403 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002404 : kernel :
2405
2406 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2407 VG_(mmap)(), we need to build the segment skip-list, so we know where
2408 we can put things. However, building that structure requires
2409 allocating memory. So we need to a bootstrapping process. It's done
2410 by making VG_(arena_malloc)() have a special static superblock that's
2411 used for the first 1MB's worth of allocations. This is enough to
2412 build the segment skip-list.
2413*/
2414
nethercote31779c72004-07-30 21:50:15 +00002415static int prmap(char *start, char *end, const char *perm, off_t off,
2416 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002417 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2418 start, end, perm, maj, min, ino);
2419 return True;
2420}
2421
sewardjb5f6f512005-03-10 23:59:00 +00002422int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002423{
2424 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002425 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002426 const char *exec = NULL;
2427 char *preload; /* tool-specific LD_PRELOAD .so */
2428 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002429 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002430 struct exeinfo info;
2431 ToolInfo *toolinfo = NULL;
2432 void *tool_dlhandle;
2433 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002434 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002435 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002436 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002437 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002438
2439 //============================================================
2440 // Nb: startup is complex. Prerequisites are shown at every step.
2441 //
2442 // *** Be very careful when messing with the order ***
2443 //============================================================
2444
nethercotef4928da2004-06-15 10:54:40 +00002445 //============================================================
2446 // Command line argument handling order:
2447 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002448 // (including the tool-specific usage)
2449 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002450 // * Then, if client is missing, abort with error msg
2451 // * Then, if any cmdline args are bad, abort with error msg
2452 //============================================================
2453
fitzhardingeb50068f2004-02-24 23:42:55 +00002454 // Get the current process datasize rlimit, and set it to zero.
2455 // This prevents any internal uses of brk() from having any effect.
2456 // We remember the old value so we can restore it on exec, so that
2457 // child processes will have a reasonable brk value.
2458 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2459 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2460 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002461
2462 // Get the current process stack rlimit.
2463 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2464
nethercote71980f02004-01-24 18:18:54 +00002465 //--------------------------------------------------------------
2466 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002467 // p: none
nethercote71980f02004-01-24 18:18:54 +00002468 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002469 {
2470 void* init_sp = argv - 1;
2471 padfile = scan_auxv(init_sp);
2472 }
nethercote71980f02004-01-24 18:18:54 +00002473 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002474 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002475 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002476 }
2477
2478 //--------------------------------------------------------------
2479 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002480 // p: none
nethercote71980f02004-01-24 18:18:54 +00002481 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002482 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002483 if (cp != NULL)
2484 VG_(libdir) = cp;
2485 }
2486
2487 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002488 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2489 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002490 // p: none
nethercote71980f02004-01-24 18:18:54 +00002491 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002492 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002493 pre_process_cmd_line_options(&need_help, &tool, &exec);
2494
2495 //==============================================================
2496 // Nb: once a tool is specified, the tool.so must be loaded even if
2497 // they specified --help or didn't specify a client program.
2498 //==============================================================
2499
2500 //--------------------------------------------------------------
2501 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002502 // p: set-libdir [for VG_(libdir)]
2503 // p: pre_process_cmd_line_options() [for 'tool']
2504 //--------------------------------------------------------------
2505 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2506
2507 //==============================================================
2508 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002509 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002510 //==============================================================
2511
2512 //--------------------------------------------------------------
2513 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002514 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002515 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002516 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002517
2518 //--------------------------------------------------------------
2519 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002520 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2521 // p: layout_remaining_space [so there's space]
2522 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002523 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002524
2525 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002526 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002527 // p: layout_remaining_space() [everything must be mapped in before now]
2528 // p: load_client() [ditto]
2529 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002530 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2531 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002532
2533 //--------------------------------------------------------------
2534 // Set up client's environment
2535 // p: set-libdir [for VG_(libdir)]
2536 // p: load_tool() [for 'preload']
2537 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002538 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002539
2540 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002541 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002542 // p: load_client() [for 'info']
2543 // p: fix_environment() [for 'env']
2544 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002545 {
2546 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002547
nethercote4ad74312004-10-26 09:59:49 +00002548 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2549 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002550 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002551 }
nethercote71980f02004-01-24 18:18:54 +00002552
2553 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002554 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002555 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002556 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002557
2558 //==============================================================
2559 // Finished setting up operating environment. Now initialise
2560 // Valgrind. (This is where the old VG_(main)() started.)
2561 //==============================================================
2562
2563 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002564 // setup file descriptors
2565 // p: n/a
2566 //--------------------------------------------------------------
2567 setup_file_descriptors();
2568
2569 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002570 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002571 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002572 //--------------------------------------------------------------
2573 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2574
2575 //==============================================================
2576 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2577 //==============================================================
2578
2579 //--------------------------------------------------------------
2580 // Init tool: pre_clo_init, process cmd line, post_clo_init
2581 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2582 // p: load_tool() [for 'tool']
2583 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2584 // p: parse_procselfmaps [so VG segments are setup so tool can
2585 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002586 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002587 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002588 VG_(tool_init_dlsym)(tool_dlhandle);
2589 VG_(sanity_check_needs)();
2590
nethercotef4928da2004-06-15 10:54:40 +00002591 // If --tool and --help/--help-debug was given, now give the core+tool
2592 // help message
nethercotef4928da2004-06-15 10:54:40 +00002593 if (need_help) {
2594 usage(/*--help-debug?*/2 == need_help);
2595 }
nethercotec314eba2004-07-15 12:59:41 +00002596 process_cmd_line_options(client_auxv, tool);
2597
njn26f02512004-11-22 18:33:15 +00002598 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002599
2600 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002601 // Determine CPU architecture and subarchitecture
2602 // p: none
2603 //--------------------------------------------------------------
2604 { Bool ok = VGA_(getArchAndSubArch)(
2605 & VG_(vex_arch), & VG_(vex_subarch) );
2606 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002607 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002608 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002609 VG_(printf)(" Supported CPUs are:\n");
2610 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2611 "AMD Athlon or above)\n");
2612 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002613 VG_(exit)(1);
2614 }
2615 if (VG_(clo_verbosity) > 2) {
2616 VG_(message)(Vg_DebugMsg,
2617 "Host CPU: arch = %s, subarch = %s",
2618 LibVEX_ppVexArch( VG_(vex_arch) ),
2619 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2620 }
2621 }
2622
2623 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002624 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002625 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002626 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002627 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002628 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002629 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002630 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002631 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002632
sewardja4da2f32005-03-02 14:06:08 +00002633#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002634 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002635 // Protect client trampoline page (which is also sysinfo stuff)
2636 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002637 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002638 {
2639 Segment *seg;
2640 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2641 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002642#endif
nethercotec314eba2004-07-15 12:59:41 +00002643
sewardjb5f6f512005-03-10 23:59:00 +00002644 /* Make sure this segment isn't treated as stack */
2645 seg = VG_(find_segment)(VG_(client_trampoline_code));
2646 if (seg)
2647 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2648 }
2649
nethercotec314eba2004-07-15 12:59:41 +00002650 //==============================================================
2651 // Can use VG_(map)() after segments set up
2652 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002653
2654 //--------------------------------------------------------------
2655 // Allow GDB attach
2656 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2657 //--------------------------------------------------------------
2658 /* Hook to delay things long enough so we can get the pid and
2659 attach GDB in another shell. */
2660 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002661 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2662 /* jrs 20050206: I don't understand why this works on x86. On
2663 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2664 work. */
2665 /* do "jump *$eip" to skip this in gdb (x86) */
2666 //VG_(do_syscall0)(__NR_pause);
2667 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002668 }
2669
nethercote71980f02004-01-24 18:18:54 +00002670 // Search for file descriptors that are inherited from our parent
2671 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2672 //--------------------------------------------------------------
2673 if (VG_(clo_track_fds))
2674 VG_(init_preopened_fds)();
2675
2676 //--------------------------------------------------------------
2677 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002678 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2679 //--------------------------------------------------------------
2680 VG_(scheduler_init)();
2681
2682 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002683 // Initialise the pthread model
2684 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002685 // load_client() [for 'client_eip']
2686 // setup_client_stack() [for 'sp_at_startup']
2687 // setup_scheduler() [for the rest of state 1 stuff]
2688 //--------------------------------------------------------------
2689 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002690
2691 // Tell the tool that we just wrote to the registers.
2692 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2693 sizeof(VexGuestArchState));
2694
2695 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002696 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002697
2698 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002699 // Initialise the pthread model
2700 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002701 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002702 //if (VG_(clo_model_pthreads))
2703 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002704
2705 //--------------------------------------------------------------
2706 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002707 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002708 //--------------------------------------------------------------
2709 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2710 VG_(sigstartup_actions)();
2711
2712 //--------------------------------------------------------------
2713 // Perhaps we're profiling Valgrind?
2714 // p: process_cmd_line_options() [for VG_(clo_profile)]
2715 // p: others?
2716 //
2717 // XXX: this seems to be broken? It always says the tool wasn't built
2718 // for profiling; vg_profile.c's functions don't seem to be overriding
2719 // vg_dummy_profile.c's?
2720 //
2721 // XXX: want this as early as possible. Looking for --profile
2722 // in pre_process_cmd_line_options() could get it earlier.
2723 //--------------------------------------------------------------
2724 if (VG_(clo_profile))
2725 VGP_(init_profiling)();
2726
2727 VGP_PUSHCC(VgpStartup);
2728
2729 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002730 // Read suppression file
2731 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2732 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002733 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002734 VG_(load_suppressions)();
2735
2736 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002737 // Initialise translation table and translation cache
2738 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2739 // aren't identified as part of the client, which would waste
2740 // > 20M of virtual address space.]
2741 //--------------------------------------------------------------
2742 VG_(init_tt_tc)();
2743
2744 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002745 // Verbosity message
2746 // p: end_rdtsc_calibration [so startup message is printed first]
2747 //--------------------------------------------------------------
2748 if (VG_(clo_verbosity) == 1)
2749 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2750 if (VG_(clo_verbosity) > 0)
2751 VG_(message)(Vg_UserMsg, "");
2752
2753 //--------------------------------------------------------------
2754 // Setup pointercheck
2755 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2756 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002757 if (VG_(clo_pointercheck))
2758 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002759
nethercote71980f02004-01-24 18:18:54 +00002760 //--------------------------------------------------------------
2761 // Run!
2762 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002763 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002764
sewardjb5f6f512005-03-10 23:59:00 +00002765 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002766
sewardjb5f6f512005-03-10 23:59:00 +00002767 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002768
sewardjb5f6f512005-03-10 23:59:00 +00002769 abort();
2770}
2771
2772
2773/* Do everything which needs doing when the last thread exits */
2774void VG_(shutdown_actions)(ThreadId tid)
2775{
2776 vg_assert(tid == VG_(master_tid));
2777 vg_assert(VG_(is_running_thread)(tid));
2778
2779 // Wait for all other threads to exit.
2780 VGA_(reap_threads)(tid);
2781
2782 VG_(clo_model_pthreads) = False;
2783
2784 // Clean the client up before the final report
2785 VGA_(final_tidyup)(tid);
2786
2787 // OK, done
2788 VG_(exit_thread)(tid);
2789
2790 /* should be no threads left */
2791 vg_assert(VG_(count_living_threads)() == 0);
2792
2793 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002794 //--------------------------------------------------------------
2795 // Finalisation: cleanup, messages, etc. Order no so important, only
2796 // affects what order the messages come.
2797 //--------------------------------------------------------------
2798 if (VG_(clo_verbosity) > 0)
2799 VG_(message)(Vg_UserMsg, "");
2800
nethercote71980f02004-01-24 18:18:54 +00002801 /* Print out file descriptor summary and stats. */
2802 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002803 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002804
njn95ec8702004-11-22 16:46:13 +00002805 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002806 VG_(show_all_errors)();
2807
sewardjb5f6f512005-03-10 23:59:00 +00002808 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002809
nethercote885dd912004-08-03 23:14:00 +00002810 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002811
2812 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002813 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002814
nethercote71980f02004-01-24 18:18:54 +00002815 if (VG_(clo_profile))
2816 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002817 if (VG_(clo_profile_flags) > 0)
2818 VG_(show_BB_profile)();
2819
sewardj8b635a42004-11-22 19:01:47 +00002820 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002821 if (0)
2822 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002823
nethercote71980f02004-01-24 18:18:54 +00002824}
2825
sewardjde4a1d02002-03-22 01:27:54 +00002826/*--------------------------------------------------------------------*/
2827/*--- end vg_main.c ---*/
2828/*--------------------------------------------------------------------*/