blob: 114ad1eb26bead5ba68088bcf9a144067e85fe76 [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/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
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
thughes74b8de22004-04-22 18:12:31 +000048#ifndef AT_DCACHEBSIZE
49#define AT_DCACHEBSIZE 19
50#endif /* AT_DCACHEBSIZE */
51
52#ifndef AT_ICACHEBSIZE
53#define AT_ICACHEBSIZE 20
54#endif /* AT_ICACHEBSIZE */
55
56#ifndef AT_UCACHEBSIZE
57#define AT_UCACHEBSIZE 21
58#endif /* AT_UCACHEBSIZE */
59
nethercote71980f02004-01-24 18:18:54 +000060#ifndef AT_SYSINFO
61#define AT_SYSINFO 32
62#endif /* AT_SYSINFO */
63
64#ifndef AT_SYSINFO_EHDR
65#define AT_SYSINFO_EHDR 33
66#endif /* AT_SYSINFO_EHDR */
67
68#ifndef AT_SECURE
69#define AT_SECURE 23 /* secure mode boolean */
70#endif /* AT_SECURE */
71
nethercote71980f02004-01-24 18:18:54 +000072/* redzone gap between client address space and shadow */
73#define REDZONE_SIZE (1 * 1024*1024)
74
75/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000076#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000077
nethercotee2097312004-06-27 12:29:56 +000078/* Proportion of client space for its heap (rest is for mmaps + stack) */
79#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000080
81/*====================================================================*/
82/*=== Global entities not referenced from generated code ===*/
83/*====================================================================*/
84
sewardjde4a1d02002-03-22 01:27:54 +000085/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000086 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000087 ------------------------------------------------------------------ */
88
nethercote71980f02004-01-24 18:18:54 +000089/* Client address space, lowest to highest (see top of ume.c) */
90Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000091Addr VG_(client_end);
92Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000093Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000094Addr VG_(clstk_base);
95Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000096
97Addr VG_(brk_base); /* start of brk */
98Addr VG_(brk_limit); /* current brk */
99
nethercote996901a2004-08-03 13:29:09 +0000100Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000104
nethercote820bd8c2004-09-07 23:04:49 +0000105// Note that VG_(valgrind_last) names the last byte of the section, whereas
106// the VG_(*_end) vars name the byte one past the end of the section.
107Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108
nethercote73b526f2004-10-31 18:48:21 +0000109struct vki_rlimit VG_(client_rlimit_data);
110struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000111
nethercote71980f02004-01-24 18:18:54 +0000112/* This is set early to indicate whether this CPU has the
113 SSE/fxsave/fxrestor features. */
114Bool VG_(have_ssestate);
115
fitzhardinge98abfc72003-12-16 02:05:15 +0000116/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000117static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000118
119/* client executable */
120Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000121
122/* Path to library directory */
123const Char *VG_(libdir) = VG_LIBDIR;
124
125/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000126static Int vg_argc;
127static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000128
jsgf855d93d2003-10-13 22:26:55 +0000129/* PID of the main thread */
130Int VG_(main_pid);
131
132/* PGRP of process */
133Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000134
thughesad1c9562004-06-26 11:27:52 +0000135/* Application-visible file descriptor limits */
136Int VG_(fd_soft_limit) = -1;
137Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000138
nethercote4ad74312004-10-26 09:59:49 +0000139/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000140 envp[] as extracted from the client's stack at startup-time. */
141Int VG_(client_argc);
142Char** VG_(client_argv);
143Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000144
145/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000146 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000147 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000148
nethercote71980f02004-01-24 18:18:54 +0000149/* Counts downwards in VG_(run_innerloop). */
150UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000151
152/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000153ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000154
nethercote71980f02004-01-24 18:18:54 +0000155/* Tell the logging mechanism whether we are logging to a file
156 descriptor or a socket descriptor. */
157Bool VG_(logging_to_filedes) = True;
158
sewardj73cf3bc2002-11-03 03:20:15 +0000159
nethercote71980f02004-01-24 18:18:54 +0000160/*====================================================================*/
161/*=== Counters, for profiling purposes only ===*/
162/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000163
nethercote92e7b7f2004-08-07 17:52:25 +0000164// These ones maintained by vg_dispatch.S
165UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
166UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
167UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000168
sewardjde4a1d02002-03-22 01:27:54 +0000169/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000170static UInt sanity_fast_count = 0;
171static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000172
nethercote3a42fb82004-08-03 18:08:50 +0000173static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000174{
nethercote3a42fb82004-08-03 18:08:50 +0000175 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000176 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000177 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000178 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000179 VG_(bb_enchain_count), VG_(bb_dechain_count) );
180 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000181 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(bbs_done),
183 VG_(unchained_jumps_done),
184 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
185 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
186 );
187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000189 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000190
nethercote71980f02004-01-24 18:18:54 +0000191 VG_(message)(Vg_DebugMsg,
192 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000193 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000194
nethercote3a42fb82004-08-03 18:08:50 +0000195 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000196 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000197 VG_(message)(Vg_DebugMsg, "");
198 VG_(message)(Vg_DebugMsg,
199 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000200 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000201 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000202 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000203 VG_(message)(Vg_DebugMsg,
204 "------ Valgrind's ExeContext management stats follow ------" );
205 VG_(print_ExeContext_stats)();
206 }
nethercote71980f02004-01-24 18:18:54 +0000207}
208
209
210/*====================================================================*/
211/*=== Miscellaneous global functions ===*/
212/*====================================================================*/
213
nethercotecf97ffb2004-09-09 13:40:31 +0000214static Int ptrace_setregs(Int pid, ThreadId tid)
215{
sewardj2a99cf62004-11-24 10:44:19 +0000216 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000217}
218
nethercote04d0fbc2004-01-26 16:48:06 +0000219/* Start debugger and get it to attach to this process. Called if the
220 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000221 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000222 meaningfully get the debugger to continue the program, though; to
223 continue, quit the debugger. */
224void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000225{
226 Int pid;
227
228 if ((pid = fork()) == 0) {
229 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000230 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000231
232 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000233 Int status;
234 Int res;
235
nethercote71980f02004-01-24 18:18:54 +0000236 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
237 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000238 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000239 kill(pid, SIGSTOP) == 0 &&
240 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000241 Char pidbuf[15];
242 Char file[30];
243 Char buf[100];
244 Char *bufptr;
245 Char *cmdptr;
246
247 VG_(sprintf)(pidbuf, "%d", pid);
248 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
249
250 bufptr = buf;
251 cmdptr = VG_(clo_db_command);
252
253 while (*cmdptr) {
254 switch (*cmdptr) {
255 case '%':
256 switch (*++cmdptr) {
257 case 'f':
258 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
259 bufptr += VG_(strlen)(file);
260 cmdptr++;
261 break;
262 case 'p':
263 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
264 bufptr += VG_(strlen)(pidbuf);
265 cmdptr++;
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 break;
272 default:
273 *bufptr++ = *cmdptr++;
274 break;
275 }
276 }
277
278 *bufptr++ = '\0';
279
280 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000281 res = VG_(system)(buf);
282 if (res == 0) {
283 VG_(message)(Vg_UserMsg, "");
284 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000285 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000286 } else {
287 VG_(message)(Vg_UserMsg, "Apparently failed!");
288 VG_(message)(Vg_UserMsg, "");
289 }
290 }
291
nethercote73b526f2004-10-31 18:48:21 +0000292 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000293 VG_(waitpid)(pid, &status, 0);
294 }
295}
296
297
298/* Print some helpful-ish text about unimplemented things, and give
299 up. */
300void VG_(unimplemented) ( Char* msg )
301{
302 VG_(message)(Vg_UserMsg, "");
303 VG_(message)(Vg_UserMsg,
304 "Valgrind detected that your program requires");
305 VG_(message)(Vg_UserMsg,
306 "the following unimplemented functionality:");
307 VG_(message)(Vg_UserMsg, " %s", msg);
308 VG_(message)(Vg_UserMsg,
309 "This may be because the functionality is hard to implement,");
310 VG_(message)(Vg_UserMsg,
311 "or because no reasonable program would behave this way,");
312 VG_(message)(Vg_UserMsg,
313 "or because nobody has yet needed it. In any case, let us know at");
314 VG_(message)(Vg_UserMsg,
315 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
316 VG_(message)(Vg_UserMsg,
317 "");
318 VG_(message)(Vg_UserMsg,
319 "Valgrind has to exit now. Sorry. Bye!");
320 VG_(message)(Vg_UserMsg,
321 "");
322 VG_(pp_sched_status)();
323 VG_(exit)(1);
324}
325
sewardj2a99cf62004-11-24 10:44:19 +0000326/* Get the simulated stack pointer */
327Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000328{
njncf45fd42004-11-24 16:30:22 +0000329 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000330}
331
332/* Initialize the PID and PGRP of scheduler LWP; this is also called
333 in any new children after fork. */
334static void newpid(ThreadId unused)
335{
336 /* PID of scheduler LWP */
337 VG_(main_pid) = VG_(getpid)();
338 VG_(main_pgrp) = VG_(getpgrp)();
339}
340
341/*====================================================================*/
342/*=== Check we were launched by stage 1 ===*/
343/*====================================================================*/
344
345/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000346int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000347{
nethercoteebf1d862004-11-01 18:22:05 +0000348 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000349 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000350
351 for (; auxv->a_type != AT_NULL; auxv++)
352 switch(auxv->a_type) {
353 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000354 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000355 found |= 1;
356 break;
357
358 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000359 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000360 found |= 2;
361 break;
nethercote7f390022004-10-25 17:18:24 +0000362
363 case AT_PHDR:
364 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
365 break;
nethercote71980f02004-01-24 18:18:54 +0000366 }
367
nethercote361a14e2004-07-26 11:11:56 +0000368 if ( found != (1|2) ) {
369 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000370 exit(127);
371 }
nethercote31779c72004-07-30 21:50:15 +0000372 vg_assert(padfile >= 0);
373 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000374}
375
376
377/*====================================================================*/
378/*=== Address space determination ===*/
379/*====================================================================*/
380
nethercote7f390022004-10-25 17:18:24 +0000381extern char _start[];
382
nethercote31779c72004-07-30 21:50:15 +0000383static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000384{
nethercotea3c3cf22004-11-01 18:38:00 +0000385 Int ires;
386 void* vres;
387 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000388
nethercote7f390022004-10-25 17:18:24 +0000389 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
390 // this is a workable approximation
391 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000392 VG_(valgrind_base) = PGROUNDDN(&_start);
393 }
394
nethercote820bd8c2004-09-07 23:04:49 +0000395 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000396
nethercote31779c72004-07-30 21:50:15 +0000397 // This gives the client the largest possible address space while
398 // taking into account the tool's shadow needs.
399 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000400 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000401 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000402 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000403 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000404 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000405 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000406
nethercote31779c72004-07-30 21:50:15 +0000407 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000408 VG_(shadow_end) = VG_(valgrind_base);
409 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000410
nethercotee2097312004-06-27 12:29:56 +0000411#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
412
nethercote71980f02004-01-24 18:18:54 +0000413 if (0)
nethercotee2097312004-06-27 12:29:56 +0000414 VG_(printf)(
415 "client_base %8x (%dMB)\n"
416 "client_mapbase %8x (%dMB)\n"
417 "client_end %8x (%dMB)\n"
418 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000419 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000420 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000421 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000422 VG_(client_base), SEGSIZE(client_base, client_mapbase),
423 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
424 VG_(client_end), SEGSIZE(client_end, shadow_base),
425 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000426 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000427 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
428 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000429 );
430
431#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000432
433 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000434 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000435 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000436 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000437
438 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000439 ires = munmap((void*)VG_(client_base), client_size);
440 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000441
442 // Map shadow memory.
443 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000444 if (shadow_size != 0) {
445 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000446 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000447 if ((void*)-1 == vres) {
448 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000449 "valgrind: Could not allocate address space (%p bytes)\n"
450 "valgrind: for shadow memory\n"
451 "valgrind: Possible causes:\n"
452 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
453 "valgrind: needs at least 1.5GB swap space.\n"
454 "valgrind: - Or, your virtual memory size may be limited (check\n"
455 "valgrind: with 'ulimit -v').\n"
456 "valgrind: - Or, your system may use a kernel that provides only a\n"
457 "valgrind: too-small (eg. 2GB) user address space.\n"
458 , (void*)shadow_size
459 );
nethercoted4722622004-08-30 19:36:42 +0000460 exit(1);
461 }
nethercotee567e702004-07-10 17:49:17 +0000462 }
nethercote71980f02004-01-24 18:18:54 +0000463}
464
465/*====================================================================*/
466/*=== Command line setup ===*/
467/*====================================================================*/
468
469/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
470static char* get_file_clo(char* dir)
471{
472# define FLEN 512
473 Int fd, n;
474 struct stat s1;
475 char* f_clo = NULL;
476 char filename[FLEN];
477
478 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
479 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
480 if ( fd > 0 ) {
481 if ( 0 == fstat(fd, &s1) ) {
482 f_clo = malloc(s1.st_size+1);
483 vg_assert(f_clo);
484 n = read(fd, f_clo, s1.st_size);
485 if (n == -1) n = 0;
486 f_clo[n] = '\0';
487 }
488 close(fd);
489 }
490 return f_clo;
491# undef FLEN
492}
493
nethercotee2097312004-06-27 12:29:56 +0000494#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
495
nethercote71980f02004-01-24 18:18:54 +0000496static Int count_args(char* s)
497{
498 Int n = 0;
499 if (s) {
500 char* cp = s;
501 while (True) {
502 // We have alternating sequences: blanks, non-blanks, blanks...
503 // count the non-blanks sequences.
504 while ( ISSPACE(*cp) ) cp++;
505 if ( !*cp ) break;
506 n++;
507 while ( !ISSPACE(*cp) && *cp ) cp++;
508 }
509 }
510 return n;
511}
512
513/* add args out of environment, skipping multiple spaces and -- args */
514static char** copy_args( char* s, char** to )
515{
516 if (s) {
517 char* cp = s;
518 while (True) {
519 // We have alternating sequences: blanks, non-blanks, blanks...
520 // copy the non-blanks sequences, and add terminating '\0'
521 while ( ISSPACE(*cp) ) cp++;
522 if ( !*cp ) break;
523 *to++ = cp;
524 while ( !ISSPACE(*cp) && *cp ) cp++;
525 if ( *cp ) *cp++ = '\0'; // terminate if necessary
526 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
527 }
528 }
529 return to;
530}
531
nethercotee2097312004-06-27 12:29:56 +0000532#undef ISSPACE
533
nethercote71980f02004-01-24 18:18:54 +0000534// Augment command line with arguments from environment and .valgrindrc
535// files.
536static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
537{
nethercotef6a1d502004-08-09 12:21:57 +0000538 int vg_argc0 = *vg_argc_inout;
539 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000540
541 char* env_clo = getenv(VALGRINDOPTS);
542 char* f1_clo = get_file_clo( getenv("HOME") );
543 char* f2_clo = get_file_clo(".");
544
545 /* copy any extra args from file or environment, if present */
546 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
547 /* ' ' separated extra options */
548 char **from;
549 char **to;
thughescaca0022004-09-13 10:20:34 +0000550 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
551
552 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
553
nethercote71980f02004-01-24 18:18:54 +0000554 env_arg_count = count_args(env_clo);
555 f1_arg_count = count_args(f1_clo);
556 f2_arg_count = count_args(f2_clo);
557
558 if (0)
559 printf("extra-argc=%d %d %d\n",
560 env_arg_count, f1_arg_count, f2_arg_count);
561
562 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000563 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000564 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000565 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000566 vg_assert(vg_argv0);
567 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000568
569 /* copy argv[0] */
570 *to++ = *from++;
571
572 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
573 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
574 * to override less local ones. */
575 to = copy_args(f1_clo, to);
576 to = copy_args(env_clo, to);
577 to = copy_args(f2_clo, to);
578
579 /* copy original arguments, stopping at command or -- */
580 while (*from) {
581 if (**from != '-')
582 break;
583 if (VG_STREQ(*from, "--")) {
584 from++; /* skip -- */
585 break;
586 }
587 *to++ = *from++;
588 }
589
590 /* add -- */
591 *to++ = "--";
592
nethercotef6a1d502004-08-09 12:21:57 +0000593 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000594
595 /* copy rest of original command line, then NULL */
596 while (*from) *to++ = *from++;
597 *to = NULL;
598 }
599
nethercotef6a1d502004-08-09 12:21:57 +0000600 *vg_argc_inout = vg_argc0;
601 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000602}
603
nethercotef6a1d502004-08-09 12:21:57 +0000604#define VG_CLO_SEP '\01'
605
nethercote71980f02004-01-24 18:18:54 +0000606static void get_command_line( int argc, char** argv,
607 Int* vg_argc_out, Char*** vg_argv_out,
608 char*** cl_argv_out )
609{
nethercotef6a1d502004-08-09 12:21:57 +0000610 int vg_argc0;
611 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000612 char** cl_argv;
613 char* env_clo = getenv(VALGRINDCLO);
614
615 if (env_clo != NULL && *env_clo != '\0') {
616 char *cp;
617 char **cpp;
618
nethercotef6a1d502004-08-09 12:21:57 +0000619 /* OK, VALGRINDCLO is set, which means we must be a child of another
620 Valgrind process using --trace-children, so we're getting all our
621 arguments from VALGRINDCLO, and the entire command line belongs to
622 the client (including argv[0]) */
623 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000624 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000625 if (*cp == VG_CLO_SEP)
626 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000627
nethercotef6a1d502004-08-09 12:21:57 +0000628 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
629 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000630
nethercotef6a1d502004-08-09 12:21:57 +0000631 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000632
633 *cpp++ = "valgrind"; /* nominal argv[0] */
634 *cpp++ = env_clo;
635
nethercotef6a1d502004-08-09 12:21:57 +0000636 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000637 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000638 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000639 *cp++ = '\0'; /* chop it up in place */
640 *cpp++ = cp;
641 }
642 }
643 *cpp = NULL;
644 cl_argv = argv;
645
646 } else {
647 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000648 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000649
nethercotef6a1d502004-08-09 12:21:57 +0000650 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
651 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000652 break;
nethercotef6a1d502004-08-09 12:21:57 +0000653 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
654 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000655 break;
656 }
657 }
nethercotef6a1d502004-08-09 12:21:57 +0000658 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000659
660 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000661 Note we don't do this if getting args from VALGRINDCLO, as
662 those extra args will already be present in VALGRINDCLO. */
663 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000664 }
665
666 if (0) {
667 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000668 for (i = 0; i < vg_argc0; i++)
669 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000670 }
671
nethercotef6a1d502004-08-09 12:21:57 +0000672 *vg_argc_out = vg_argc0;
673 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000674 *cl_argv_out = cl_argv;
675}
676
677
678/*====================================================================*/
679/*=== Environment and stack setup ===*/
680/*====================================================================*/
681
682/* Scan a colon-separated list, and call a function on each element.
683 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000684 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000685 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000686
687 This routine will return True if (*func) returns True and False if
688 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000689*/
thughes4ad52d02004-06-27 17:37:21 +0000690static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000691{
692 char *cp, *entry;
693 int end;
694
695 if (colsep == NULL ||
696 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000697 return False;
nethercote71980f02004-01-24 18:18:54 +0000698
699 entry = cp = colsep;
700
701 do {
702 end = (*cp == '\0');
703
704 if (*cp == ':' || *cp == '\0') {
705 char save = *cp;
706
707 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000708 if ((*func)(entry)) {
709 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000710 return True;
thughes21942d92004-07-12 09:35:37 +0000711 }
nethercote71980f02004-01-24 18:18:54 +0000712 *cp = save;
713 entry = cp+1;
714 }
715 cp++;
716 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000717
718 return False;
719}
720
721static Bool contains(const char *p) {
722 if (VG_STREQ(p, VG_(libdir))) {
723 return True;
724 }
725 return False;
nethercote71980f02004-01-24 18:18:54 +0000726}
727
728/* Prepare the client's environment. This is basically a copy of our
729 environment, except:
730 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
731 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
732
733 If any of these is missing, then it is added.
734
735 Yummy. String hacking in C.
736
737 If this needs to handle any more variables it should be hacked
738 into something table driven.
739 */
740static char **fix_environment(char **origenv, const char *preload)
741{
742 static const char inject_so[] = "vg_inject.so";
743 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
744 static const char ld_preload[] = "LD_PRELOAD=";
745 static const char valgrind_clo[] = VALGRINDCLO "=";
746 static const int ld_library_path_len = sizeof(ld_library_path)-1;
747 static const int ld_preload_len = sizeof(ld_preload)-1;
748 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
749 int ld_preload_done = 0;
750 int ld_library_path_done = 0;
751 char *inject_path;
752 int inject_path_len;
753 int vgliblen = strlen(VG_(libdir));
754 char **cpp;
755 char **ret;
756 int envc;
757 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
758
759 /* Find the vg_inject.so; also make room for the tool preload
760 library */
761 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
762 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000763 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000764
765 if (preload)
766 snprintf(inject_path, inject_path_len, "%s/%s:%s",
767 VG_(libdir), inject_so, preload);
768 else
769 snprintf(inject_path, inject_path_len, "%s/%s",
770 VG_(libdir), inject_so);
771
772 /* Count the original size of the env */
773 envc = 0; /* trailing NULL */
774 for (cpp = origenv; cpp && *cpp; cpp++)
775 envc++;
776
777 /* Allocate a new space */
778 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000779 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000780
781 /* copy it over */
782 for (cpp = ret; *origenv; )
783 *cpp++ = *origenv++;
784 *cpp = NULL;
785
786 vg_assert(envc == (cpp - ret));
787
788 /* Walk over the new environment, mashing as we go */
789 for (cpp = ret; cpp && *cpp; cpp++) {
790 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000791 /* If the LD_LIBRARY_PATH already contains libdir, then don't
792 bother adding it again, even if it isn't the first (it
793 seems that the Java runtime will keep reexecing itself
794 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000795 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000796 int len = strlen(*cpp) + vgliblen*2 + 16;
797 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000798 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000799
800 snprintf(cp, len, "%s%s:%s",
801 ld_library_path, VG_(libdir),
802 (*cpp)+ld_library_path_len);
803
804 *cpp = cp;
805 }
806
807 ld_library_path_done = 1;
808 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
809 int len = strlen(*cpp) + inject_path_len;
810 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000811 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000812
813 snprintf(cp, len, "%s%s:%s",
814 ld_preload, inject_path, (*cpp)+ld_preload_len);
815
816 *cpp = cp;
817
818 ld_preload_done = 1;
819 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
820 *cpp = "";
821 }
822 }
823
824 /* Add the missing bits */
825
826 if (!ld_library_path_done) {
827 int len = ld_library_path_len + vgliblen*2 + 16;
828 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000829 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000830
831 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
832
833 ret[envc++] = cp;
834 }
835
836 if (!ld_preload_done) {
837 int len = ld_preload_len + inject_path_len;
838 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000839 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000840
841 snprintf(cp, len, "%s%s",
842 ld_preload, inject_path);
843
844 ret[envc++] = cp;
845 }
846
847 ret[envc] = NULL;
848
849 return ret;
850}
851
852extern char **environ; /* our environment */
853//#include <error.h>
854
855/* Add a string onto the string table, and return its address */
856static char *copy_str(char **tab, const char *str)
857{
858 char *cp = *tab;
859 char *orig = cp;
860
861 while(*str)
862 *cp++ = *str++;
863 *cp++ = '\0';
864
865 if (0)
nethercote545fe672004-11-01 16:52:43 +0000866 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000867
868 *tab = cp;
869
870 return orig;
871}
872
873/*
874 This sets up the client's initial stack, containing the args,
875 environment and aux vector.
876
877 The format of the stack is:
878
879 higher address +-----------------+
880 | Trampoline code |
881 +-----------------+
882 | |
883 : string table :
884 | |
885 +-----------------+
886 | AT_NULL |
887 - -
888 | auxv |
889 +-----------------+
890 | NULL |
891 - -
892 | envp |
893 +-----------------+
894 | NULL |
895 - -
896 | argv |
897 +-----------------+
898 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000899 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000900 | undefined |
901 : :
902 */
nethercotec25c4492004-10-18 11:52:17 +0000903static Addr setup_client_stack(void* init_sp,
904 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000905 const struct exeinfo *info,
906 UInt** client_auxv)
907{
nethercotee567e702004-07-10 17:49:17 +0000908 void* res;
nethercote71980f02004-01-24 18:18:54 +0000909 char **cpp;
910 char *strtab; /* string table */
911 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000912 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000913 struct ume_auxv *auxv;
914 const struct ume_auxv *orig_auxv;
915 const struct ume_auxv *cauxv;
916 unsigned stringsize; /* total size of strings in bytes */
917 unsigned auxsize; /* total size of auxv in bytes */
918 int argc; /* total argc */
919 int envc; /* total number of env vars */
920 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000921 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000922
923 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000924 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000925
926 /* ==================== compute sizes ==================== */
927
928 /* first of all, work out how big the client stack will be */
929 stringsize = 0;
930
931 /* paste on the extra args if the loader needs them (ie, the #!
932 interpreter and its argument) */
933 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000934 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000935 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000936 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000937 }
nethercoted6a56872004-07-26 15:32:47 +0000938 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000939 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000940 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000941 }
942
943 /* now scan the args we're given... */
944 for (cpp = orig_argv; *cpp; cpp++) {
945 argc++;
946 stringsize += strlen(*cpp) + 1;
947 }
948
949 /* ...and the environment */
950 envc = 0;
951 for (cpp = orig_envp; cpp && *cpp; cpp++) {
952 envc++;
953 stringsize += strlen(*cpp) + 1;
954 }
955
956 /* now, how big is the auxv? */
957 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
958 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
959 if (cauxv->a_type == AT_PLATFORM)
960 stringsize += strlen(cauxv->u.a_ptr) + 1;
961 auxsize += sizeof(*cauxv);
962 }
963
964 /* OK, now we know how big the client stack is */
965 stacksize =
966 sizeof(int) + /* argc */
967 sizeof(char **)*argc + /* argv */
968 sizeof(char **) + /* terminal NULL */
969 sizeof(char **)*envc + /* envp */
970 sizeof(char **) + /* terminal NULL */
971 auxsize + /* auxv */
972 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000973 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000974
nethercotef84f6952004-07-15 14:58:33 +0000975 // decide where stack goes!
976 VG_(clstk_end) = VG_(client_end);
977
nethercote73b526f2004-10-31 18:48:21 +0000978 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000979
nethercote71980f02004-01-24 18:18:54 +0000980 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000981 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000982 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
983
nethercote71980f02004-01-24 18:18:54 +0000984 /* base of the string table (aligned) */
985 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
986
987 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000988
nethercote5ee67ca2004-06-22 14:00:09 +0000989 if (0)
990 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000991 "clstk_base %p\n"
992 "clstk_end %p\n",
993 stringsize, auxsize, stacksize,
994 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000995
996
nethercote71980f02004-01-24 18:18:54 +0000997 /* ==================== allocate space ==================== */
998
999 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001000 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001001 PROT_READ | PROT_WRITE | PROT_EXEC,
1002 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1003 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001004
1005 /* ==================== copy client stack ==================== */
1006
nethercotea3c3cf22004-11-01 18:38:00 +00001007 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +00001008
1009 /* --- argc --- */
1010 *ptr++ = argc; /* client argc */
1011
1012 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001013 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001014 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001015 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001016 }
nethercoted6a56872004-07-26 15:32:47 +00001017 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001018 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001019 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001020 }
1021 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001022 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001023 }
1024 *ptr++ = 0;
1025
1026 /* --- envp --- */
1027 VG_(client_envp) = (Char **)ptr;
1028 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001029 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001030 *ptr++ = 0;
1031
1032 /* --- auxv --- */
1033 auxv = (struct ume_auxv *)ptr;
1034 *client_auxv = (UInt *)auxv;
1035
1036 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1037 /* copy the entry... */
1038 *auxv = *orig_auxv;
1039
1040 /* ...and fix up the copy */
1041 switch(auxv->a_type) {
1042 case AT_PHDR:
1043 if (info->phdr == 0)
1044 auxv->a_type = AT_IGNORE;
1045 else
1046 auxv->u.a_val = info->phdr;
1047 break;
1048
1049 case AT_PHNUM:
1050 if (info->phdr == 0)
1051 auxv->a_type = AT_IGNORE;
1052 else
1053 auxv->u.a_val = info->phnum;
1054 break;
1055
1056 case AT_BASE:
1057 if (info->interp_base == 0)
1058 auxv->a_type = AT_IGNORE;
1059 else
1060 auxv->u.a_val = info->interp_base;
1061 break;
1062
1063 case AT_PLATFORM: /* points to a platform description string */
1064 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1065 break;
1066
1067 case AT_ENTRY:
1068 auxv->u.a_val = info->entry;
1069 break;
1070
1071 case AT_IGNORE:
1072 case AT_EXECFD:
1073 case AT_PHENT:
1074 case AT_PAGESZ:
1075 case AT_FLAGS:
1076 case AT_NOTELF:
1077 case AT_UID:
1078 case AT_EUID:
1079 case AT_GID:
1080 case AT_EGID:
1081 case AT_CLKTCK:
1082 case AT_HWCAP:
1083 case AT_FPUCW:
1084 case AT_DCACHEBSIZE:
1085 case AT_ICACHEBSIZE:
1086 case AT_UCACHEBSIZE:
1087 /* All these are pointerless, so we don't need to do anything
1088 about them. */
1089 break;
1090
1091 case AT_SECURE:
1092 /* If this is 1, then it means that this program is running
1093 suid, and therefore the dynamic linker should be careful
1094 about LD_PRELOAD, etc. However, since stage1 (the thing
1095 the kernel actually execve's) should never be SUID, and we
1096 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1097 set AT_SECURE to 0. */
1098 auxv->u.a_val = 0;
1099 break;
1100
1101 case AT_SYSINFO:
1102 /* Leave this unmolested for now, but we'll update it later
1103 when we set up the client trampoline code page */
1104 break;
1105
1106 case AT_SYSINFO_EHDR:
1107 /* Trash this, because we don't reproduce it */
1108 auxv->a_type = AT_IGNORE;
1109 break;
1110
1111 default:
1112 /* stomp out anything we don't know about */
1113 if (0)
nethercote545fe672004-11-01 16:52:43 +00001114 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001115 auxv->a_type = AT_IGNORE;
1116 break;
1117
1118 }
1119 }
1120 *auxv = *orig_auxv;
1121 vg_assert(auxv->a_type == AT_NULL);
1122
nethercotef84f6952004-07-15 14:58:33 +00001123 /* --- trampoline page --- */
1124 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1125 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1126
nethercote71980f02004-01-24 18:18:54 +00001127 vg_assert((strtab-stringbase) == stringsize);
1128
nethercote5ee67ca2004-06-22 14:00:09 +00001129 /* We know the initial ESP is pointing at argc/argv */
1130 VG_(client_argc) = *(Int*)cl_esp;
1131 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1132
nethercote71980f02004-01-24 18:18:54 +00001133 return cl_esp;
1134}
1135
1136/*====================================================================*/
1137/*=== Find executable ===*/
1138/*====================================================================*/
1139
thughes4ad52d02004-06-27 17:37:21 +00001140static const char* executable_name;
1141
1142static Bool match_executable(const char *entry) {
1143 char buf[strlen(entry) + strlen(executable_name) + 2];
1144
1145 /* empty PATH element means . */
1146 if (*entry == '\0')
1147 entry = ".";
1148
1149 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1150
1151 if (access(buf, R_OK|X_OK) == 0) {
1152 executable_name = strdup(buf);
1153 vg_assert(NULL != executable_name);
1154 return True;
1155 }
1156 return False;
1157}
1158
nethercote71980f02004-01-24 18:18:54 +00001159static const char* find_executable(const char* exec)
1160{
1161 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001162 executable_name = exec;
1163 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001164 /* no '/' - we need to search the path */
1165 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001166 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001167 }
thughes4ad52d02004-06-27 17:37:21 +00001168 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001169}
1170
1171
1172/*====================================================================*/
1173/*=== Loading tools ===*/
1174/*====================================================================*/
1175
1176static void list_tools(void)
1177{
1178 DIR *dir = opendir(VG_(libdir));
1179 struct dirent *de;
1180 int first = 1;
1181
1182 if (dir == NULL) {
1183 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001184 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001185 return;
1186 }
1187
nethercotef4928da2004-06-15 10:54:40 +00001188 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001189 int len = strlen(de->d_name);
1190
njn063c5402004-11-22 16:58:05 +00001191 /* look for vgtool_TOOL.so names */
1192 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1193 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001194 VG_STREQ(de->d_name + len - 3, ".so")) {
1195 if (first) {
1196 fprintf(stderr, "Available tools:\n");
1197 first = 0;
1198 }
1199 de->d_name[len-3] = '\0';
1200 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001201 }
1202 }
1203
1204 closedir(dir);
1205
1206 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001207 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1208 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001209}
1210
1211
1212/* Find and load a tool, and check it looks ok. Also looks to see if there's
1213 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1214static void load_tool( const char *toolname, void** handle_out,
1215 ToolInfo** toolinfo_out, char **preloadpath_out )
1216{
1217 Bool ok;
1218 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1219 char buf[len];
1220 void* handle;
1221 ToolInfo* toolinfo;
1222 char* preloadpath = NULL;
1223 Int* vg_malloc_redzonep;
1224
1225 // XXX: allowing full paths for --tool option -- does it make sense?
1226 // Doesn't allow for vgpreload_<tool>.so.
1227
1228 if (strchr(toolname, '/') != 0) {
1229 /* toolname contains '/', and so must be a pathname */
1230 handle = dlopen(toolname, RTLD_NOW);
1231 } else {
1232 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001233 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001234 handle = dlopen(buf, RTLD_NOW);
1235
1236 if (handle != NULL) {
1237 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1238 if (access(buf, R_OK) == 0) {
1239 preloadpath = strdup(buf);
1240 vg_assert(NULL != preloadpath);
1241 }
1242 }
1243 }
1244
1245 ok = (NULL != handle);
1246 if (!ok) {
1247 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1248 goto bad_load;
1249 }
1250
njn26f02512004-11-22 18:33:15 +00001251 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001252 ok = (NULL != toolinfo);
1253 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001254 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001255 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1256 goto bad_load;
1257 }
1258
1259 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1260 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1261 toolinfo->sk_pre_clo_init != NULL);
1262 if (!ok) {
1263 fprintf(stderr, "Error:\n"
1264 " Tool and core interface versions do not match.\n"
1265 " Interface version used by core is: %d.%d (size %d)\n"
1266 " Interface version used by tool is: %d.%d (size %d)\n"
1267 " The major version numbers must match.\n",
1268 VG_CORE_INTERFACE_MAJOR_VERSION,
1269 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001270 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001271 toolinfo->interface_major_version,
1272 toolinfo->interface_minor_version,
1273 toolinfo->sizeof_ToolInfo);
1274 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1275 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001276 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001277 else
nethercote996901a2004-08-03 13:29:09 +00001278 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001279 goto bad_load;
1280 }
1281
1282 // Set redzone size for V's allocator
1283 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1284 if ( NULL != vg_malloc_redzonep ) {
1285 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1286 }
1287
1288 vg_assert(NULL != handle && NULL != toolinfo);
1289 *handle_out = handle;
1290 *toolinfo_out = toolinfo;
1291 *preloadpath_out = preloadpath;
1292 return;
1293
1294
1295 bad_load:
1296 if (handle != NULL)
1297 dlclose(handle);
1298
nethercotef4928da2004-06-15 10:54:40 +00001299 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001300 list_tools();
1301 exit(127);
1302}
1303
nethercotef4928da2004-06-15 10:54:40 +00001304
1305/*====================================================================*/
1306/*=== Command line errors ===*/
1307/*====================================================================*/
1308
1309static void abort_msg ( void )
1310{
nethercotef8548672004-06-21 12:42:35 +00001311 VG_(clo_log_to) = VgLogTo_Fd;
1312 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001313}
1314
1315void VG_(bad_option) ( Char* opt )
1316{
1317 abort_msg();
1318 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1319 VG_(printf)("valgrind: Use --help for more information.\n");
1320 VG_(exit)(1);
1321}
1322
1323static void missing_tool_option ( void )
1324{
1325 abort_msg();
1326 VG_(printf)("valgrind: Missing --tool option\n");
1327 list_tools();
1328 VG_(printf)("valgrind: Use --help for more information.\n");
1329 VG_(exit)(1);
1330}
1331
1332static void missing_prog ( void )
1333{
1334 abort_msg();
1335 VG_(printf)("valgrind: no program specified\n");
1336 VG_(printf)("valgrind: Use --help for more information.\n");
1337 VG_(exit)(1);
1338}
1339
1340static void config_error ( Char* msg )
1341{
1342 abort_msg();
1343 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1344 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1345 VG_(exit)(1);
1346}
1347
1348
nethercote71980f02004-01-24 18:18:54 +00001349/*====================================================================*/
1350/*=== Loading the client ===*/
1351/*====================================================================*/
1352
nethercotef4928da2004-06-15 10:54:40 +00001353static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001354 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1355{
1356 // If they didn't specify an executable with --exec, and didn't specify
1357 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001358 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001359 if (cl_argv[0] == NULL ||
1360 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1361 {
nethercotef4928da2004-06-15 10:54:40 +00001362 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001363 }
1364 }
1365
1366 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001367 info->exe_base = VG_(client_base);
1368 info->exe_end = VG_(client_end);
1369 info->argv = cl_argv;
1370
nethercotef4928da2004-06-15 10:54:40 +00001371 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001372 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001373 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001374 info->interp_name = NULL;
1375 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001376 } else {
1377 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001378 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001379 ret = do_exec(exec, info);
1380 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001381 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1382 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001383 exit(127);
1384 }
1385 }
1386
1387 /* Copy necessary bits of 'info' that were filled in */
1388 *client_eip = info->init_eip;
1389 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1390}
1391
nethercote969ecf12004-10-13 17:29:01 +00001392/*====================================================================*/
1393/*=== Address space unpadding ===*/
1394/*====================================================================*/
1395
1396typedef struct {
1397 char* killpad_start;
1398 char* killpad_end;
1399 struct stat* killpad_padstat;
1400} killpad_extra;
1401
1402static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1403 int maj, int min, int ino, void* ex)
1404{
1405 killpad_extra* extra = ex;
1406 void *b, *e;
1407 int res;
1408
1409 vg_assert(NULL != extra->killpad_padstat);
1410
1411 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1412 extra->killpad_padstat->st_ino != ino)
1413 return 1;
1414
1415 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1416 return 1;
1417
1418 if (segstart <= extra->killpad_start)
1419 b = extra->killpad_start;
1420 else
1421 b = segstart;
1422
1423 if (segend >= extra->killpad_end)
1424 e = extra->killpad_end;
1425 else
1426 e = segend;
1427
1428 res = munmap(b, (char *)e-(char *)b);
1429 vg_assert(0 == res);
1430
1431 return 1;
1432}
1433
1434// Remove padding of 'padfile' from a range of address space.
1435void as_unpad(void *start, void *end, int padfile)
1436{
1437 static struct stat padstat;
1438 killpad_extra extra;
1439 int res;
1440
1441 vg_assert(padfile > 0);
1442
1443 res = fstat(padfile, &padstat);
1444 vg_assert(0 == res);
1445 extra.killpad_padstat = &padstat;
1446 extra.killpad_start = start;
1447 extra.killpad_end = end;
1448 foreach_map(killpad, &extra);
1449}
1450
1451void as_closepadfile(int padfile)
1452{
1453 int res = close(padfile);
1454 vg_assert(0 == res);
1455}
1456
nethercote71980f02004-01-24 18:18:54 +00001457
1458/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001459/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001460/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001461
njn25e49d8e72002-09-23 09:36:25 +00001462/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001463VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001464Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001465Bool VG_(clo_db_attach) = False;
1466Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001467Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001468Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001469Int VG_(clo_verbosity) = 1;
1470Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001471Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001472
nethercotef1e5e152004-09-01 23:58:16 +00001473/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001474 fd is initially stdout, for --help, but gets moved to stderr by default
1475 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001476VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001477Int VG_(clo_log_fd) = 1;
1478Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001479
thughes6233a382004-08-21 11:10:44 +00001480Bool VG_(clo_time_stamp) = False;
1481
sewardj6024b212003-07-13 10:54:33 +00001482Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001483Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001484Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001485Bool VG_(clo_profile) = False;
1486Bool VG_(clo_single_step) = False;
1487Bool VG_(clo_optimise) = True;
1488UChar VG_(clo_trace_codegen) = 0; // 00000000b
1489Bool VG_(clo_trace_syscalls) = False;
1490Bool VG_(clo_trace_signals) = False;
1491Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001492Bool VG_(clo_trace_sched) = False;
1493Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001494Int VG_(clo_dump_error) = 0;
1495Int VG_(clo_backtrace_size) = 4;
1496Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001497Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001498Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001499Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001500Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001501Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001502Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001503
jsgf855d93d2003-10-13 22:26:55 +00001504static Bool VG_(clo_wait_for_gdb) = False;
1505
1506/* If we're doing signal routing, poll for signals every 50mS by
1507 default. */
1508Int VG_(clo_signal_polltime) = 50;
1509
1510/* These flags reduce thread wakeup latency on syscall completion and
1511 signal delivery, respectively. The downside is possible unfairness. */
1512Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1513Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1514
sewardjde4a1d02002-03-22 01:27:54 +00001515
nethercote6c999f22004-01-31 22:55:15 +00001516void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001517{
njn25e49d8e72002-09-23 09:36:25 +00001518 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001519"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001520"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001521" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001522" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001523" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001524" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001525" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001526" -q --quiet run silently; only print error msgs\n"
1527" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001528" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001529" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001530" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001531"\n"
1532" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001533" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1534" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1535" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1536" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1537" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001538" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001539"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001540" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001541" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1542" --log-file=<file> log messages to <file>.pid<pid>\n"
1543" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001544" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1545" --num-callers=<number> show <num> callers in stack traces [4]\n"
1546" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1547" --show-below-main=no|yes continue stack traces below main() [no]\n"
1548" --suppressions=<filename> suppress errors described in <filename>\n"
1549" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001550" --db-attach=no|yes start debugger when errors detected? [no]\n"
1551" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1552" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001553"\n";
njn7cf0bd32002-06-08 13:36:03 +00001554
njn25e49d8e72002-09-23 09:36:25 +00001555 Char* usage2 =
1556"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001557" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001558" --sanity-level=<number> level of sanity checking to do [1]\n"
1559" --single-step=no|yes translate each instr separately? [no]\n"
1560" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001561" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001562" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001563" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001564" --trace-codegen=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
njn25e49d8e72002-09-23 09:36:25 +00001565" --trace-syscalls=no|yes show all system calls? [no]\n"
1566" --trace-signals=no|yes show signal handling details? [no]\n"
1567" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001568" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001569" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001570" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001571"\n"
sewardj8b635a42004-11-22 19:01:47 +00001572" --vex-iropt-verbosity 0 .. 9 [0]\n"
1573" --vex-iropt-level 0 .. 2 [2]\n"
1574" --vex-iropt-precise-memory-exns [no]\n"
1575" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1576" --vex-guest-max-insns 1 .. 100 [50]\n"
1577" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1578"\n"
sewardj2a99cf62004-11-24 10:44:19 +00001579" --trace-codegen values (omit the middle space):\n"
1580" 1000 0000 show conversion into IR\n"
1581" 0100 0000 show after initial opt\n"
1582" 0010 0000 show after instrumentation\n"
1583" 0001 0000 show after second opt\n"
1584" 0000 1000 show after tree building\n"
1585" 0000 0100 show selecting insns\n"
1586" 0000 0010 show after reg-alloc\n"
1587" 0000 0001 show final assembly\n"
1588"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001589" debugging options for Valgrind tools that report errors\n"
1590" --dump-error=<number> show translation for basic block associated\n"
1591" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001592"\n";
njn3e884182003-04-15 13:03:23 +00001593
1594 Char* usage3 =
1595"\n"
nethercote71980f02004-01-24 18:18:54 +00001596" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001597"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001598" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001599" and licensed under the GNU General Public License, version 2.\n"
1600" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001601"\n"
nethercote137bc552003-11-14 17:47:54 +00001602" Tools are copyright and licensed by their authors. See each\n"
1603" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001604"\n";
njn7cf0bd32002-06-08 13:36:03 +00001605
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 VG_(printf)(usage1);
1607 if (VG_(details).name) {
1608 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001609 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001610 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001611 else
1612 VG_(printf)(" (none)\n");
1613 }
nethercote6c999f22004-01-31 22:55:15 +00001614 if (debug_help) {
1615 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001616
nethercote6c999f22004-01-31 22:55:15 +00001617 if (VG_(details).name) {
1618 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1619
1620 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001621 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001622 else
1623 VG_(printf)(" (none)\n");
1624 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001625 }
nethercote421281e2003-11-20 16:20:55 +00001626 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001627 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001628}
sewardjde4a1d02002-03-22 01:27:54 +00001629
nethercote71980f02004-01-24 18:18:54 +00001630static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001631 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001632{
nethercote71980f02004-01-24 18:18:54 +00001633 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001634
sewardj8b635a42004-11-22 19:01:47 +00001635 LibVEX_default_VexControl(& VG_(clo_vex_control));
1636
nethercote71980f02004-01-24 18:18:54 +00001637 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001638 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001639
nethercotef6a1d502004-08-09 12:21:57 +00001640 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001641 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001642 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001643
nethercotef6a1d502004-08-09 12:21:57 +00001644 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1645 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001646 *need_help = 1;
1647
nethercotef6a1d502004-08-09 12:21:57 +00001648 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001649 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001650
nethercotef6c99d72004-11-09 14:35:43 +00001651 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001652 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001653
nethercotef6a1d502004-08-09 12:21:57 +00001654 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1655 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001656 }
1657 }
1658
nethercotef4928da2004-06-15 10:54:40 +00001659 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001660 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001661 if (0 == *need_help) {
1662 // neither --tool nor --help/--help-debug specified
1663 missing_tool_option();
1664 } else {
1665 // Give help message, without any tool-specific help
1666 usage(/*help-debug?*/2 == *need_help);
1667 }
nethercote71980f02004-01-24 18:18:54 +00001668 }
1669}
1670
nethercote5ee67ca2004-06-22 14:00:09 +00001671static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001672{
nethercotef8548672004-06-21 12:42:35 +00001673 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001674 Int *auxp;
1675 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001676
nethercotee1730692003-11-20 10:38:07 +00001677 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001678 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001679
sewardj19d81412002-06-03 01:10:40 +00001680 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001681 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001682 config_error("Please use absolute paths in "
1683 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001684
nethercote73b526f2004-10-31 18:48:21 +00001685 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001686 switch(auxp[0]) {
nethercote73b526f2004-10-31 18:48:21 +00001687 case AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001688 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001689 break;
sewardjde4a1d02002-03-22 01:27:54 +00001690 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001691 }
sewardjde4a1d02002-03-22 01:27:54 +00001692
nethercotef6a1d502004-08-09 12:21:57 +00001693 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001694
nethercotef6a1d502004-08-09 12:21:57 +00001695 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001696 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001697
thughes3bfd5a02004-07-18 08:05:44 +00001698 /* Look for a colon in the switch name */
1699 while (*colon && *colon != ':' && *colon != '=')
1700 colon++;
nethercote71980f02004-01-24 18:18:54 +00001701
1702 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001703 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001704 if (VG_CLO_STREQN(2, arg, "--") &&
1705 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1706 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1707 {
1708 // prefix matches, convert "--toolname:foo" to "--foo"
1709 if (0)
1710 VG_(printf)("tool-specific arg: %s\n", arg);
1711 arg += toolname_len + 1;
1712 arg[0] = '-';
1713 arg[1] = '-';
1714
1715 } else {
1716 // prefix doesn't match, skip to next arg
1717 continue;
1718 }
1719 }
1720
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001722 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001723 continue;
nethercote71980f02004-01-24 18:18:54 +00001724 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001725 continue;
1726
nethercote71980f02004-01-24 18:18:54 +00001727 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001728 continue;
nethercote27fec902004-06-16 21:26:32 +00001729
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQ(arg, "-v") ||
1731 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001732 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001733
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "-q") ||
1735 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001736 VG_(clo_verbosity)--;
1737
nethercote27fec902004-06-16 21:26:32 +00001738 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1739 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1740 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1741 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1742 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1743 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1744 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1745 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1746 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1747 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1748 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1749 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1750 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1751 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001752 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001753 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1754 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1755 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1756 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1757 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1758 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1759 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001760
nethercote27fec902004-06-16 21:26:32 +00001761 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1762 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001763
nethercote27fec902004-06-16 21:26:32 +00001764 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1765 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1766 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001767 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001768 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1769 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001770
sewardj8b635a42004-11-22 19:01:47 +00001771 else VG_BNUM_CLO("--vex-iropt-verbosity",
1772 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1773 else VG_BNUM_CLO("--vex-iropt-level",
1774 VG_(clo_vex_control).iropt_level, 0, 2)
1775 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1776 VG_(clo_vex_control).iropt_precise_memory_exns)
1777 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1778 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1779 else VG_BNUM_CLO("--vex-guest-max-insns",
1780 VG_(clo_vex_control).guest_max_insns, 1, 100)
1781 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1782 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1783
nethercotef8548672004-06-21 12:42:35 +00001784 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001785 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001786 VG_(clo_log_to) = VgLogTo_Fd;
1787 VG_(clo_log_name) = NULL;
1788 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1789 }
1790 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1791 VG_(clo_log_to) = VgLogTo_Fd;
1792 VG_(clo_log_name) = NULL;
1793 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001794 }
1795
nethercotef8548672004-06-21 12:42:35 +00001796 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001797 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001798 VG_(clo_log_to) = VgLogTo_File;
1799 VG_(clo_log_name) = &arg[10];
1800 }
1801 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1802 VG_(clo_log_to) = VgLogTo_File;
1803 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001804 }
sewardjde4a1d02002-03-22 01:27:54 +00001805
nethercotef8548672004-06-21 12:42:35 +00001806 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001807 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001808 VG_(clo_log_to) = VgLogTo_Socket;
1809 VG_(clo_log_name) = &arg[12];
1810 }
1811 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1812 VG_(clo_log_to) = VgLogTo_Socket;
1813 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001814 }
1815
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001817 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001818 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001819 VG_(message)(Vg_UserMsg,
1820 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001822 }
nethercote71980f02004-01-24 18:18:54 +00001823 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001824 VG_(clo_n_suppressions)++;
1825 }
sewardjde4a1d02002-03-22 01:27:54 +00001826
njn25e49d8e72002-09-23 09:36:25 +00001827 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001829 Int j;
nethercote71980f02004-01-24 18:18:54 +00001830 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001831
sewardj2a99cf62004-11-24 10:44:19 +00001832 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001833 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +00001834 "--trace-codegen argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001835 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001836 }
sewardj8b635a42004-11-22 19:01:47 +00001837 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001838 if ('0' == opt[j]) { /* do nothing */ }
sewardj8b635a42004-11-22 19:01:47 +00001839 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001840 else {
1841 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1842 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001843 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001844 }
1845 }
1846 }
sewardjde4a1d02002-03-22 01:27:54 +00001847
nethercote71980f02004-01-24 18:18:54 +00001848 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001849 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001850 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001851 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001852 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001853 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001854
nethercote71980f02004-01-24 18:18:54 +00001855 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001856 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001857 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001858 }
sewardjde4a1d02002-03-22 01:27:54 +00001859 }
1860
nethercote27fec902004-06-16 21:26:32 +00001861 // Check various option values
1862
njnf9ebf672003-05-12 21:41:30 +00001863 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001864 VG_(clo_verbosity) = 0;
1865
nethercote04d0fbc2004-01-26 16:48:06 +00001866 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001867 VG_(message)(Vg_UserMsg, "");
1868 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001869 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001870 VG_(message)(Vg_UserMsg,
1871 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001872 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001873 }
1874
nethercotef8548672004-06-21 12:42:35 +00001875 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001876 should be connected to whatever sink has been selected, and we
1877 indiscriminately chuck stuff into it without worrying what the
1878 nature of it is. Oh the wonder of Unix streams. */
1879
nethercotee1730692003-11-20 10:38:07 +00001880 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001881 the terminal any problems to do with processing command line
1882 opts. */
nethercotef8548672004-06-21 12:42:35 +00001883 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001884 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001885
1886 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001887
sewardj4cf05692002-10-27 20:28:29 +00001888 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001889 vg_assert(VG_(clo_log_name) == NULL);
1890 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001891 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001892
sewardj4cf05692002-10-27 20:28:29 +00001893 case VgLogTo_File: {
1894 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001895 Int seq = 0;
1896 Int pid = VG_(getpid)();
1897
nethercotef8548672004-06-21 12:42:35 +00001898 vg_assert(VG_(clo_log_name) != NULL);
1899 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001900
nethercote71980f02004-01-24 18:18:54 +00001901 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001902 if (seq == 0)
1903 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001904 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001905 else
1906 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001907 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001908 seq++;
1909
nethercotef8548672004-06-21 12:42:35 +00001910 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001911 = VG_(open)(logfilename,
1912 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1913 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001914 if (eventually_log_fd >= 0) {
1915 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001916 break;
1917 } else {
nethercotef8548672004-06-21 12:42:35 +00001918 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001919 VG_(message)(Vg_UserMsg,
1920 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001921 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001922 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001923 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001924 break;
1925 }
1926 }
1927 }
sewardj4cf05692002-10-27 20:28:29 +00001928 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001929 }
1930
1931 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001932 vg_assert(VG_(clo_log_name) != NULL);
1933 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1934 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1935 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001937 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001938 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001939 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001940 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001941 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001942 }
nethercotef8548672004-06-21 12:42:35 +00001943 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001944 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001945 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001946 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001947 VG_(message)(Vg_UserMsg,
1948 "Log messages will sent to stderr instead." );
1949 VG_(message)(Vg_UserMsg,
1950 "" );
1951 /* We don't change anything here. */
1952 } else {
nethercotef8548672004-06-21 12:42:35 +00001953 vg_assert(eventually_log_fd > 0);
1954 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001955 VG_(logging_to_filedes) = False;
1956 }
sewardj73cf3bc2002-11-03 03:20:15 +00001957 break;
1958 }
1959
sewardj4cf05692002-10-27 20:28:29 +00001960 }
1961
nethercotef8548672004-06-21 12:42:35 +00001962 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001963 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001964 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001965 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1966 else {
nethercotef8548672004-06-21 12:42:35 +00001967 VG_(clo_log_fd) = eventually_log_fd;
1968 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001969 }
1970
sewardj4cf05692002-10-27 20:28:29 +00001971 /* Ok, the logging sink is running now. Print a suitable preamble.
1972 If logging to file or a socket, write details of parent PID and
1973 command line args, to help people trying to interpret the
1974 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001975
sewardj83adf412002-05-01 01:25:45 +00001976 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001977 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001978 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001979 VG_(details).name,
1980 NULL == VG_(details).version ? "" : "-",
1981 NULL == VG_(details).version
1982 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001983 VG_(details).description,
1984 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001985 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001986
njnd04b7c62002-10-03 14:05:52 +00001987 /* Core details */
1988 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001989 "Using valgrind-%s, a program supervision framework for %s.",
1990 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001992 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001993 }
1994
nethercotec1e395d2003-11-10 13:26:49 +00001995 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001996 VG_(message)(Vg_UserMsg, "");
1997 VG_(message)(Vg_UserMsg,
1998 "My PID = %d, parent PID = %d. Prog and args are:",
1999 VG_(getpid)(), VG_(getppid)() );
2000 for (i = 0; i < VG_(client_argc); i++)
2001 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2002 }
2003
sewardjde4a1d02002-03-22 01:27:54 +00002004 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002005 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002006 if (VG_(clo_log_to) != VgLogTo_Fd)
2007 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002008 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002009 VG_(message)(Vg_UserMsg, "Command line");
2010 for (i = 0; i < VG_(client_argc); i++)
2011 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2012
sewardjde4a1d02002-03-22 01:27:54 +00002013 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002014 for (i = 1; i < vg_argc; i++) {
2015 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
nethercotea70f7352004-04-18 12:08:46 +00002017
2018 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2019 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2020 if (fd < 0) {
2021 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2022 } else {
2023 #define BUF_LEN 256
2024 Char version_buf[BUF_LEN];
2025 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2026 vg_assert(n <= 256);
2027 if (n > 0) {
2028 version_buf[n-1] = '\0';
2029 VG_(message)(Vg_UserMsg, " %s", version_buf);
2030 } else {
2031 VG_(message)(Vg_UserMsg, " (empty?)");
2032 }
2033 VG_(close)(fd);
2034 #undef BUF_LEN
2035 }
sewardjde4a1d02002-03-22 01:27:54 +00002036 }
2037
fitzhardinge98abfc72003-12-16 02:05:15 +00002038 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002039 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002040 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002041 needs one, load the default */
2042 static const Char default_supp[] = "default.supp";
2043 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2044 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2045 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2046 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2047 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002048 }
sewardj4cf05692002-10-27 20:28:29 +00002049
njn6a230532003-07-21 10:38:23 +00002050 if (VG_(clo_gen_suppressions) &&
njn95ec8702004-11-22 16:46:13 +00002051 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002052 VG_(message)(Vg_UserMsg,
2053 "Can't use --gen-suppressions=yes with this tool,");
2054 VG_(message)(Vg_UserMsg,
2055 "as it doesn't generate errors.");
2056 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002057 }
sewardjde4a1d02002-03-22 01:27:54 +00002058}
2059
nethercotef6a1d502004-08-09 12:21:57 +00002060// Build the string for VALGRINDCLO.
2061Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2062{
2063 /* If we're tracing the children, then we need to start it
2064 with our starter+arguments, which are copied into VALGRINDCLO,
2065 except the --exec= option is changed if present.
2066 */
2067 Int i;
2068 Char *exec;
2069 Char *cp;
2070 Char *optvar;
2071 Int optlen, execlen;
2072
2073 // All these allocated blocks are not free - because we're either
2074 // going to exec, or panic when we fail.
2075
2076 // Create --exec= option: "--exec=<exename>"
2077 exec = VG_(arena_malloc)(VG_AR_CORE,
2078 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2079 vg_assert(NULL != exec);
2080 VG_(sprintf)(exec, "--exec=%s", exename);
2081
2082 // Allocate space for optvar (may overestimate by counting --exec twice,
2083 // no matter)
2084 optlen = 1;
2085 for (i = 0; i < vg_argc; i++)
2086 optlen += VG_(strlen)(vg_argv[i]) + 1;
2087 optlen += VG_(strlen)(exec)+1;
2088 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2089
2090 // Copy all valgrind args except the old --exec (if present)
2091 // VG_CLO_SEP is the separator.
2092 cp = optvar;
2093 for (i = 1; i < vg_argc; i++) {
2094 Char *arg = vg_argv[i];
2095
2096 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2097 // don't copy existing --exec= arg
2098 } else if (VG_(strcmp)(arg, "--") == 0) {
2099 // stop at "--"
2100 break;
2101 } else {
2102 // copy non "--exec" arg
2103 Int len = VG_(strlen)(arg);
2104 VG_(memcpy)(cp, arg, len);
2105 cp += len;
2106 *cp++ = VG_CLO_SEP;
2107 }
2108 }
2109 // Add the new --exec= option
2110 execlen = VG_(strlen)(exec);
2111 VG_(memcpy)(cp, exec, execlen);
2112 cp += execlen;
2113 *cp++ = VG_CLO_SEP;
2114
2115 *cp = '\0';
2116
2117 return optvar;
2118}
2119
2120// Build "/proc/self/fd/<execfd>".
2121Char* VG_(build_child_exename)( void )
2122{
2123 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2124 vg_assert(NULL != exename);
2125 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2126 return exename;
2127}
2128
sewardjde4a1d02002-03-22 01:27:54 +00002129
nethercote71980f02004-01-24 18:18:54 +00002130/*====================================================================*/
2131/*=== File descriptor setup ===*/
2132/*====================================================================*/
2133
2134static void setup_file_descriptors(void)
2135{
2136 struct vki_rlimit rl;
2137
2138 /* Get the current file descriptor limits. */
2139 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2140 rl.rlim_cur = 1024;
2141 rl.rlim_max = 1024;
2142 }
2143
2144 /* Work out where to move the soft limit to. */
2145 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2146 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2147 } else {
2148 rl.rlim_cur = rl.rlim_max;
2149 }
2150
2151 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002152 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2153 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002154
2155 /* Update the soft limit. */
2156 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2157
nethercotef6a1d502004-08-09 12:21:57 +00002158 if (vgexecfd != -1)
2159 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002160 if (VG_(clexecfd) != -1)
2161 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2162}
2163
2164
2165/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002166/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002167/*====================================================================*/
2168
nethercote4ad74312004-10-26 09:59:49 +00002169Bool VG_(need_to_handle_SP_assignment)(void)
nethercote71980f02004-01-24 18:18:54 +00002170{
2171 return ( VG_(defined_new_mem_stack_4)() ||
2172 VG_(defined_die_mem_stack_4)() ||
2173 VG_(defined_new_mem_stack_8)() ||
2174 VG_(defined_die_mem_stack_8)() ||
2175 VG_(defined_new_mem_stack_12)() ||
2176 VG_(defined_die_mem_stack_12)() ||
2177 VG_(defined_new_mem_stack_16)() ||
2178 VG_(defined_die_mem_stack_16)() ||
2179 VG_(defined_new_mem_stack_32)() ||
2180 VG_(defined_die_mem_stack_32)() ||
2181 VG_(defined_new_mem_stack)() ||
2182 VG_(defined_die_mem_stack)()
2183 );
2184}
2185
sewardj5f07b662002-04-23 16:52:51 +00002186
nethercote71980f02004-01-24 18:18:54 +00002187/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002188/*=== Initialise program data/text, etc. ===*/
2189/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002190
nethercote71980f02004-01-24 18:18:54 +00002191static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002192 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002193 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002194{
nethercote71980f02004-01-24 18:18:54 +00002195 UInt prot = 0;
2196 UInt flags = SF_MMAP|SF_NOSYMS;
2197 Bool is_stack_segment;
2198
2199 is_stack_segment =
2200 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2201
2202 /* Only record valgrind mappings for now, without loading any
2203 symbols. This is so we know where the free space is before we
2204 start allocating more memory (note: heap is OK, it's just mmap
2205 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002206 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002207 flags |= SF_VALGRIND;
2208 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2209 }
sewardjde4a1d02002-03-22 01:27:54 +00002210}
2211
nethercote71980f02004-01-24 18:18:54 +00002212// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002213Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002214
nethercote71980f02004-01-24 18:18:54 +00002215static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002216 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002217 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002218{
nethercote71980f02004-01-24 18:18:54 +00002219 UInt prot = 0;
2220 UInt flags;
2221 Bool is_stack_segment;
2222 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 is_stack_segment
2225 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002226
nethercote71980f02004-01-24 18:18:54 +00002227 if (rr == 'r') prot |= VKI_PROT_READ;
2228 if (ww == 'w') prot |= VKI_PROT_WRITE;
2229 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002230
nethercote71980f02004-01-24 18:18:54 +00002231 if (is_stack_segment)
2232 flags = SF_STACK | SF_GROWDOWN;
2233 else
2234 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002235
nethercote71980f02004-01-24 18:18:54 +00002236 if (filename != NULL)
2237 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002238
nethercote820bd8c2004-09-07 23:04:49 +00002239 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002240 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002241
nethercote71980f02004-01-24 18:18:54 +00002242 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002243
nethercote71980f02004-01-24 18:18:54 +00002244 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2245 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002246
nethercote71980f02004-01-24 18:18:54 +00002247 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002248 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002249 vg_assert(0 != r_esp);
2250 if (is_stack_segment) {
2251 if (0)
2252 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2253 start,r_esp);
2254 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002255 }
sewardjde4a1d02002-03-22 01:27:54 +00002256}
2257
2258
nethercote71980f02004-01-24 18:18:54 +00002259/*====================================================================*/
2260/*=== Sanity check machinery (permanently engaged) ===*/
2261/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002262
2263/* A fast sanity check -- suitable for calling circa once per
2264 millisecond. */
2265
nethercote885dd912004-08-03 23:14:00 +00002266void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002267{
njn37cea302002-09-30 11:24:00 +00002268 VGP_PUSHCC(VgpCoreCheapSanity);
2269
nethercote27fec902004-06-16 21:26:32 +00002270 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002271
2272 /* --- First do all the tests that we can do quickly. ---*/
2273
nethercote297effd2004-08-02 15:07:57 +00002274 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002275
njn25e49d8e72002-09-23 09:36:25 +00002276 /* Check stuff pertaining to the memory check system. */
2277
2278 /* Check that nobody has spuriously claimed that the first or
2279 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002280 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002281 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002282 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002283 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002284 }
njn25e49d8e72002-09-23 09:36:25 +00002285
2286 /* --- Now some more expensive checks. ---*/
2287
2288 /* Once every 25 times, check some more expensive stuff. */
2289 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002290 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002291 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002292
njn37cea302002-09-30 11:24:00 +00002293 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002294 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002295
nethercote885dd912004-08-03 23:14:00 +00002296 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002297
njn25e49d8e72002-09-23 09:36:25 +00002298# if 0
2299 { void zzzmemscan(void); zzzmemscan(); }
2300# endif
2301
nethercote297effd2004-08-02 15:07:57 +00002302 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002303 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002304
2305 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002306 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002307 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002308 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002309 }
2310 /*
nethercote297effd2004-08-02 15:07:57 +00002311 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002312 */
njn37cea302002-09-30 11:24:00 +00002313 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002314 }
2315
nethercote27fec902004-06-16 21:26:32 +00002316 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002317 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002318 /* Check sanity of the low-level memory manager. Note that bugs
2319 in the client's code can cause this to fail, so we don't do
2320 this check unless specially asked for. And because it's
2321 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002322 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002323 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002324 }
njn37cea302002-09-30 11:24:00 +00002325 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002326}
nethercote71980f02004-01-24 18:18:54 +00002327
2328
2329/*====================================================================*/
2330/*=== main() ===*/
2331/*====================================================================*/
2332
nethercotec314eba2004-07-15 12:59:41 +00002333/*
2334 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002335 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002336 loads the client executable (and the dynamic linker, if necessary)
2337 into the client part, and calls into Valgrind proper.
2338
2339 The code is careful not to allow spurious mappings to appear in the
2340 wrong parts of the address space. In particular, to make sure
2341 dlopen puts things in the right place, it will pad out the forbidden
2342 chunks of address space so that dlopen is forced to put things where
2343 we want them.
2344
2345 The memory map it creates is:
2346
2347 CLIENT_BASE +-------------------------+
2348 | client address space |
2349 : :
2350 : :
2351 | client stack |
2352 client_end +-------------------------+
2353 | redzone |
2354 shadow_base +-------------------------+
2355 | |
nethercote996901a2004-08-03 13:29:09 +00002356 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002357 | (may be 0 sized) |
2358 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002359 valgrind_base +-------------------------+
2360 | kickstart executable |
2361 | valgrind heap vvvvvvvvv| (barely used)
2362 - -
2363 | valgrind .so files |
2364 | and mappings |
2365 - -
2366 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002367 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002368 : kernel :
2369
2370 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2371 VG_(mmap)(), we need to build the segment skip-list, so we know where
2372 we can put things. However, building that structure requires
2373 allocating memory. So we need to a bootstrapping process. It's done
2374 by making VG_(arena_malloc)() have a special static superblock that's
2375 used for the first 1MB's worth of allocations. This is enough to
2376 build the segment skip-list.
2377*/
2378
nethercote31779c72004-07-30 21:50:15 +00002379static int prmap(char *start, char *end, const char *perm, off_t off,
2380 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002381 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2382 start, end, perm, maj, min, ino);
2383 return True;
2384}
2385
nethercote71980f02004-01-24 18:18:54 +00002386int main(int argc, char **argv)
2387{
2388 char **cl_argv;
2389 const char *tool = NULL;
2390 const char *exec = NULL;
2391 char *preload; /* tool-specific LD_PRELOAD .so */
2392 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002393 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002394 struct exeinfo info;
2395 ToolInfo *toolinfo = NULL;
2396 void *tool_dlhandle;
2397 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002398 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002399 UInt * client_auxv;
2400 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002401 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002402 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002403 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002404 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002405 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2406
nethercote71980f02004-01-24 18:18:54 +00002407
2408 //============================================================
2409 // Nb: startup is complex. Prerequisites are shown at every step.
2410 //
2411 // *** Be very careful when messing with the order ***
2412 //============================================================
2413
nethercotef4928da2004-06-15 10:54:40 +00002414 //============================================================
2415 // Command line argument handling order:
2416 // * If --help/--help-debug are present, show usage message
2417 // (if --tool is also present, that includes the tool-specific usage)
2418 // * Then, if --tool is missing, abort with error msg
2419 // * Then, if client is missing, abort with error msg
2420 // * Then, if any cmdline args are bad, abort with error msg
2421 //============================================================
2422
fitzhardingeb50068f2004-02-24 23:42:55 +00002423 // Get the current process datasize rlimit, and set it to zero.
2424 // This prevents any internal uses of brk() from having any effect.
2425 // We remember the old value so we can restore it on exec, so that
2426 // child processes will have a reasonable brk value.
2427 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2428 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2429 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002430
2431 // Get the current process stack rlimit.
2432 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2433
nethercote71980f02004-01-24 18:18:54 +00002434 //--------------------------------------------------------------
2435 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002436 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002437 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002438 {
2439 void* init_sp = argv - 1;
2440 padfile = scan_auxv(init_sp);
2441 }
nethercote71980f02004-01-24 18:18:54 +00002442
2443 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002444 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002445 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002446 }
2447
2448 //--------------------------------------------------------------
2449 // Look for alternative libdir
2450 // p: n/a
2451 //--------------------------------------------------------------
2452 { char *cp = getenv(VALGRINDLIB);
2453 if (cp != NULL)
2454 VG_(libdir) = cp;
2455 }
2456
2457 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002458 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2459 // Pre-process the command line.
2460 // p: n/a
2461 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002462 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002463 pre_process_cmd_line_options(&need_help, &tool, &exec);
2464
2465 //==============================================================
2466 // Nb: once a tool is specified, the tool.so must be loaded even if
2467 // they specified --help or didn't specify a client program.
2468 //==============================================================
2469
2470 //--------------------------------------------------------------
2471 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002472 // p: set-libdir [for VG_(libdir)]
2473 // p: pre_process_cmd_line_options() [for 'tool']
2474 //--------------------------------------------------------------
2475 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2476
2477 //==============================================================
2478 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002479 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002480 //==============================================================
2481
2482 //--------------------------------------------------------------
2483 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002484 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002485 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002486 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002487
2488 //--------------------------------------------------------------
2489 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002490 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2491 // p: layout_remaining_space [so there's space]
2492 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002493 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002494
2495 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002496 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002497 // p: layout_remaining_space() [everything must be mapped in before now]
2498 // p: load_client() [ditto]
2499 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002500 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2501 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002502
2503 //--------------------------------------------------------------
2504 // Set up client's environment
2505 // p: set-libdir [for VG_(libdir)]
2506 // p: load_tool() [for 'preload']
2507 //--------------------------------------------------------------
2508 env = fix_environment(environ, preload);
2509
2510 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002511 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002512 // p: load_client() [for 'info']
2513 // p: fix_environment() [for 'env']
2514 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002515 {
2516 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002517 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2518 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002519 }
nethercote71980f02004-01-24 18:18:54 +00002520
2521 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002522 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002523 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002524 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002525
2526 //==============================================================
2527 // Finished setting up operating environment. Now initialise
2528 // Valgrind. (This is where the old VG_(main)() started.)
2529 //==============================================================
2530
2531 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002532 // atfork
2533 // p: n/a
2534 //--------------------------------------------------------------
2535 VG_(atfork)(NULL, NULL, newpid);
2536 newpid(VG_INVALID_THREADID);
2537
2538 //--------------------------------------------------------------
2539 // setup file descriptors
2540 // p: n/a
2541 //--------------------------------------------------------------
2542 setup_file_descriptors();
2543
2544 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002545 // Read /proc/self/maps into a buffer
2546 // p: all memory layout, environment setup [so memory maps are right]
2547 //--------------------------------------------------------------
2548 VG_(read_procselfmaps)();
2549
2550 //--------------------------------------------------------------
2551 // Build segment map (Valgrind segments only)
2552 // p: read proc/self/maps
2553 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2554 //--------------------------------------------------------------
2555 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2556
2557 //==============================================================
2558 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2559 //==============================================================
2560
2561 //--------------------------------------------------------------
2562 // Init tool: pre_clo_init, process cmd line, post_clo_init
2563 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2564 // p: load_tool() [for 'tool']
2565 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2566 // p: parse_procselfmaps [so VG segments are setup so tool can
2567 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002568 //--------------------------------------------------------------
2569 (*toolinfo->sk_pre_clo_init)();
2570 VG_(tool_init_dlsym)(tool_dlhandle);
2571 VG_(sanity_check_needs)();
2572
nethercotef4928da2004-06-15 10:54:40 +00002573 // If --tool and --help/--help-debug was given, now give the core+tool
2574 // help message
nethercotef4928da2004-06-15 10:54:40 +00002575 if (need_help) {
2576 usage(/*--help-debug?*/2 == need_help);
2577 }
nethercotec314eba2004-07-15 12:59:41 +00002578 process_cmd_line_options(client_auxv, tool);
2579
njn26f02512004-11-22 18:33:15 +00002580 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002581
2582 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002583 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002584 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002585 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002586 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002587 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002588 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002589 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002590
2591 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002592 // Protect client trampoline page (which is also sysinfo stuff)
2593 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002594 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002595 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2596 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2597
2598 //==============================================================
2599 // Can use VG_(map)() after segments set up
2600 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002601
2602 //--------------------------------------------------------------
2603 // Allow GDB attach
2604 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2605 //--------------------------------------------------------------
2606 /* Hook to delay things long enough so we can get the pid and
2607 attach GDB in another shell. */
2608 if (VG_(clo_wait_for_gdb)) {
2609 VG_(printf)("pid=%d\n", VG_(getpid)());
2610 /* do "jump *$eip" to skip this in gdb */
2611 VG_(do_syscall)(__NR_pause);
2612 }
2613
2614 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002615 // Search for file descriptors that are inherited from our parent
2616 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2617 //--------------------------------------------------------------
2618 if (VG_(clo_track_fds))
2619 VG_(init_preopened_fds)();
2620
2621 //--------------------------------------------------------------
2622 // Initialise the scheduler
2623 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2624 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2625 //--------------------------------------------------------------
2626 VG_(scheduler_init)();
2627
2628 //--------------------------------------------------------------
sewardj2a99cf62004-11-24 10:44:19 +00002629 // Set up state of thread 1
2630 // p: {pre,post}_clo_init() [for tool helper registration]
2631 // load_client() [for 'client_eip']
2632 // setup_client_stack() [for 'sp_at_startup']
2633 // setup_scheduler() [for the rest of state 1 stuff]
2634 //--------------------------------------------------------------
2635 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
2636
2637 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002638 // Set up the ProxyLWP machinery
2639 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002640 //--------------------------------------------------------------
2641 VG_(proxy_init)();
2642
2643 //--------------------------------------------------------------
2644 // Initialise the signal handling subsystem
2645 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2646 // p: VG_(proxy_init)() [else breaks...]
2647 //--------------------------------------------------------------
2648 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2649 VG_(sigstartup_actions)();
2650
2651 //--------------------------------------------------------------
2652 // Perhaps we're profiling Valgrind?
2653 // p: process_cmd_line_options() [for VG_(clo_profile)]
2654 // p: others?
2655 //
2656 // XXX: this seems to be broken? It always says the tool wasn't built
2657 // for profiling; vg_profile.c's functions don't seem to be overriding
2658 // vg_dummy_profile.c's?
2659 //
2660 // XXX: want this as early as possible. Looking for --profile
2661 // in pre_process_cmd_line_options() could get it earlier.
2662 //--------------------------------------------------------------
2663 if (VG_(clo_profile))
2664 VGP_(init_profiling)();
2665
2666 VGP_PUSHCC(VgpStartup);
2667
2668 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002669 // Read suppression file
2670 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2671 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002672 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002673 VG_(load_suppressions)();
2674
2675 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002676 // Initialise translation table and translation cache
2677 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2678 // aren't identified as part of the client, which would waste
2679 // > 20M of virtual address space.]
2680 //--------------------------------------------------------------
2681 VG_(init_tt_tc)();
2682
2683 //--------------------------------------------------------------
2684 // Read debug info to find glibc entry points to intercept
2685 // p: parse_procselfmaps? [XXX for debug info?]
2686 // p: init_tt_tc? [XXX ???]
2687 //--------------------------------------------------------------
2688 VG_(setup_code_redirect_table)();
2689
2690 //--------------------------------------------------------------
2691 // Verbosity message
2692 // p: end_rdtsc_calibration [so startup message is printed first]
2693 //--------------------------------------------------------------
2694 if (VG_(clo_verbosity) == 1)
2695 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2696 if (VG_(clo_verbosity) > 0)
2697 VG_(message)(Vg_UserMsg, "");
2698
2699 //--------------------------------------------------------------
2700 // Setup pointercheck
2701 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2702 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002703 if (VG_(clo_pointercheck))
2704 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002705
nethercote71980f02004-01-24 18:18:54 +00002706 //--------------------------------------------------------------
2707 // Run!
2708 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002709 VGP_POPCC(VgpStartup);
2710 VGP_PUSHCC(VgpSched);
2711
nethercote238a3c32004-08-09 13:13:31 +00002712 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002713
nethercote238a3c32004-08-09 13:13:31 +00002714 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002715
2716
2717 //--------------------------------------------------------------
2718 // Finalisation: cleanup, messages, etc. Order no so important, only
2719 // affects what order the messages come.
2720 //--------------------------------------------------------------
2721 if (VG_(clo_verbosity) > 0)
2722 VG_(message)(Vg_UserMsg, "");
2723
2724 if (src == VgSrc_Deadlock) {
2725 VG_(message)(Vg_UserMsg,
2726 "Warning: pthread scheduler exited due to deadlock");
2727 }
2728
2729 /* Print out file descriptor summary and stats. */
2730 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002731 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002732
njn95ec8702004-11-22 16:46:13 +00002733 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002734 VG_(show_all_errors)();
2735
njn26f02512004-11-22 18:33:15 +00002736 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002737
nethercote885dd912004-08-03 23:14:00 +00002738 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002739
2740 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002741 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002742
nethercote71980f02004-01-24 18:18:54 +00002743 if (VG_(clo_profile))
2744 VGP_(done_profiling)();
2745
nethercote71980f02004-01-24 18:18:54 +00002746 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2747 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002748 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2749 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002750 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2751
sewardj8b635a42004-11-22 19:01:47 +00002752 /* Print Vex storage stats */
njn383ae5e2004-11-23 17:10:15 +00002753 LibVEX_ClearTemporary( False/*show stats*/ );
sewardj8b635a42004-11-22 19:01:47 +00002754
nethercote71980f02004-01-24 18:18:54 +00002755 //--------------------------------------------------------------
2756 // Exit, according to the scheduler's return code
2757 //--------------------------------------------------------------
2758 switch (src) {
2759 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002760 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002761 VG_(proxy_shutdown)();
2762
2763 /* The thread's %EBX at the time it did __NR_exit() will hold
2764 the arg to __NR_exit(), so we just do __NR_exit() with
2765 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002766 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002767 /* NOT ALIVE HERE! */
2768 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2769 break; /* what the hell :) */
2770
2771 case VgSrc_Deadlock:
2772 /* Just exit now. No point in continuing. */
2773 VG_(proxy_shutdown)();
2774 VG_(exit)(0);
2775 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2776 break;
2777
nethercote71980f02004-01-24 18:18:54 +00002778 case VgSrc_FatalSig:
2779 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002780 vg_assert(fatal_sigNo != -1);
2781 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002782 VG_(core_panic)("main(): signal was supposed to be fatal");
2783 break;
2784
2785 default:
2786 VG_(core_panic)("main(): unexpected scheduler return code");
2787 }
2788
2789 abort();
2790}
2791
2792
sewardjde4a1d02002-03-22 01:27:54 +00002793/*--------------------------------------------------------------------*/
2794/*--- end vg_main.c ---*/
2795/*--------------------------------------------------------------------*/