blob: 37769546a8fd17b441361d4766c0a52ab443ef55 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
nethercote71980f02004-01-24 18:18:54 +000035
36#include <dirent.h>
37#include <dlfcn.h>
38#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000039#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000040#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000041#include <string.h>
42#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/wait.h>
46#include <unistd.h>
47
sewardjb5f6f512005-03-10 23:59:00 +000048#include "memcheck/memcheck.h"
49
thughes74b8de22004-04-22 18:12:31 +000050#ifndef AT_DCACHEBSIZE
51#define AT_DCACHEBSIZE 19
52#endif /* AT_DCACHEBSIZE */
53
54#ifndef AT_ICACHEBSIZE
55#define AT_ICACHEBSIZE 20
56#endif /* AT_ICACHEBSIZE */
57
58#ifndef AT_UCACHEBSIZE
59#define AT_UCACHEBSIZE 21
60#endif /* AT_UCACHEBSIZE */
61
nethercote71980f02004-01-24 18:18:54 +000062#ifndef AT_SYSINFO
63#define AT_SYSINFO 32
64#endif /* AT_SYSINFO */
65
66#ifndef AT_SYSINFO_EHDR
67#define AT_SYSINFO_EHDR 33
68#endif /* AT_SYSINFO_EHDR */
69
70#ifndef AT_SECURE
71#define AT_SECURE 23 /* secure mode boolean */
72#endif /* AT_SECURE */
73
nethercote71980f02004-01-24 18:18:54 +000074/* redzone gap between client address space and shadow */
75#define REDZONE_SIZE (1 * 1024*1024)
76
77/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000078#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000079
nethercotee2097312004-06-27 12:29:56 +000080/* Proportion of client space for its heap (rest is for mmaps + stack) */
81#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000082
83/*====================================================================*/
84/*=== Global entities not referenced from generated code ===*/
85/*====================================================================*/
86
sewardjde4a1d02002-03-22 01:27:54 +000087/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000088 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000089 ------------------------------------------------------------------ */
90
nethercote71980f02004-01-24 18:18:54 +000091/* Client address space, lowest to highest (see top of ume.c) */
92Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000093Addr VG_(client_end);
94Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000095Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000096Addr VG_(clstk_base);
97Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000098
99Addr VG_(brk_base); /* start of brk */
100Addr VG_(brk_limit); /* current brk */
101
nethercote996901a2004-08-03 13:29:09 +0000102Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000104
105Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000106
nethercote820bd8c2004-09-07 23:04:49 +0000107// Note that VG_(valgrind_last) names the last byte of the section, whereas
108// the VG_(*_end) vars name the byte one past the end of the section.
109Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000110
nethercote73b526f2004-10-31 18:48:21 +0000111struct vki_rlimit VG_(client_rlimit_data);
112struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000113
fitzhardinge98abfc72003-12-16 02:05:15 +0000114/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000115static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000116
117/* client executable */
118Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000119
120/* Path to library directory */
121const Char *VG_(libdir) = VG_LIBDIR;
122
123/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000124static Int vg_argc;
125static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000126
sewardjb5f6f512005-03-10 23:59:00 +0000127/* The master thread the one which will be responsible for mopping
128 everything up at exit. Normally it is tid 1, since that's the
129 first thread created, but it may be something else after a
130 fork(). */
131ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000132
thughesad1c9562004-06-26 11:27:52 +0000133/* Application-visible file descriptor limits */
134Int VG_(fd_soft_limit) = -1;
135Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000136
nethercote4ad74312004-10-26 09:59:49 +0000137/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000138 envp[] as extracted from the client's stack at startup-time. */
139Int VG_(client_argc);
140Char** VG_(client_argv);
141Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000142
njn16de5572004-11-27 14:27:21 +0000143// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000144OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000145
sewardj51ac0872004-12-21 01:20:49 +0000146/* Indicates what arch and subarch we are running on. */
147VexArch VG_(vex_arch) = VexArch_INVALID;
148VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
149
150
sewardjde4a1d02002-03-22 01:27:54 +0000151/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000152 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000153 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000154
nethercote71980f02004-01-24 18:18:54 +0000155/* Counts downwards in VG_(run_innerloop). */
156UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000157
158/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000159ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000160
nethercote71980f02004-01-24 18:18:54 +0000161/* Tell the logging mechanism whether we are logging to a file
162 descriptor or a socket descriptor. */
163Bool VG_(logging_to_filedes) = True;
164
sewardj73cf3bc2002-11-03 03:20:15 +0000165
nethercote71980f02004-01-24 18:18:54 +0000166/*====================================================================*/
167/*=== Counters, for profiling purposes only ===*/
168/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000169
sewardjde4a1d02002-03-22 01:27:54 +0000170/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000171static UInt sanity_fast_count = 0;
172static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000173
nethercote3a42fb82004-08-03 18:08:50 +0000174static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000175{
nethercote3a42fb82004-08-03 18:08:50 +0000176 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000177 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000178 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000179 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000182 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000183
nethercote71980f02004-01-24 18:18:54 +0000184 VG_(message)(Vg_DebugMsg,
185 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000186 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000189 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000190 VG_(message)(Vg_DebugMsg, "");
191 VG_(message)(Vg_DebugMsg,
192 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000193 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000194 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000195 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000196 //VG_(print_shadow_stats)();
197 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000198 VG_(message)(Vg_DebugMsg,
199 "------ Valgrind's ExeContext management stats follow ------" );
200 VG_(print_ExeContext_stats)();
201 }
nethercote71980f02004-01-24 18:18:54 +0000202}
203
204
205/*====================================================================*/
206/*=== Miscellaneous global functions ===*/
207/*====================================================================*/
208
nethercotecf97ffb2004-09-09 13:40:31 +0000209static Int ptrace_setregs(Int pid, ThreadId tid)
210{
sewardj2a99cf62004-11-24 10:44:19 +0000211 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000212}
213
nethercote04d0fbc2004-01-26 16:48:06 +0000214/* Start debugger and get it to attach to this process. Called if the
215 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000216 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000217 meaningfully get the debugger to continue the program, though; to
218 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000219void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000220{
221 Int pid;
222
223 if ((pid = fork()) == 0) {
224 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000225 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000226
227 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000228 Int status;
229 Int res;
230
nethercote71980f02004-01-24 18:18:54 +0000231 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
232 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000233 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000234 kill(pid, SIGSTOP) == 0 &&
235 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000236 Char pidbuf[15];
237 Char file[30];
238 Char buf[100];
239 Char *bufptr;
240 Char *cmdptr;
241
242 VG_(sprintf)(pidbuf, "%d", pid);
243 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
244
245 bufptr = buf;
246 cmdptr = VG_(clo_db_command);
247
248 while (*cmdptr) {
249 switch (*cmdptr) {
250 case '%':
251 switch (*++cmdptr) {
252 case 'f':
253 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
254 bufptr += VG_(strlen)(file);
255 cmdptr++;
256 break;
257 case 'p':
258 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
259 bufptr += VG_(strlen)(pidbuf);
260 cmdptr++;
261 break;
262 default:
263 *bufptr++ = *cmdptr++;
264 break;
265 }
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 }
272
273 *bufptr++ = '\0';
274
275 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000276 res = VG_(system)(buf);
277 if (res == 0) {
278 VG_(message)(Vg_UserMsg, "");
279 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000280 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000281 } else {
282 VG_(message)(Vg_UserMsg, "Apparently failed!");
283 VG_(message)(Vg_UserMsg, "");
284 }
285 }
286
nethercote73b526f2004-10-31 18:48:21 +0000287 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000288 VG_(waitpid)(pid, &status, 0);
289 }
290}
291
292
293/* Print some helpful-ish text about unimplemented things, and give
294 up. */
295void VG_(unimplemented) ( Char* msg )
296{
297 VG_(message)(Vg_UserMsg, "");
298 VG_(message)(Vg_UserMsg,
299 "Valgrind detected that your program requires");
300 VG_(message)(Vg_UserMsg,
301 "the following unimplemented functionality:");
302 VG_(message)(Vg_UserMsg, " %s", msg);
303 VG_(message)(Vg_UserMsg,
304 "This may be because the functionality is hard to implement,");
305 VG_(message)(Vg_UserMsg,
306 "or because no reasonable program would behave this way,");
307 VG_(message)(Vg_UserMsg,
308 "or because nobody has yet needed it. In any case, let us know at");
309 VG_(message)(Vg_UserMsg,
310 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
311 VG_(message)(Vg_UserMsg,
312 "");
313 VG_(message)(Vg_UserMsg,
314 "Valgrind has to exit now. Sorry. Bye!");
315 VG_(message)(Vg_UserMsg,
316 "");
317 VG_(pp_sched_status)();
318 VG_(exit)(1);
319}
320
sewardj2a99cf62004-11-24 10:44:19 +0000321/* Get the simulated stack pointer */
322Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000323{
njncf45fd42004-11-24 16:30:22 +0000324 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000325}
326
njnea4b28c2004-11-30 16:04:58 +0000327/* Debugging thing .. can be called from assembly with OYNK macro. */
328void VG_(oynk) ( Int n )
329{
330 OINK(n);
331}
332
nethercote71980f02004-01-24 18:18:54 +0000333/*====================================================================*/
334/*=== Check we were launched by stage 1 ===*/
335/*====================================================================*/
336
337/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000338static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000339{
nethercoteebf1d862004-11-01 18:22:05 +0000340 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000341 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000342
343 for (; auxv->a_type != AT_NULL; auxv++)
344 switch(auxv->a_type) {
345 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000346 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000347 found |= 1;
348 break;
349
350 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000351 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 2;
353 break;
nethercote7f390022004-10-25 17:18:24 +0000354
355 case AT_PHDR:
356 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
357 break;
nethercote71980f02004-01-24 18:18:54 +0000358 }
359
nethercote361a14e2004-07-26 11:11:56 +0000360 if ( found != (1|2) ) {
361 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000362 exit(127);
363 }
nethercote31779c72004-07-30 21:50:15 +0000364 vg_assert(padfile >= 0);
365 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000366}
367
368
369/*====================================================================*/
370/*=== Address space determination ===*/
371/*====================================================================*/
372
nethercote7f390022004-10-25 17:18:24 +0000373extern char _start[];
374
nethercote31779c72004-07-30 21:50:15 +0000375static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000376{
nethercotea3c3cf22004-11-01 18:38:00 +0000377 Int ires;
378 void* vres;
379 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000380
nethercote7f390022004-10-25 17:18:24 +0000381 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
382 // this is a workable approximation
383 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000384 VG_(valgrind_base) = PGROUNDDN(&_start);
385 }
386
nethercote820bd8c2004-09-07 23:04:49 +0000387 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000388
nethercote31779c72004-07-30 21:50:15 +0000389 // This gives the client the largest possible address space while
390 // taking into account the tool's shadow needs.
391 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000392 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000393 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000394 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000395 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000396 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000397 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000398
nethercote31779c72004-07-30 21:50:15 +0000399 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000400 VG_(shadow_end) = VG_(valgrind_base);
401 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000402
nethercotee2097312004-06-27 12:29:56 +0000403#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
404
nethercote71980f02004-01-24 18:18:54 +0000405 if (0)
nethercotee2097312004-06-27 12:29:56 +0000406 VG_(printf)(
407 "client_base %8x (%dMB)\n"
408 "client_mapbase %8x (%dMB)\n"
409 "client_end %8x (%dMB)\n"
410 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000411 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000412 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000413 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000414 VG_(client_base), SEGSIZE(client_base, client_mapbase),
415 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
416 VG_(client_end), SEGSIZE(client_end, shadow_base),
417 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000418 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000419 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
420 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000421 );
422
423#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000424
425 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000426 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000427 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000428 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000431 ires = munmap((void*)VG_(client_base), client_size);
432 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000433
434 // Map shadow memory.
435 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000436 if (shadow_size != 0) {
437 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000438 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000439 if ((void*)-1 == vres) {
440 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000441 "valgrind: Could not allocate address space (%p bytes)\n"
442 "valgrind: for shadow memory\n"
443 "valgrind: Possible causes:\n"
444 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
445 "valgrind: needs at least 1.5GB swap space.\n"
446 "valgrind: - Or, your virtual memory size may be limited (check\n"
447 "valgrind: with 'ulimit -v').\n"
448 "valgrind: - Or, your system may use a kernel that provides only a\n"
449 "valgrind: too-small (eg. 2GB) user address space.\n"
450 , (void*)shadow_size
451 );
nethercoted4722622004-08-30 19:36:42 +0000452 exit(1);
453 }
nethercotee567e702004-07-10 17:49:17 +0000454 }
nethercote71980f02004-01-24 18:18:54 +0000455}
456
457/*====================================================================*/
458/*=== Command line setup ===*/
459/*====================================================================*/
460
461/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
462static char* get_file_clo(char* dir)
463{
464# define FLEN 512
465 Int fd, n;
466 struct stat s1;
467 char* f_clo = NULL;
468 char filename[FLEN];
469
470 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
471 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
472 if ( fd > 0 ) {
473 if ( 0 == fstat(fd, &s1) ) {
474 f_clo = malloc(s1.st_size+1);
475 vg_assert(f_clo);
476 n = read(fd, f_clo, s1.st_size);
477 if (n == -1) n = 0;
478 f_clo[n] = '\0';
479 }
480 close(fd);
481 }
482 return f_clo;
483# undef FLEN
484}
485
nethercotee2097312004-06-27 12:29:56 +0000486#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
487
nethercote71980f02004-01-24 18:18:54 +0000488static Int count_args(char* s)
489{
490 Int n = 0;
491 if (s) {
492 char* cp = s;
493 while (True) {
494 // We have alternating sequences: blanks, non-blanks, blanks...
495 // count the non-blanks sequences.
496 while ( ISSPACE(*cp) ) cp++;
497 if ( !*cp ) break;
498 n++;
499 while ( !ISSPACE(*cp) && *cp ) cp++;
500 }
501 }
502 return n;
503}
504
505/* add args out of environment, skipping multiple spaces and -- args */
506static char** copy_args( char* s, char** to )
507{
508 if (s) {
509 char* cp = s;
510 while (True) {
511 // We have alternating sequences: blanks, non-blanks, blanks...
512 // copy the non-blanks sequences, and add terminating '\0'
513 while ( ISSPACE(*cp) ) cp++;
514 if ( !*cp ) break;
515 *to++ = cp;
516 while ( !ISSPACE(*cp) && *cp ) cp++;
517 if ( *cp ) *cp++ = '\0'; // terminate if necessary
518 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
519 }
520 }
521 return to;
522}
523
nethercotee2097312004-06-27 12:29:56 +0000524#undef ISSPACE
525
nethercote71980f02004-01-24 18:18:54 +0000526// Augment command line with arguments from environment and .valgrindrc
527// files.
528static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
529{
nethercotef6a1d502004-08-09 12:21:57 +0000530 int vg_argc0 = *vg_argc_inout;
531 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000532
533 char* env_clo = getenv(VALGRINDOPTS);
534 char* f1_clo = get_file_clo( getenv("HOME") );
535 char* f2_clo = get_file_clo(".");
536
537 /* copy any extra args from file or environment, if present */
538 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
539 /* ' ' separated extra options */
540 char **from;
541 char **to;
thughescaca0022004-09-13 10:20:34 +0000542 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
543
544 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
545
nethercote71980f02004-01-24 18:18:54 +0000546 env_arg_count = count_args(env_clo);
547 f1_arg_count = count_args(f1_clo);
548 f2_arg_count = count_args(f2_clo);
549
550 if (0)
551 printf("extra-argc=%d %d %d\n",
552 env_arg_count, f1_arg_count, f2_arg_count);
553
554 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000555 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000556 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000557 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000558 vg_assert(vg_argv0);
559 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000560
561 /* copy argv[0] */
562 *to++ = *from++;
563
564 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
565 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
566 * to override less local ones. */
567 to = copy_args(f1_clo, to);
568 to = copy_args(env_clo, to);
569 to = copy_args(f2_clo, to);
570
571 /* copy original arguments, stopping at command or -- */
572 while (*from) {
573 if (**from != '-')
574 break;
575 if (VG_STREQ(*from, "--")) {
576 from++; /* skip -- */
577 break;
578 }
579 *to++ = *from++;
580 }
581
582 /* add -- */
583 *to++ = "--";
584
nethercotef6a1d502004-08-09 12:21:57 +0000585 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000586
587 /* copy rest of original command line, then NULL */
588 while (*from) *to++ = *from++;
589 *to = NULL;
590 }
591
nethercotef6a1d502004-08-09 12:21:57 +0000592 *vg_argc_inout = vg_argc0;
593 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000594}
595
nethercotef6a1d502004-08-09 12:21:57 +0000596#define VG_CLO_SEP '\01'
597
nethercote71980f02004-01-24 18:18:54 +0000598static void get_command_line( int argc, char** argv,
599 Int* vg_argc_out, Char*** vg_argv_out,
600 char*** cl_argv_out )
601{
nethercotef6a1d502004-08-09 12:21:57 +0000602 int vg_argc0;
603 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000604 char** cl_argv;
605 char* env_clo = getenv(VALGRINDCLO);
606
607 if (env_clo != NULL && *env_clo != '\0') {
608 char *cp;
609 char **cpp;
610
nethercotef6a1d502004-08-09 12:21:57 +0000611 /* OK, VALGRINDCLO is set, which means we must be a child of another
612 Valgrind process using --trace-children, so we're getting all our
613 arguments from VALGRINDCLO, and the entire command line belongs to
614 the client (including argv[0]) */
615 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000616 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000617 if (*cp == VG_CLO_SEP)
618 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000619
nethercotef6a1d502004-08-09 12:21:57 +0000620 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
621 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000622
nethercotef6a1d502004-08-09 12:21:57 +0000623 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000624
625 *cpp++ = "valgrind"; /* nominal argv[0] */
626 *cpp++ = env_clo;
627
nethercotef6a1d502004-08-09 12:21:57 +0000628 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000629 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000630 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000631 *cp++ = '\0'; /* chop it up in place */
632 *cpp++ = cp;
633 }
634 }
635 *cpp = NULL;
636 cl_argv = argv;
637
638 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000639 Bool noaugment = False;
640
nethercote71980f02004-01-24 18:18:54 +0000641 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000642 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000643
nethercotef6a1d502004-08-09 12:21:57 +0000644 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000645 Char* arg = argv[vg_argc0];
646 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000647 break;
sewardjb5f6f512005-03-10 23:59:00 +0000648 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000649 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000650 break;
651 }
sewardjb5f6f512005-03-10 23:59:00 +0000652 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000653 }
nethercotef6a1d502004-08-09 12:21:57 +0000654 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000655
656 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000657 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000658 those extra args will already be present in VALGRINDCLO.
659 (We also don't do it when --command-line-only=yes.) */
660 if (!noaugment)
661 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000662 }
663
664 if (0) {
665 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000666 for (i = 0; i < vg_argc0; i++)
667 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000668 }
669
nethercotef6a1d502004-08-09 12:21:57 +0000670 *vg_argc_out = vg_argc0;
671 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000672 *cl_argv_out = cl_argv;
673}
674
675
676/*====================================================================*/
677/*=== Environment and stack setup ===*/
678/*====================================================================*/
679
680/* Scan a colon-separated list, and call a function on each element.
681 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000682 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000683 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000684
685 This routine will return True if (*func) returns True and False if
686 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000687*/
thughes4ad52d02004-06-27 17:37:21 +0000688static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000689{
690 char *cp, *entry;
691 int end;
692
693 if (colsep == NULL ||
694 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000695 return False;
nethercote71980f02004-01-24 18:18:54 +0000696
697 entry = cp = colsep;
698
699 do {
700 end = (*cp == '\0');
701
702 if (*cp == ':' || *cp == '\0') {
703 char save = *cp;
704
705 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000706 if ((*func)(entry)) {
707 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000708 return True;
thughes21942d92004-07-12 09:35:37 +0000709 }
nethercote71980f02004-01-24 18:18:54 +0000710 *cp = save;
711 entry = cp+1;
712 }
713 cp++;
714 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000715
716 return False;
717}
718
nethercote71980f02004-01-24 18:18:54 +0000719/* Prepare the client's environment. This is basically a copy of our
720 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000721 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000722
sewardjb5f6f512005-03-10 23:59:00 +0000723 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000724
725 Yummy. String hacking in C.
726
727 If this needs to handle any more variables it should be hacked
728 into something table driven.
729 */
730static char **fix_environment(char **origenv, const char *preload)
731{
732 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000733 static const char ld_preload[] = "LD_PRELOAD=";
734 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000735 static const int ld_preload_len = sizeof(ld_preload)-1;
736 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
737 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000738 char *inject_path;
739 int inject_path_len;
740 int vgliblen = strlen(VG_(libdir));
741 char **cpp;
742 char **ret;
743 int envc;
744 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
745
746 /* Find the vg_inject.so; also make room for the tool preload
747 library */
748 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
749 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000750 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000751
752 if (preload)
753 snprintf(inject_path, inject_path_len, "%s/%s:%s",
754 VG_(libdir), inject_so, preload);
755 else
756 snprintf(inject_path, inject_path_len, "%s/%s",
757 VG_(libdir), inject_so);
758
759 /* Count the original size of the env */
760 envc = 0; /* trailing NULL */
761 for (cpp = origenv; cpp && *cpp; cpp++)
762 envc++;
763
764 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000765 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000766 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000767
768 /* copy it over */
769 for (cpp = ret; *origenv; )
770 *cpp++ = *origenv++;
771 *cpp = NULL;
772
773 vg_assert(envc == (cpp - ret));
774
775 /* Walk over the new environment, mashing as we go */
776 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000777 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000778 int len = strlen(*cpp) + inject_path_len;
779 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000780 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000781
782 snprintf(cp, len, "%s%s:%s",
783 ld_preload, inject_path, (*cpp)+ld_preload_len);
784
785 *cpp = cp;
786
787 ld_preload_done = 1;
788 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
789 *cpp = "";
790 }
791 }
792
793 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000794 if (!ld_preload_done) {
795 int len = ld_preload_len + inject_path_len;
796 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000797 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000798
799 snprintf(cp, len, "%s%s",
800 ld_preload, inject_path);
801
802 ret[envc++] = cp;
803 }
804
sewardjb5f6f512005-03-10 23:59:00 +0000805 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000806 ret[envc] = NULL;
807
808 return ret;
809}
810
811extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000812
813/* Add a string onto the string table, and return its address */
814static char *copy_str(char **tab, const char *str)
815{
816 char *cp = *tab;
817 char *orig = cp;
818
819 while(*str)
820 *cp++ = *str++;
821 *cp++ = '\0';
822
823 if (0)
nethercote545fe672004-11-01 16:52:43 +0000824 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000825
826 *tab = cp;
827
828 return orig;
829}
830
831/*
832 This sets up the client's initial stack, containing the args,
833 environment and aux vector.
834
835 The format of the stack is:
836
837 higher address +-----------------+
838 | Trampoline code |
839 +-----------------+
840 | |
841 : string table :
842 | |
843 +-----------------+
844 | AT_NULL |
845 - -
846 | auxv |
847 +-----------------+
848 | NULL |
849 - -
850 | envp |
851 +-----------------+
852 | NULL |
853 - -
854 | argv |
855 +-----------------+
856 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000857 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000858 | undefined |
859 : :
860 */
nethercotec25c4492004-10-18 11:52:17 +0000861static Addr setup_client_stack(void* init_sp,
862 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000863 const struct exeinfo *info,
864 UInt** client_auxv)
865{
nethercotee567e702004-07-10 17:49:17 +0000866 void* res;
nethercote71980f02004-01-24 18:18:54 +0000867 char **cpp;
868 char *strtab; /* string table */
869 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000870 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000871 struct ume_auxv *auxv;
872 const struct ume_auxv *orig_auxv;
873 const struct ume_auxv *cauxv;
874 unsigned stringsize; /* total size of strings in bytes */
875 unsigned auxsize; /* total size of auxv in bytes */
876 int argc; /* total argc */
877 int envc; /* total number of env vars */
878 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000879 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000880
881 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000882 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000883
884 /* ==================== compute sizes ==================== */
885
886 /* first of all, work out how big the client stack will be */
887 stringsize = 0;
888
889 /* paste on the extra args if the loader needs them (ie, the #!
890 interpreter and its argument) */
891 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000892 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000893 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000894 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000895 }
nethercoted6a56872004-07-26 15:32:47 +0000896 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000897 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000898 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000899 }
900
901 /* now scan the args we're given... */
902 for (cpp = orig_argv; *cpp; cpp++) {
903 argc++;
904 stringsize += strlen(*cpp) + 1;
905 }
906
907 /* ...and the environment */
908 envc = 0;
909 for (cpp = orig_envp; cpp && *cpp; cpp++) {
910 envc++;
911 stringsize += strlen(*cpp) + 1;
912 }
913
914 /* now, how big is the auxv? */
915 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
916 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
917 if (cauxv->a_type == AT_PLATFORM)
918 stringsize += strlen(cauxv->u.a_ptr) + 1;
919 auxsize += sizeof(*cauxv);
920 }
921
922 /* OK, now we know how big the client stack is */
923 stacksize =
924 sizeof(int) + /* argc */
925 sizeof(char **)*argc + /* argv */
926 sizeof(char **) + /* terminal NULL */
927 sizeof(char **)*envc + /* envp */
928 sizeof(char **) + /* terminal NULL */
929 auxsize + /* auxv */
930 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000931 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000932
sewardj79048ce2005-02-18 08:28:32 +0000933 if (0) VG_(printf)("stacksize = %d\n", stacksize);
934
nethercotef84f6952004-07-15 14:58:33 +0000935 // decide where stack goes!
936 VG_(clstk_end) = VG_(client_end);
937
nethercote73b526f2004-10-31 18:48:21 +0000938 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000939
nethercote71980f02004-01-24 18:18:54 +0000940 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000941 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000942 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
943
nethercote71980f02004-01-24 18:18:54 +0000944 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000945 stringbase = strtab = (char *)(VG_(client_trampoline_code)
946 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000947
948 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000949
sewardj79048ce2005-02-18 08:28:32 +0000950 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000951 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000952 "clstk_base %p\n"
953 "clstk_end %p\n",
954 stringsize, auxsize, stacksize,
955 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000956
nethercote71980f02004-01-24 18:18:54 +0000957 /* ==================== allocate space ==================== */
958
959 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000960 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000961 PROT_READ | PROT_WRITE | PROT_EXEC,
962 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
963 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000964
965 /* ==================== copy client stack ==================== */
966
nethercotea3c3cf22004-11-01 18:38:00 +0000967 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000968
969 /* --- argc --- */
970 *ptr++ = argc; /* client argc */
971
972 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000973 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000974 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000975 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000976 }
nethercoted6a56872004-07-26 15:32:47 +0000977 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000978 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000979 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000980 }
981 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000982 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000983 }
984 *ptr++ = 0;
985
986 /* --- envp --- */
987 VG_(client_envp) = (Char **)ptr;
988 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000989 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000990 *ptr++ = 0;
991
992 /* --- auxv --- */
993 auxv = (struct ume_auxv *)ptr;
994 *client_auxv = (UInt *)auxv;
995
996 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
997 /* copy the entry... */
998 *auxv = *orig_auxv;
999
1000 /* ...and fix up the copy */
1001 switch(auxv->a_type) {
1002 case AT_PHDR:
1003 if (info->phdr == 0)
1004 auxv->a_type = AT_IGNORE;
1005 else
1006 auxv->u.a_val = info->phdr;
1007 break;
1008
1009 case AT_PHNUM:
1010 if (info->phdr == 0)
1011 auxv->a_type = AT_IGNORE;
1012 else
1013 auxv->u.a_val = info->phnum;
1014 break;
1015
1016 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001017 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001018 break;
1019
1020 case AT_PLATFORM: /* points to a platform description string */
1021 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1022 break;
1023
1024 case AT_ENTRY:
1025 auxv->u.a_val = info->entry;
1026 break;
1027
1028 case AT_IGNORE:
1029 case AT_EXECFD:
1030 case AT_PHENT:
1031 case AT_PAGESZ:
1032 case AT_FLAGS:
1033 case AT_NOTELF:
1034 case AT_UID:
1035 case AT_EUID:
1036 case AT_GID:
1037 case AT_EGID:
1038 case AT_CLKTCK:
1039 case AT_HWCAP:
1040 case AT_FPUCW:
1041 case AT_DCACHEBSIZE:
1042 case AT_ICACHEBSIZE:
1043 case AT_UCACHEBSIZE:
1044 /* All these are pointerless, so we don't need to do anything
1045 about them. */
1046 break;
1047
1048 case AT_SECURE:
1049 /* If this is 1, then it means that this program is running
1050 suid, and therefore the dynamic linker should be careful
1051 about LD_PRELOAD, etc. However, since stage1 (the thing
1052 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001053 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001054 set AT_SECURE to 0. */
1055 auxv->u.a_val = 0;
1056 break;
1057
1058 case AT_SYSINFO:
1059 /* Leave this unmolested for now, but we'll update it later
1060 when we set up the client trampoline code page */
1061 break;
1062
1063 case AT_SYSINFO_EHDR:
1064 /* Trash this, because we don't reproduce it */
1065 auxv->a_type = AT_IGNORE;
1066 break;
1067
1068 default:
1069 /* stomp out anything we don't know about */
1070 if (0)
nethercote545fe672004-11-01 16:52:43 +00001071 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001072 auxv->a_type = AT_IGNORE;
1073 break;
1074
1075 }
1076 }
1077 *auxv = *orig_auxv;
1078 vg_assert(auxv->a_type == AT_NULL);
1079
njnc6168192004-11-29 13:54:10 +00001080// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1081// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001082#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001083 /* --- trampoline page --- */
1084 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1085 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001086#endif
nethercotef84f6952004-07-15 14:58:33 +00001087
nethercote71980f02004-01-24 18:18:54 +00001088 vg_assert((strtab-stringbase) == stringsize);
1089
nethercote5ee67ca2004-06-22 14:00:09 +00001090 /* We know the initial ESP is pointing at argc/argv */
1091 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001092 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001093
sewardj79048ce2005-02-18 08:28:32 +00001094 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001095 return cl_esp;
1096}
1097
1098/*====================================================================*/
1099/*=== Find executable ===*/
1100/*====================================================================*/
1101
thughes4ad52d02004-06-27 17:37:21 +00001102static const char* executable_name;
1103
1104static Bool match_executable(const char *entry) {
1105 char buf[strlen(entry) + strlen(executable_name) + 2];
1106
1107 /* empty PATH element means . */
1108 if (*entry == '\0')
1109 entry = ".";
1110
1111 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1112
1113 if (access(buf, R_OK|X_OK) == 0) {
1114 executable_name = strdup(buf);
1115 vg_assert(NULL != executable_name);
1116 return True;
1117 }
1118 return False;
1119}
1120
nethercote71980f02004-01-24 18:18:54 +00001121static const char* find_executable(const char* exec)
1122{
1123 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001124 executable_name = exec;
1125 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001126 /* no '/' - we need to search the path */
1127 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001128 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001129 }
thughes4ad52d02004-06-27 17:37:21 +00001130 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001131}
1132
1133
1134/*====================================================================*/
1135/*=== Loading tools ===*/
1136/*====================================================================*/
1137
1138static void list_tools(void)
1139{
1140 DIR *dir = opendir(VG_(libdir));
1141 struct dirent *de;
1142 int first = 1;
1143
1144 if (dir == NULL) {
1145 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001146 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001147 return;
1148 }
1149
nethercotef4928da2004-06-15 10:54:40 +00001150 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001151 int len = strlen(de->d_name);
1152
njn063c5402004-11-22 16:58:05 +00001153 /* look for vgtool_TOOL.so names */
1154 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1155 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001156 VG_STREQ(de->d_name + len - 3, ".so")) {
1157 if (first) {
1158 fprintf(stderr, "Available tools:\n");
1159 first = 0;
1160 }
1161 de->d_name[len-3] = '\0';
1162 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001163 }
1164 }
1165
1166 closedir(dir);
1167
1168 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001169 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1170 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001171}
1172
1173
1174/* Find and load a tool, and check it looks ok. Also looks to see if there's
1175 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1176static void load_tool( const char *toolname, void** handle_out,
1177 ToolInfo** toolinfo_out, char **preloadpath_out )
1178{
1179 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001180 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001181 char buf[len];
1182 void* handle;
1183 ToolInfo* toolinfo;
1184 char* preloadpath = NULL;
1185 Int* vg_malloc_redzonep;
1186
1187 // XXX: allowing full paths for --tool option -- does it make sense?
1188 // Doesn't allow for vgpreload_<tool>.so.
1189
1190 if (strchr(toolname, '/') != 0) {
1191 /* toolname contains '/', and so must be a pathname */
1192 handle = dlopen(toolname, RTLD_NOW);
1193 } else {
1194 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001195 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001196 handle = dlopen(buf, RTLD_NOW);
1197
1198 if (handle != NULL) {
1199 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1200 if (access(buf, R_OK) == 0) {
1201 preloadpath = strdup(buf);
1202 vg_assert(NULL != preloadpath);
1203 }
1204 }
1205 }
1206
1207 ok = (NULL != handle);
1208 if (!ok) {
1209 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1210 goto bad_load;
1211 }
1212
njn26f02512004-11-22 18:33:15 +00001213 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001214 ok = (NULL != toolinfo);
1215 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001216 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001217 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1218 goto bad_load;
1219 }
1220
1221 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1222 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001223 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001224 if (!ok) {
1225 fprintf(stderr, "Error:\n"
1226 " Tool and core interface versions do not match.\n"
1227 " Interface version used by core is: %d.%d (size %d)\n"
1228 " Interface version used by tool is: %d.%d (size %d)\n"
1229 " The major version numbers must match.\n",
1230 VG_CORE_INTERFACE_MAJOR_VERSION,
1231 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001232 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001233 toolinfo->interface_major_version,
1234 toolinfo->interface_minor_version,
1235 toolinfo->sizeof_ToolInfo);
1236 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1237 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001238 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001239 else
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 goto bad_load;
1242 }
1243
1244 // Set redzone size for V's allocator
1245 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1246 if ( NULL != vg_malloc_redzonep ) {
1247 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1248 }
1249
1250 vg_assert(NULL != handle && NULL != toolinfo);
1251 *handle_out = handle;
1252 *toolinfo_out = toolinfo;
1253 *preloadpath_out = preloadpath;
1254 return;
1255
1256
1257 bad_load:
1258 if (handle != NULL)
1259 dlclose(handle);
1260
nethercotef4928da2004-06-15 10:54:40 +00001261 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001262 list_tools();
1263 exit(127);
1264}
1265
nethercotef4928da2004-06-15 10:54:40 +00001266
1267/*====================================================================*/
1268/*=== Command line errors ===*/
1269/*====================================================================*/
1270
1271static void abort_msg ( void )
1272{
nethercotef8548672004-06-21 12:42:35 +00001273 VG_(clo_log_to) = VgLogTo_Fd;
1274 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001275}
1276
1277void VG_(bad_option) ( Char* opt )
1278{
1279 abort_msg();
1280 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1281 VG_(printf)("valgrind: Use --help for more information.\n");
1282 VG_(exit)(1);
1283}
1284
nethercotef4928da2004-06-15 10:54:40 +00001285static void missing_prog ( void )
1286{
1287 abort_msg();
1288 VG_(printf)("valgrind: no program specified\n");
1289 VG_(printf)("valgrind: Use --help for more information.\n");
1290 VG_(exit)(1);
1291}
1292
1293static void config_error ( Char* msg )
1294{
1295 abort_msg();
1296 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1297 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1298 VG_(exit)(1);
1299}
1300
1301
nethercote71980f02004-01-24 18:18:54 +00001302/*====================================================================*/
1303/*=== Loading the client ===*/
1304/*====================================================================*/
1305
nethercotef4928da2004-06-15 10:54:40 +00001306static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001307 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1308{
1309 // If they didn't specify an executable with --exec, and didn't specify
1310 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001311 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001312 if (cl_argv[0] == NULL ||
1313 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1314 {
nethercotef4928da2004-06-15 10:54:40 +00001315 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001316 }
1317 }
1318
1319 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001320 info->exe_base = VG_(client_base);
1321 info->exe_end = VG_(client_end);
1322 info->argv = cl_argv;
1323
nethercotef4928da2004-06-15 10:54:40 +00001324 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001325 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001326 // Totally zero 'info' before continuing.
1327 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001328 } else {
1329 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001330 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001331 ret = do_exec(exec, info);
1332 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001333 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1334 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001335 exit(127);
1336 }
1337 }
1338
1339 /* Copy necessary bits of 'info' that were filled in */
1340 *client_eip = info->init_eip;
1341 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1342}
1343
nethercote969ecf12004-10-13 17:29:01 +00001344/*====================================================================*/
1345/*=== Address space unpadding ===*/
1346/*====================================================================*/
1347
1348typedef struct {
1349 char* killpad_start;
1350 char* killpad_end;
1351 struct stat* killpad_padstat;
1352} killpad_extra;
1353
1354static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1355 int maj, int min, int ino, void* ex)
1356{
1357 killpad_extra* extra = ex;
1358 void *b, *e;
1359 int res;
1360
1361 vg_assert(NULL != extra->killpad_padstat);
1362
1363 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1364 extra->killpad_padstat->st_ino != ino)
1365 return 1;
1366
1367 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1368 return 1;
1369
1370 if (segstart <= extra->killpad_start)
1371 b = extra->killpad_start;
1372 else
1373 b = segstart;
1374
1375 if (segend >= extra->killpad_end)
1376 e = extra->killpad_end;
1377 else
1378 e = segend;
1379
1380 res = munmap(b, (char *)e-(char *)b);
1381 vg_assert(0 == res);
1382
1383 return 1;
1384}
1385
1386// Remove padding of 'padfile' from a range of address space.
1387void as_unpad(void *start, void *end, int padfile)
1388{
1389 static struct stat padstat;
1390 killpad_extra extra;
1391 int res;
1392
sewardjb5f6f512005-03-10 23:59:00 +00001393 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001394
1395 res = fstat(padfile, &padstat);
1396 vg_assert(0 == res);
1397 extra.killpad_padstat = &padstat;
1398 extra.killpad_start = start;
1399 extra.killpad_end = end;
1400 foreach_map(killpad, &extra);
1401}
1402
1403void as_closepadfile(int padfile)
1404{
1405 int res = close(padfile);
1406 vg_assert(0 == res);
1407}
1408
nethercote71980f02004-01-24 18:18:54 +00001409
1410/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001411/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001412/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001413
njn25e49d8e72002-09-23 09:36:25 +00001414/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001415VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001416Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001417Bool VG_(clo_db_attach) = False;
1418Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001419Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001420Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001421Int VG_(clo_verbosity) = 1;
1422Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001423Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001424
nethercotef1e5e152004-09-01 23:58:16 +00001425/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001426 fd is initially stdout, for --help, but gets moved to stderr by default
1427 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001428VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001429Int VG_(clo_log_fd) = 1;
1430Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001431
thughes6233a382004-08-21 11:10:44 +00001432Bool VG_(clo_time_stamp) = False;
1433
sewardj6024b212003-07-13 10:54:33 +00001434Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001435Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001436Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001437Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001438UChar VG_(clo_trace_flags) = 0; // 00000000b
1439UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001440Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001441Bool VG_(clo_trace_syscalls) = False;
1442Bool VG_(clo_trace_signals) = False;
1443Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001444Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001445Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001446Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001447Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001448Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001449Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001450Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001451Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001452Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001453Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001454Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001455Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001456Bool VG_(clo_model_pthreads) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001457
jsgf855d93d2003-10-13 22:26:55 +00001458static Bool VG_(clo_wait_for_gdb) = False;
1459
sewardjde4a1d02002-03-22 01:27:54 +00001460
nethercote6c999f22004-01-31 22:55:15 +00001461void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001462{
njn25e49d8e72002-09-23 09:36:25 +00001463 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001464"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001465"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001466" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001467" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001468" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001469" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001470" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001471" -q --quiet run silently; only print error msgs\n"
1472" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001473" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001474" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001475" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001476"\n"
1477" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001478" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001479" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001480" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001481" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001482"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001484" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1485" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001486" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001487" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001488" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1489" --num-callers=<number> show <num> callers in stack traces [4]\n"
1490" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1491" --show-below-main=no|yes continue stack traces below main() [no]\n"
1492" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001493" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001494" --db-attach=no|yes start debugger when errors detected? [no]\n"
1495" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1496" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001497"\n";
njn7cf0bd32002-06-08 13:36:03 +00001498
njn25e49d8e72002-09-23 09:36:25 +00001499 Char* usage2 =
1500"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001501" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001502" --sanity-level=<number> level of sanity checking to do [1]\n"
1503" --single-step=no|yes translate each instr separately? [no]\n"
1504" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001505" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001506" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001507" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1508" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001509" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001510" --trace-syscalls=no|yes show all system calls? [no]\n"
1511" --trace-signals=no|yes show signal handling details? [no]\n"
1512" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001513" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001514" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001515#if 0
1516" --model-pthreads=yes|no model the pthreads library [no]\n"
1517#endif
1518" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001519"\n"
1520" --vex-iropt-verbosity 0 .. 9 [0]\n"
1521" --vex-iropt-level 0 .. 2 [2]\n"
1522" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001523" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1524" --vex-guest-max-insns 1 .. 100 [50]\n"
1525" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1526"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001527" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001528" 1000 0000 show conversion into IR\n"
1529" 0100 0000 show after initial opt\n"
1530" 0010 0000 show after instrumentation\n"
1531" 0001 0000 show after second opt\n"
1532" 0000 1000 show after tree building\n"
1533" 0000 0100 show selecting insns\n"
1534" 0000 0010 show after reg-alloc\n"
1535" 0000 0001 show final assembly\n"
1536"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" debugging options for Valgrind tools that report errors\n"
1538" --dump-error=<number> show translation for basic block associated\n"
1539" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001540"\n";
njn3e884182003-04-15 13:03:23 +00001541
1542 Char* usage3 =
1543"\n"
nethercote71980f02004-01-24 18:18:54 +00001544" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001546" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001547" and licensed under the GNU General Public License, version 2.\n"
1548" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001549"\n"
nethercote137bc552003-11-14 17:47:54 +00001550" Tools are copyright and licensed by their authors. See each\n"
1551" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001552"\n";
njn7cf0bd32002-06-08 13:36:03 +00001553
fitzhardinge98abfc72003-12-16 02:05:15 +00001554 VG_(printf)(usage1);
1555 if (VG_(details).name) {
1556 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001557 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001558 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001559 else
1560 VG_(printf)(" (none)\n");
1561 }
nethercote6c999f22004-01-31 22:55:15 +00001562 if (debug_help) {
1563 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001564
nethercote6c999f22004-01-31 22:55:15 +00001565 if (VG_(details).name) {
1566 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1567
1568 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001569 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001570 else
1571 VG_(printf)(" (none)\n");
1572 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001573 }
nethercote421281e2003-11-20 16:20:55 +00001574 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001575 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001576}
sewardjde4a1d02002-03-22 01:27:54 +00001577
nethercote71980f02004-01-24 18:18:54 +00001578static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001579 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001580{
nethercote71980f02004-01-24 18:18:54 +00001581 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001582
sewardj8b635a42004-11-22 19:01:47 +00001583 LibVEX_default_VexControl(& VG_(clo_vex_control));
1584
nethercote71980f02004-01-24 18:18:54 +00001585 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001586 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001589 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001590 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1593 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001594 *need_help = 1;
1595
nethercotef6a1d502004-08-09 12:21:57 +00001596 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001597 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001598
nethercotef6c99d72004-11-09 14:35:43 +00001599 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001600 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001601
nethercotef6a1d502004-08-09 12:21:57 +00001602 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1603 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001604 }
1605 }
nethercote71980f02004-01-24 18:18:54 +00001606}
1607
nethercote5ee67ca2004-06-22 14:00:09 +00001608static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001609{
nethercotef8548672004-06-21 12:42:35 +00001610 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001611 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001612
nethercotee1730692003-11-20 10:38:07 +00001613 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001614 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001615
sewardj19d81412002-06-03 01:10:40 +00001616 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001618 config_error("Please use absolute paths in "
1619 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001620
njnc6168192004-11-29 13:54:10 +00001621// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001622#ifdef __x86__
1623 {
sewardjb5f6f512005-03-10 23:59:00 +00001624 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001625 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1626 switch(auxp[0]) {
1627 case AT_SYSINFO:
1628 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1629 break;
1630 }
1631 }
1632 }
1633#endif
sewardjde4a1d02002-03-22 01:27:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001638 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001639
thughes3bfd5a02004-07-18 08:05:44 +00001640 /* Look for a colon in the switch name */
1641 while (*colon && *colon != ':' && *colon != '=')
1642 colon++;
nethercote71980f02004-01-24 18:18:54 +00001643
1644 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001645 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001646 if (VG_CLO_STREQN(2, arg, "--") &&
1647 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1648 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1649 {
1650 // prefix matches, convert "--toolname:foo" to "--foo"
1651 if (0)
1652 VG_(printf)("tool-specific arg: %s\n", arg);
1653 arg += toolname_len + 1;
1654 arg[0] = '-';
1655 arg[1] = '-';
1656
1657 } else {
1658 // prefix doesn't match, skip to next arg
1659 continue;
1660 }
1661 }
1662
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001664 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 continue;
nethercote71980f02004-01-24 18:18:54 +00001666 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001667 continue;
sewardjb5f6f512005-03-10 23:59:00 +00001668 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
1669 continue;
fitzhardinge98abfc72003-12-16 02:05:15 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001672 continue;
nethercote27fec902004-06-16 21:26:32 +00001673
nethercote71980f02004-01-24 18:18:54 +00001674 else if (VG_CLO_STREQ(arg, "-v") ||
1675 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001676 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 else if (VG_CLO_STREQ(arg, "-q") ||
1679 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001680 VG_(clo_verbosity)--;
1681
nethercote27fec902004-06-16 21:26:32 +00001682 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001683 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1684 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1685 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001686 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001687 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
nethercote27fec902004-06-16 21:26:32 +00001688 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1689 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1690 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001691 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001692 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1693 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1694 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1695 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1696 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001697 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001698 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001699 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001700 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001701 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001702
nethercote27fec902004-06-16 21:26:32 +00001703 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1704 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001705
nethercote27fec902004-06-16 21:26:32 +00001706 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1707 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1708 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001709 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1710 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001711
sewardj8b635a42004-11-22 19:01:47 +00001712 else VG_BNUM_CLO("--vex-iropt-verbosity",
1713 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1714 else VG_BNUM_CLO("--vex-iropt-level",
1715 VG_(clo_vex_control).iropt_level, 0, 2)
1716 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1717 VG_(clo_vex_control).iropt_precise_memory_exns)
1718 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1719 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1720 else VG_BNUM_CLO("--vex-guest-max-insns",
1721 VG_(clo_vex_control).guest_max_insns, 1, 100)
1722 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1723 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1724
nethercotef8548672004-06-21 12:42:35 +00001725 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001726 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001727 VG_(clo_log_to) = VgLogTo_Fd;
1728 VG_(clo_log_name) = NULL;
1729 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1730 }
1731 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1732 VG_(clo_log_to) = VgLogTo_Fd;
1733 VG_(clo_log_name) = NULL;
1734 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001735 }
1736
nethercotef8548672004-06-21 12:42:35 +00001737 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001738 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001739 VG_(clo_log_to) = VgLogTo_File;
1740 VG_(clo_log_name) = &arg[10];
1741 }
1742 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1743 VG_(clo_log_to) = VgLogTo_File;
1744 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001745 }
sewardj603d4102005-01-11 14:01:02 +00001746 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1747 VG_(clo_log_to) = VgLogTo_FileExactly;
1748 VG_(clo_log_name) = &arg[19];
1749 }
sewardjde4a1d02002-03-22 01:27:54 +00001750
nethercotef8548672004-06-21 12:42:35 +00001751 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001753 VG_(clo_log_to) = VgLogTo_Socket;
1754 VG_(clo_log_name) = &arg[12];
1755 }
1756 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1757 VG_(clo_log_to) = VgLogTo_Socket;
1758 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001759 }
1760
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001762 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001763 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001764 VG_(message)(Vg_UserMsg,
1765 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001767 }
nethercote71980f02004-01-24 18:18:54 +00001768 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(clo_n_suppressions)++;
1770 }
sewardjde4a1d02002-03-22 01:27:54 +00001771
sewardjfa8ec112005-01-19 11:55:34 +00001772 /* "stuvwxyz" --> stuvwxyz (binary) */
1773 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1774 Int j;
1775 char* opt = & arg[14];
1776
1777 if (8 != VG_(strlen)(opt)) {
1778 VG_(message)(Vg_UserMsg,
1779 "--trace-flags argument must have 8 digits");
1780 VG_(bad_option)(arg);
1781 }
1782 for (j = 0; j < 8; j++) {
1783 if ('0' == opt[j]) { /* do nothing */ }
1784 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1785 else {
1786 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1787 "contain 0s and 1s");
1788 VG_(bad_option)(arg);
1789 }
1790 }
1791 }
1792
1793 /* "stuvwxyz" --> stuvwxyz (binary) */
1794 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001795 Int j;
nethercote71980f02004-01-24 18:18:54 +00001796 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001797
sewardj2a99cf62004-11-24 10:44:19 +00001798 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001799 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001800 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001802 }
sewardj8b635a42004-11-22 19:01:47 +00001803 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001804 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001805 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001806 else {
sewardjfa8ec112005-01-19 11:55:34 +00001807 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001808 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
1811 }
1812 }
sewardjde4a1d02002-03-22 01:27:54 +00001813
sewardjc771b292004-11-30 18:55:21 +00001814 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1815
sewardjd153fae2005-01-10 17:24:47 +00001816 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1817 VG_(clo_gen_suppressions) = 0;
1818 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1819 VG_(clo_gen_suppressions) = 1;
1820 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1821 VG_(clo_gen_suppressions) = 2;
1822
nethercote71980f02004-01-24 18:18:54 +00001823 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001824 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001825 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001826 }
sewardjde4a1d02002-03-22 01:27:54 +00001827 }
1828
sewardj998d40d2004-12-06 14:24:52 +00001829 /* Make VEX control parameters sane */
1830
1831 if (VG_(clo_vex_control).guest_chase_thresh
1832 >= VG_(clo_vex_control).guest_max_insns)
1833 VG_(clo_vex_control).guest_chase_thresh
1834 = VG_(clo_vex_control).guest_max_insns - 1;
1835
1836 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1837 VG_(clo_vex_control).guest_chase_thresh = 0;
1838
1839 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001840
njnf9ebf672003-05-12 21:41:30 +00001841 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001842 VG_(clo_verbosity) = 0;
1843
nethercote04d0fbc2004-01-26 16:48:06 +00001844 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001845 VG_(message)(Vg_UserMsg, "");
1846 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001847 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001848 VG_(message)(Vg_UserMsg,
1849 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001850 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001851 }
1852
nethercotef8548672004-06-21 12:42:35 +00001853 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001854 should be connected to whatever sink has been selected, and we
1855 indiscriminately chuck stuff into it without worrying what the
1856 nature of it is. Oh the wonder of Unix streams. */
1857
nethercotee1730692003-11-20 10:38:07 +00001858 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001859 the terminal any problems to do with processing command line
1860 opts. */
nethercotef8548672004-06-21 12:42:35 +00001861 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001862 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001863
1864 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001865
sewardj4cf05692002-10-27 20:28:29 +00001866 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001867 vg_assert(VG_(clo_log_name) == NULL);
1868 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001869 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001870
sewardj4cf05692002-10-27 20:28:29 +00001871 case VgLogTo_File: {
1872 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001873 Int seq = 0;
1874 Int pid = VG_(getpid)();
1875
nethercotef8548672004-06-21 12:42:35 +00001876 vg_assert(VG_(clo_log_name) != NULL);
1877 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001878
nethercote71980f02004-01-24 18:18:54 +00001879 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001880 if (seq == 0)
1881 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001882 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001883 else
1884 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001885 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001886 seq++;
1887
nethercotef8548672004-06-21 12:42:35 +00001888 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001889 = VG_(open)(logfilename,
1890 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1891 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001892 if (eventually_log_fd >= 0) {
1893 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001894 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001895 } else {
nethercotef8548672004-06-21 12:42:35 +00001896 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001897 VG_(message)(Vg_UserMsg,
1898 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001899 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001900 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001901 "--log-file=<file> (didn't work out for some reason.)");
1902 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001903 }
1904 }
1905 }
sewardj603d4102005-01-11 14:01:02 +00001906 break; /* switch (VG_(clo_log_to)) */
1907 }
1908
1909 case VgLogTo_FileExactly: {
1910 Char logfilename[1000];
1911
1912 vg_assert(VG_(clo_log_name) != NULL);
1913 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1914 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1915
1916 eventually_log_fd
1917 = VG_(open)(logfilename,
1918 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1919 VKI_S_IRUSR|VKI_S_IWUSR);
1920 if (eventually_log_fd >= 0) {
1921 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1922 }
1923 else if (eventually_log_fd != -VKI_EEXIST) {
1924 VG_(message)(Vg_UserMsg,
1925 "Can't create/open log file `%s'; giving up!",
1926 VG_(clo_log_name));
1927 VG_(bad_option)(
1928 "--log-file-exactly=<file> (didn't work out for some reason.)");
1929 /*NOTREACHED*/
1930 }
1931 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001932 }
1933
1934 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001935 vg_assert(VG_(clo_log_name) != NULL);
1936 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1937 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1938 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001939 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001940 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001941 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001942 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001943 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001944 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001945 }
nethercotef8548672004-06-21 12:42:35 +00001946 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001947 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001948 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001949 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001950 VG_(message)(Vg_UserMsg,
1951 "Log messages will sent to stderr instead." );
1952 VG_(message)(Vg_UserMsg,
1953 "" );
1954 /* We don't change anything here. */
1955 } else {
nethercotef8548672004-06-21 12:42:35 +00001956 vg_assert(eventually_log_fd > 0);
1957 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001958 VG_(logging_to_filedes) = False;
1959 }
sewardj73cf3bc2002-11-03 03:20:15 +00001960 break;
1961 }
1962
sewardj4cf05692002-10-27 20:28:29 +00001963 }
1964
nethercotef8548672004-06-21 12:42:35 +00001965 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001966 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001967 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001968 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1969 else {
nethercotef8548672004-06-21 12:42:35 +00001970 VG_(clo_log_fd) = eventually_log_fd;
1971 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001972 }
1973
sewardj4cf05692002-10-27 20:28:29 +00001974 /* Ok, the logging sink is running now. Print a suitable preamble.
1975 If logging to file or a socket, write details of parent PID and
1976 command line args, to help people trying to interpret the
1977 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001978
sewardj83adf412002-05-01 01:25:45 +00001979 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001980 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001981 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001982 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001983 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001984 NULL == VG_(details).version
1985 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001986 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001987 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001988
njnd04b7c62002-10-03 14:05:52 +00001989 /* Core details */
1990 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001991 "Using LibVEX rev %s, a library for dynamic binary translation.",
1992 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001993 VG_(message)(Vg_UserMsg,
1994 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1995 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001996 "Using valgrind-%s, a dynamic binary instrumentation framework.",
sewardj5a1feda2004-12-17 19:18:02 +00001997 /*VERSION*/ "SVN >= 3207");
sewardjde4a1d02002-03-22 01:27:54 +00001998 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001999 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002000 }
2001
nethercotec1e395d2003-11-10 13:26:49 +00002002 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002003 VG_(message)(Vg_UserMsg, "");
2004 VG_(message)(Vg_UserMsg,
2005 "My PID = %d, parent PID = %d. Prog and args are:",
2006 VG_(getpid)(), VG_(getppid)() );
2007 for (i = 0; i < VG_(client_argc); i++)
2008 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2009 }
2010
sewardjde4a1d02002-03-22 01:27:54 +00002011 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002012 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002013 if (VG_(clo_log_to) != VgLogTo_Fd)
2014 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002015 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002016 VG_(message)(Vg_UserMsg, "Command line");
2017 for (i = 0; i < VG_(client_argc); i++)
2018 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2019
sewardjde4a1d02002-03-22 01:27:54 +00002020 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002021 for (i = 1; i < vg_argc; i++) {
2022 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002023 }
nethercotea70f7352004-04-18 12:08:46 +00002024
2025 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2026 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2027 if (fd < 0) {
2028 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2029 } else {
2030 #define BUF_LEN 256
2031 Char version_buf[BUF_LEN];
2032 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2033 vg_assert(n <= 256);
2034 if (n > 0) {
2035 version_buf[n-1] = '\0';
2036 VG_(message)(Vg_UserMsg, " %s", version_buf);
2037 } else {
2038 VG_(message)(Vg_UserMsg, " (empty?)");
2039 }
2040 VG_(close)(fd);
2041 #undef BUF_LEN
2042 }
sewardjde4a1d02002-03-22 01:27:54 +00002043 }
2044
fitzhardinge98abfc72003-12-16 02:05:15 +00002045 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002046 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002047 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002048 needs one, load the default */
2049 static const Char default_supp[] = "default.supp";
2050 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2051 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2052 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2053 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2054 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002055 }
sewardj4cf05692002-10-27 20:28:29 +00002056
sewardjd153fae2005-01-10 17:24:47 +00002057 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002058 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002059 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002060 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002061 VG_(message)(Vg_UserMsg,
2062 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002063 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002064 }
sewardjde4a1d02002-03-22 01:27:54 +00002065}
2066
nethercotef6a1d502004-08-09 12:21:57 +00002067// Build the string for VALGRINDCLO.
2068Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2069{
2070 /* If we're tracing the children, then we need to start it
2071 with our starter+arguments, which are copied into VALGRINDCLO,
2072 except the --exec= option is changed if present.
2073 */
2074 Int i;
2075 Char *exec;
2076 Char *cp;
2077 Char *optvar;
2078 Int optlen, execlen;
2079
2080 // All these allocated blocks are not free - because we're either
2081 // going to exec, or panic when we fail.
2082
2083 // Create --exec= option: "--exec=<exename>"
2084 exec = VG_(arena_malloc)(VG_AR_CORE,
2085 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2086 vg_assert(NULL != exec);
2087 VG_(sprintf)(exec, "--exec=%s", exename);
2088
2089 // Allocate space for optvar (may overestimate by counting --exec twice,
2090 // no matter)
2091 optlen = 1;
2092 for (i = 0; i < vg_argc; i++)
2093 optlen += VG_(strlen)(vg_argv[i]) + 1;
2094 optlen += VG_(strlen)(exec)+1;
2095 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2096
2097 // Copy all valgrind args except the old --exec (if present)
2098 // VG_CLO_SEP is the separator.
2099 cp = optvar;
2100 for (i = 1; i < vg_argc; i++) {
2101 Char *arg = vg_argv[i];
2102
2103 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2104 // don't copy existing --exec= arg
2105 } else if (VG_(strcmp)(arg, "--") == 0) {
2106 // stop at "--"
2107 break;
2108 } else {
2109 // copy non "--exec" arg
2110 Int len = VG_(strlen)(arg);
2111 VG_(memcpy)(cp, arg, len);
2112 cp += len;
2113 *cp++ = VG_CLO_SEP;
2114 }
2115 }
2116 // Add the new --exec= option
2117 execlen = VG_(strlen)(exec);
2118 VG_(memcpy)(cp, exec, execlen);
2119 cp += execlen;
2120 *cp++ = VG_CLO_SEP;
2121
2122 *cp = '\0';
2123
2124 return optvar;
2125}
2126
2127// Build "/proc/self/fd/<execfd>".
2128Char* VG_(build_child_exename)( void )
2129{
2130 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2131 vg_assert(NULL != exename);
2132 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2133 return exename;
2134}
2135
sewardjde4a1d02002-03-22 01:27:54 +00002136
nethercote71980f02004-01-24 18:18:54 +00002137/*====================================================================*/
2138/*=== File descriptor setup ===*/
2139/*====================================================================*/
2140
2141static void setup_file_descriptors(void)
2142{
2143 struct vki_rlimit rl;
2144
2145 /* Get the current file descriptor limits. */
2146 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2147 rl.rlim_cur = 1024;
2148 rl.rlim_max = 1024;
2149 }
2150
2151 /* Work out where to move the soft limit to. */
2152 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2153 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2154 } else {
2155 rl.rlim_cur = rl.rlim_max;
2156 }
2157
2158 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002159 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2160 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002161
2162 /* Update the soft limit. */
2163 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2164
nethercotef6a1d502004-08-09 12:21:57 +00002165 if (vgexecfd != -1)
2166 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002167 if (VG_(clexecfd) != -1)
2168 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2169}
2170
nethercote71980f02004-01-24 18:18:54 +00002171/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002172/*=== Initialise program data/text, etc. ===*/
2173/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002174
sewardjb5f6f512005-03-10 23:59:00 +00002175static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2176 UInt dev, UInt ino, ULong foffset,
2177 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002178{
nethercote71980f02004-01-24 18:18:54 +00002179 /* Only record valgrind mappings for now, without loading any
2180 symbols. This is so we know where the free space is before we
2181 start allocating more memory (note: heap is OK, it's just mmap
2182 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002183 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2184 if (0)
2185 VG_(printf)("init1: %p-%p prot %s\n",
2186 start, start+size, VG_(prot_str)(prot));
2187 VG_(map_file_segment)(start, size, prot,
2188 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2189 dev, ino, foffset, filename);
2190 /* update VG_(valgrind_last) if it looks wrong */
2191 if (start+size > VG_(valgrind_last))
2192 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002193 }
sewardjde4a1d02002-03-22 01:27:54 +00002194}
2195
nethercote71980f02004-01-24 18:18:54 +00002196// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002197Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002198
sewardjb5f6f512005-03-10 23:59:00 +00002199/*
2200 This second pass adds in client mappings, and loads symbol tables
2201 for all interesting mappings. The trouble is that things can
2202 change as we go, because we're calling the Tool to track memory as
2203 we find it.
2204
2205 So for Valgrind mappings, we don't replace any mappings which
2206 aren't still identical (which will include the .so mappings, so we
2207 will load their symtabs)>
2208 */
2209static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2210 UInt dev, UInt ino, ULong foffset,
2211 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002212{
nethercote71980f02004-01-24 18:18:54 +00002213 UInt flags;
2214 Bool is_stack_segment;
2215 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002216
nethercote71980f02004-01-24 18:18:54 +00002217 is_stack_segment
2218 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002219
sewardjb5f6f512005-03-10 23:59:00 +00002220 if (0)
2221 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2222 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 if (is_stack_segment)
2225 flags = SF_STACK | SF_GROWDOWN;
2226 else
2227 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002228
nethercote71980f02004-01-24 18:18:54 +00002229 if (filename != NULL)
2230 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
sewardjb5f6f512005-03-10 23:59:00 +00002232#if 0
2233 // This needs to be fixed properly. jrs 20050307
2234 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2235 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002236
sewardjb5f6f512005-03-10 23:59:00 +00002237 /* We have to be a bit careful about inserting new mappings into
2238 the Valgrind part of the address space. We're actively
2239 changing things as we parse these mappings, particularly in
2240 shadow memory, and so we don't want to overwrite those
2241 changes. Therefore, we only insert/update a mapping if it is
2242 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002243
sewardjb5f6f512005-03-10 23:59:00 +00002244 NOTE: we're only talking about the Segment list mapping
2245 metadata; this doesn't actually mmap anything more. */
2246 if (filename || (s && s->addr == start && s->len == size)) {
2247 flags |= SF_VALGRIND;
2248 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2249 } else {
2250 /* assert range is already mapped */
2251 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2252 }
2253 } else
2254#endif
2255 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2256
2257 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2258 VG_TRACK( new_mem_startup, start, size,
2259 !!(prot & VKI_PROT_READ),
2260 !!(prot & VKI_PROT_WRITE),
2261 !!(prot & VKI_PROT_EXEC));
2262 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002263
nethercote71980f02004-01-24 18:18:54 +00002264 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002265 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002266 vg_assert(0 != r_esp);
2267 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002268 if (0) {
2269 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002270 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002271 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2272 r_esp, start+size);
2273 }
nethercote71980f02004-01-24 18:18:54 +00002274 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002275 // what's this for?
2276 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002277 }
sewardjde4a1d02002-03-22 01:27:54 +00002278}
2279
2280
nethercote71980f02004-01-24 18:18:54 +00002281/*====================================================================*/
2282/*=== Sanity check machinery (permanently engaged) ===*/
2283/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002284
2285/* A fast sanity check -- suitable for calling circa once per
2286 millisecond. */
2287
nethercote885dd912004-08-03 23:14:00 +00002288void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002289{
sewardjb5f6f512005-03-10 23:59:00 +00002290 ThreadId tid;
2291
njn37cea302002-09-30 11:24:00 +00002292 VGP_PUSHCC(VgpCoreCheapSanity);
2293
nethercote27fec902004-06-16 21:26:32 +00002294 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002295
2296 /* --- First do all the tests that we can do quickly. ---*/
2297
nethercote297effd2004-08-02 15:07:57 +00002298 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002299
njn25e49d8e72002-09-23 09:36:25 +00002300 /* Check stuff pertaining to the memory check system. */
2301
2302 /* Check that nobody has spuriously claimed that the first or
2303 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002304 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002305 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002306 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002307 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002308 }
njn25e49d8e72002-09-23 09:36:25 +00002309
2310 /* --- Now some more expensive checks. ---*/
2311
2312 /* Once every 25 times, check some more expensive stuff. */
2313 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002314 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002315 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002316
njn37cea302002-09-30 11:24:00 +00002317 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002318 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002319
2320# if 0
2321 { void zzzmemscan(void); zzzmemscan(); }
2322# endif
2323
nethercote297effd2004-08-02 15:07:57 +00002324 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002325 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002326
2327 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002328 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002329 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002330 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002331 }
sewardjb5f6f512005-03-10 23:59:00 +00002332
2333 /* Check that Segments and /proc/self/maps match up */
2334 //vg_assert(VG_(sanity_check_memory)());
2335
2336 /* Look for stack overruns. Visit all threads. */
2337 for(tid = 1; tid < VG_N_THREADS; tid++) {
2338 Int remains;
2339
2340 if (VG_(threads)[tid].status == VgTs_Empty ||
2341 VG_(threads)[tid].status == VgTs_Zombie)
2342 continue;
2343
2344 remains = VGA_(stack_unused)(tid);
2345 if (remains < VKI_PAGE_SIZE)
2346 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2347 tid, remains);
2348 }
2349
njn25e49d8e72002-09-23 09:36:25 +00002350 /*
nethercote297effd2004-08-02 15:07:57 +00002351 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002352 */
njn37cea302002-09-30 11:24:00 +00002353 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002354 }
2355
nethercote27fec902004-06-16 21:26:32 +00002356 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002357 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002358 /* Check sanity of the low-level memory manager. Note that bugs
2359 in the client's code can cause this to fail, so we don't do
2360 this check unless specially asked for. And because it's
2361 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002362 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002363 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002364 }
njn37cea302002-09-30 11:24:00 +00002365 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002366}
nethercote71980f02004-01-24 18:18:54 +00002367
2368
2369/*====================================================================*/
2370/*=== main() ===*/
2371/*====================================================================*/
2372
nethercotec314eba2004-07-15 12:59:41 +00002373/*
2374 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002375 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002376 loads the client executable (and the dynamic linker, if necessary)
2377 into the client part, and calls into Valgrind proper.
2378
2379 The code is careful not to allow spurious mappings to appear in the
2380 wrong parts of the address space. In particular, to make sure
2381 dlopen puts things in the right place, it will pad out the forbidden
2382 chunks of address space so that dlopen is forced to put things where
2383 we want them.
2384
2385 The memory map it creates is:
2386
2387 CLIENT_BASE +-------------------------+
2388 | client address space |
2389 : :
2390 : :
2391 | client stack |
2392 client_end +-------------------------+
2393 | redzone |
2394 shadow_base +-------------------------+
2395 | |
nethercote996901a2004-08-03 13:29:09 +00002396 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002397 | (may be 0 sized) |
2398 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002399 valgrind_base +-------------------------+
2400 | kickstart executable |
2401 | valgrind heap vvvvvvvvv| (barely used)
2402 - -
2403 | valgrind .so files |
2404 | and mappings |
2405 - -
2406 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002407 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002408 : kernel :
2409
2410 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2411 VG_(mmap)(), we need to build the segment skip-list, so we know where
2412 we can put things. However, building that structure requires
2413 allocating memory. So we need to a bootstrapping process. It's done
2414 by making VG_(arena_malloc)() have a special static superblock that's
2415 used for the first 1MB's worth of allocations. This is enough to
2416 build the segment skip-list.
2417*/
2418
nethercote31779c72004-07-30 21:50:15 +00002419static int prmap(char *start, char *end, const char *perm, off_t off,
2420 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002421 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2422 start, end, perm, maj, min, ino);
2423 return True;
2424}
2425
sewardjb5f6f512005-03-10 23:59:00 +00002426int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002427{
2428 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002429 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002430 const char *exec = NULL;
2431 char *preload; /* tool-specific LD_PRELOAD .so */
2432 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002433 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002434 struct exeinfo info;
2435 ToolInfo *toolinfo = NULL;
2436 void *tool_dlhandle;
2437 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002438 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002439 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002440 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002441 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002442
2443 //============================================================
2444 // Nb: startup is complex. Prerequisites are shown at every step.
2445 //
2446 // *** Be very careful when messing with the order ***
2447 //============================================================
2448
nethercotef4928da2004-06-15 10:54:40 +00002449 //============================================================
2450 // Command line argument handling order:
2451 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002452 // (including the tool-specific usage)
2453 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002454 // * Then, if client is missing, abort with error msg
2455 // * Then, if any cmdline args are bad, abort with error msg
2456 //============================================================
2457
fitzhardingeb50068f2004-02-24 23:42:55 +00002458 // Get the current process datasize rlimit, and set it to zero.
2459 // This prevents any internal uses of brk() from having any effect.
2460 // We remember the old value so we can restore it on exec, so that
2461 // child processes will have a reasonable brk value.
2462 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2463 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2464 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002465
2466 // Get the current process stack rlimit.
2467 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2468
nethercote71980f02004-01-24 18:18:54 +00002469 //--------------------------------------------------------------
2470 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002471 // p: none
nethercote71980f02004-01-24 18:18:54 +00002472 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002473 {
2474 void* init_sp = argv - 1;
2475 padfile = scan_auxv(init_sp);
2476 }
nethercote71980f02004-01-24 18:18:54 +00002477 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002478 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002479 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002480 }
2481
2482 //--------------------------------------------------------------
2483 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002484 // p: none
nethercote71980f02004-01-24 18:18:54 +00002485 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002486 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002487 if (cp != NULL)
2488 VG_(libdir) = cp;
2489 }
2490
2491 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002492 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2493 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002494 // p: none
nethercote71980f02004-01-24 18:18:54 +00002495 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002496 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002497 pre_process_cmd_line_options(&need_help, &tool, &exec);
2498
2499 //==============================================================
2500 // Nb: once a tool is specified, the tool.so must be loaded even if
2501 // they specified --help or didn't specify a client program.
2502 //==============================================================
2503
2504 //--------------------------------------------------------------
2505 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002506 // p: set-libdir [for VG_(libdir)]
2507 // p: pre_process_cmd_line_options() [for 'tool']
2508 //--------------------------------------------------------------
2509 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2510
2511 //==============================================================
2512 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002513 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002514 //==============================================================
2515
2516 //--------------------------------------------------------------
2517 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002518 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002519 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002520 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002521
2522 //--------------------------------------------------------------
2523 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002524 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2525 // p: layout_remaining_space [so there's space]
2526 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002527 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002528
2529 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002530 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002531 // p: layout_remaining_space() [everything must be mapped in before now]
2532 // p: load_client() [ditto]
2533 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002534 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2535 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002536
2537 //--------------------------------------------------------------
2538 // Set up client's environment
2539 // p: set-libdir [for VG_(libdir)]
2540 // p: load_tool() [for 'preload']
2541 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002542 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002543
2544 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002545 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002546 // p: load_client() [for 'info']
2547 // p: fix_environment() [for 'env']
2548 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002549 {
2550 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002551
nethercote4ad74312004-10-26 09:59:49 +00002552 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2553 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002554 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002555 }
nethercote71980f02004-01-24 18:18:54 +00002556
2557 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002558 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002559 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002560 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002561
2562 //==============================================================
2563 // Finished setting up operating environment. Now initialise
2564 // Valgrind. (This is where the old VG_(main)() started.)
2565 //==============================================================
2566
2567 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002568 // setup file descriptors
2569 // p: n/a
2570 //--------------------------------------------------------------
2571 setup_file_descriptors();
2572
2573 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002574 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002575 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002576 //--------------------------------------------------------------
2577 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2578
2579 //==============================================================
2580 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2581 //==============================================================
2582
2583 //--------------------------------------------------------------
2584 // Init tool: pre_clo_init, process cmd line, post_clo_init
2585 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2586 // p: load_tool() [for 'tool']
2587 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2588 // p: parse_procselfmaps [so VG segments are setup so tool can
2589 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002590 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002591 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002592 VG_(tool_init_dlsym)(tool_dlhandle);
2593 VG_(sanity_check_needs)();
2594
nethercotef4928da2004-06-15 10:54:40 +00002595 // If --tool and --help/--help-debug was given, now give the core+tool
2596 // help message
nethercotef4928da2004-06-15 10:54:40 +00002597 if (need_help) {
2598 usage(/*--help-debug?*/2 == need_help);
2599 }
nethercotec314eba2004-07-15 12:59:41 +00002600 process_cmd_line_options(client_auxv, tool);
2601
njn26f02512004-11-22 18:33:15 +00002602 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002603
2604 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002605 // Determine CPU architecture and subarchitecture
2606 // p: none
2607 //--------------------------------------------------------------
2608 { Bool ok = VGA_(getArchAndSubArch)(
2609 & VG_(vex_arch), & VG_(vex_subarch) );
2610 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002611 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002612 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002613 VG_(printf)(" Supported CPUs are:\n");
2614 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2615 "AMD Athlon or above)\n");
2616 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002617 VG_(exit)(1);
2618 }
2619 if (VG_(clo_verbosity) > 2) {
2620 VG_(message)(Vg_DebugMsg,
2621 "Host CPU: arch = %s, subarch = %s",
2622 LibVEX_ppVexArch( VG_(vex_arch) ),
2623 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2624 }
2625 }
2626
2627 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002628 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002629 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002630 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002631 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002632 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002633 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002634 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002635 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002636
sewardja4da2f32005-03-02 14:06:08 +00002637#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002638 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002639 // Protect client trampoline page (which is also sysinfo stuff)
2640 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002641 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002642 {
2643 Segment *seg;
2644 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2645 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002646#endif
nethercotec314eba2004-07-15 12:59:41 +00002647
sewardjb5f6f512005-03-10 23:59:00 +00002648 /* Make sure this segment isn't treated as stack */
2649 seg = VG_(find_segment)(VG_(client_trampoline_code));
2650 if (seg)
2651 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2652 }
2653
nethercotec314eba2004-07-15 12:59:41 +00002654 //==============================================================
2655 // Can use VG_(map)() after segments set up
2656 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002657
2658 //--------------------------------------------------------------
2659 // Allow GDB attach
2660 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2661 //--------------------------------------------------------------
2662 /* Hook to delay things long enough so we can get the pid and
2663 attach GDB in another shell. */
2664 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002665 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2666 /* jrs 20050206: I don't understand why this works on x86. On
2667 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2668 work. */
2669 /* do "jump *$eip" to skip this in gdb (x86) */
2670 //VG_(do_syscall0)(__NR_pause);
2671 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002672 }
2673
nethercote71980f02004-01-24 18:18:54 +00002674 // Search for file descriptors that are inherited from our parent
2675 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2676 //--------------------------------------------------------------
2677 if (VG_(clo_track_fds))
2678 VG_(init_preopened_fds)();
2679
2680 //--------------------------------------------------------------
2681 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002682 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2683 //--------------------------------------------------------------
2684 VG_(scheduler_init)();
2685
2686 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002687 // Initialise the pthread model
2688 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002689 // load_client() [for 'client_eip']
2690 // setup_client_stack() [for 'sp_at_startup']
2691 // setup_scheduler() [for the rest of state 1 stuff]
2692 //--------------------------------------------------------------
2693 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002694
2695 // Tell the tool that we just wrote to the registers.
2696 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2697 sizeof(VexGuestArchState));
2698
2699 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002700 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002701
2702 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002703 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002704 //if (VG_(clo_model_pthreads))
2705 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002706
2707 //--------------------------------------------------------------
2708 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002709 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002710 //--------------------------------------------------------------
2711 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2712 VG_(sigstartup_actions)();
2713
2714 //--------------------------------------------------------------
2715 // Perhaps we're profiling Valgrind?
2716 // p: process_cmd_line_options() [for VG_(clo_profile)]
2717 // p: others?
2718 //
2719 // XXX: this seems to be broken? It always says the tool wasn't built
2720 // for profiling; vg_profile.c's functions don't seem to be overriding
2721 // vg_dummy_profile.c's?
2722 //
2723 // XXX: want this as early as possible. Looking for --profile
2724 // in pre_process_cmd_line_options() could get it earlier.
2725 //--------------------------------------------------------------
2726 if (VG_(clo_profile))
2727 VGP_(init_profiling)();
2728
2729 VGP_PUSHCC(VgpStartup);
2730
2731 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002732 // Read suppression file
2733 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2734 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002735 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002736 VG_(load_suppressions)();
2737
2738 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002739 // Initialise translation table and translation cache
2740 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2741 // aren't identified as part of the client, which would waste
2742 // > 20M of virtual address space.]
2743 //--------------------------------------------------------------
2744 VG_(init_tt_tc)();
2745
2746 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002747 // Verbosity message
2748 // p: end_rdtsc_calibration [so startup message is printed first]
2749 //--------------------------------------------------------------
2750 if (VG_(clo_verbosity) == 1)
2751 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2752 if (VG_(clo_verbosity) > 0)
2753 VG_(message)(Vg_UserMsg, "");
2754
2755 //--------------------------------------------------------------
2756 // Setup pointercheck
2757 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2758 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002759 if (VG_(clo_pointercheck))
2760 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002761
nethercote71980f02004-01-24 18:18:54 +00002762 //--------------------------------------------------------------
2763 // Run!
2764 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002765 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002766
sewardjb5f6f512005-03-10 23:59:00 +00002767 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002768
sewardjb5f6f512005-03-10 23:59:00 +00002769 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002770
sewardjb5f6f512005-03-10 23:59:00 +00002771 abort();
2772}
2773
2774
2775/* Do everything which needs doing when the last thread exits */
2776void VG_(shutdown_actions)(ThreadId tid)
2777{
2778 vg_assert(tid == VG_(master_tid));
2779 vg_assert(VG_(is_running_thread)(tid));
2780
2781 // Wait for all other threads to exit.
2782 VGA_(reap_threads)(tid);
2783
2784 VG_(clo_model_pthreads) = False;
2785
2786 // Clean the client up before the final report
2787 VGA_(final_tidyup)(tid);
2788
2789 // OK, done
2790 VG_(exit_thread)(tid);
2791
2792 /* should be no threads left */
2793 vg_assert(VG_(count_living_threads)() == 0);
2794
2795 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002796 //--------------------------------------------------------------
2797 // Finalisation: cleanup, messages, etc. Order no so important, only
2798 // affects what order the messages come.
2799 //--------------------------------------------------------------
2800 if (VG_(clo_verbosity) > 0)
2801 VG_(message)(Vg_UserMsg, "");
2802
nethercote71980f02004-01-24 18:18:54 +00002803 /* Print out file descriptor summary and stats. */
2804 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002805 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002806
njn95ec8702004-11-22 16:46:13 +00002807 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002808 VG_(show_all_errors)();
2809
sewardjb5f6f512005-03-10 23:59:00 +00002810 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002811
nethercote885dd912004-08-03 23:14:00 +00002812 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002813
2814 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002815 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002816
nethercote71980f02004-01-24 18:18:54 +00002817 if (VG_(clo_profile))
2818 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002819 if (VG_(clo_profile_flags) > 0)
2820 VG_(show_BB_profile)();
2821
sewardj8b635a42004-11-22 19:01:47 +00002822 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002823 if (0)
2824 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002825
nethercote71980f02004-01-24 18:18:54 +00002826}
2827
sewardjde4a1d02002-03-22 01:27:54 +00002828/*--------------------------------------------------------------------*/
2829/*--- end vg_main.c ---*/
2830/*--------------------------------------------------------------------*/