blob: 3fdac2df39e1905519a2c2db91e0c262fa5e2a17 [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{
216 if (VG_(is_running_thread)( tid ))
217 return VGA_(ptrace_setregs_from_BB)(pid);
218 else
219 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
220}
221
nethercote04d0fbc2004-01-26 16:48:06 +0000222/* Start debugger and get it to attach to this process. Called if the
223 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000224 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000225 meaningfully get the debugger to continue the program, though; to
226 continue, quit the debugger. */
227void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000228{
229 Int pid;
230
231 if ((pid = fork()) == 0) {
232 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000233 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000234
235 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000236 Int status;
237 Int res;
238
nethercote71980f02004-01-24 18:18:54 +0000239 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
240 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000241 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000242 kill(pid, SIGSTOP) == 0 &&
243 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000244 Char pidbuf[15];
245 Char file[30];
246 Char buf[100];
247 Char *bufptr;
248 Char *cmdptr;
249
250 VG_(sprintf)(pidbuf, "%d", pid);
251 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
252
253 bufptr = buf;
254 cmdptr = VG_(clo_db_command);
255
256 while (*cmdptr) {
257 switch (*cmdptr) {
258 case '%':
259 switch (*++cmdptr) {
260 case 'f':
261 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
262 bufptr += VG_(strlen)(file);
263 cmdptr++;
264 break;
265 case 'p':
266 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
267 bufptr += VG_(strlen)(pidbuf);
268 cmdptr++;
269 break;
270 default:
271 *bufptr++ = *cmdptr++;
272 break;
273 }
274 break;
275 default:
276 *bufptr++ = *cmdptr++;
277 break;
278 }
279 }
280
281 *bufptr++ = '\0';
282
283 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000284 res = VG_(system)(buf);
285 if (res == 0) {
286 VG_(message)(Vg_UserMsg, "");
287 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000288 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000289 } else {
290 VG_(message)(Vg_UserMsg, "Apparently failed!");
291 VG_(message)(Vg_UserMsg, "");
292 }
293 }
294
nethercote73b526f2004-10-31 18:48:21 +0000295 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000296 VG_(waitpid)(pid, &status, 0);
297 }
298}
299
300
301/* Print some helpful-ish text about unimplemented things, and give
302 up. */
303void VG_(unimplemented) ( Char* msg )
304{
305 VG_(message)(Vg_UserMsg, "");
306 VG_(message)(Vg_UserMsg,
307 "Valgrind detected that your program requires");
308 VG_(message)(Vg_UserMsg,
309 "the following unimplemented functionality:");
310 VG_(message)(Vg_UserMsg, " %s", msg);
311 VG_(message)(Vg_UserMsg,
312 "This may be because the functionality is hard to implement,");
313 VG_(message)(Vg_UserMsg,
314 "or because no reasonable program would behave this way,");
315 VG_(message)(Vg_UserMsg,
316 "or because nobody has yet needed it. In any case, let us know at");
317 VG_(message)(Vg_UserMsg,
318 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
319 VG_(message)(Vg_UserMsg,
320 "");
321 VG_(message)(Vg_UserMsg,
322 "Valgrind has to exit now. Sorry. Bye!");
323 VG_(message)(Vg_UserMsg,
324 "");
325 VG_(pp_sched_status)();
326 VG_(exit)(1);
327}
328
329Addr VG_(get_stack_pointer) ( void )
330{
sewardj8b635a42004-11-22 19:01:47 +0000331 return BASEBLOCK_STACK_PTR;
nethercote71980f02004-01-24 18:18:54 +0000332}
333
334/* Debugging thing .. can be called from assembly with OYNK macro. */
335void VG_(oynk) ( Int n )
336{
337 OINK(n);
338}
339
340/* Initialize the PID and PGRP of scheduler LWP; this is also called
341 in any new children after fork. */
342static void newpid(ThreadId unused)
343{
344 /* PID of scheduler LWP */
345 VG_(main_pid) = VG_(getpid)();
346 VG_(main_pgrp) = VG_(getpgrp)();
347}
348
349/*====================================================================*/
350/*=== Check we were launched by stage 1 ===*/
351/*====================================================================*/
352
353/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000354int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000355{
nethercoteebf1d862004-11-01 18:22:05 +0000356 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000357 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000358
359 for (; auxv->a_type != AT_NULL; auxv++)
360 switch(auxv->a_type) {
361 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000362 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000363 found |= 1;
364 break;
365
366 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000367 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000368 found |= 2;
369 break;
nethercote7f390022004-10-25 17:18:24 +0000370
371 case AT_PHDR:
372 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
373 break;
nethercote71980f02004-01-24 18:18:54 +0000374 }
375
nethercote361a14e2004-07-26 11:11:56 +0000376 if ( found != (1|2) ) {
377 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000378 exit(127);
379 }
nethercote31779c72004-07-30 21:50:15 +0000380 vg_assert(padfile >= 0);
381 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000382}
383
384
385/*====================================================================*/
386/*=== Address space determination ===*/
387/*====================================================================*/
388
nethercote7f390022004-10-25 17:18:24 +0000389extern char _start[];
390
nethercote31779c72004-07-30 21:50:15 +0000391static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000392{
nethercotea3c3cf22004-11-01 18:38:00 +0000393 Int ires;
394 void* vres;
395 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000396
nethercote7f390022004-10-25 17:18:24 +0000397 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
398 // this is a workable approximation
399 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000400 VG_(valgrind_base) = PGROUNDDN(&_start);
401 }
402
nethercote820bd8c2004-09-07 23:04:49 +0000403 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 // This gives the client the largest possible address space while
406 // taking into account the tool's shadow needs.
407 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000408 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000409 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000410 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000411 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000412 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000413 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000414
nethercote31779c72004-07-30 21:50:15 +0000415 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000416 VG_(shadow_end) = VG_(valgrind_base);
417 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000418
nethercotee2097312004-06-27 12:29:56 +0000419#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
420
nethercote71980f02004-01-24 18:18:54 +0000421 if (0)
nethercotee2097312004-06-27 12:29:56 +0000422 VG_(printf)(
423 "client_base %8x (%dMB)\n"
424 "client_mapbase %8x (%dMB)\n"
425 "client_end %8x (%dMB)\n"
426 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000427 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000428 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000429 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000430 VG_(client_base), SEGSIZE(client_base, client_mapbase),
431 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
432 VG_(client_end), SEGSIZE(client_end, shadow_base),
433 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000434 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000435 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
436 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000437 );
438
439#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000440
441 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000442 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000443 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000444 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000445
446 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000447 ires = munmap((void*)VG_(client_base), client_size);
448 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000449
450 // Map shadow memory.
451 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000452 if (shadow_size != 0) {
453 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000454 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000455 if ((void*)-1 == vres) {
456 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000457 "valgrind: Could not allocate address space (%p bytes)\n"
458 "valgrind: for shadow memory\n"
459 "valgrind: Possible causes:\n"
460 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
461 "valgrind: needs at least 1.5GB swap space.\n"
462 "valgrind: - Or, your virtual memory size may be limited (check\n"
463 "valgrind: with 'ulimit -v').\n"
464 "valgrind: - Or, your system may use a kernel that provides only a\n"
465 "valgrind: too-small (eg. 2GB) user address space.\n"
466 , (void*)shadow_size
467 );
nethercoted4722622004-08-30 19:36:42 +0000468 exit(1);
469 }
nethercotee567e702004-07-10 17:49:17 +0000470 }
nethercote71980f02004-01-24 18:18:54 +0000471}
472
473/*====================================================================*/
474/*=== Command line setup ===*/
475/*====================================================================*/
476
477/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
478static char* get_file_clo(char* dir)
479{
480# define FLEN 512
481 Int fd, n;
482 struct stat s1;
483 char* f_clo = NULL;
484 char filename[FLEN];
485
486 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
487 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
488 if ( fd > 0 ) {
489 if ( 0 == fstat(fd, &s1) ) {
490 f_clo = malloc(s1.st_size+1);
491 vg_assert(f_clo);
492 n = read(fd, f_clo, s1.st_size);
493 if (n == -1) n = 0;
494 f_clo[n] = '\0';
495 }
496 close(fd);
497 }
498 return f_clo;
499# undef FLEN
500}
501
nethercotee2097312004-06-27 12:29:56 +0000502#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
503
nethercote71980f02004-01-24 18:18:54 +0000504static Int count_args(char* s)
505{
506 Int n = 0;
507 if (s) {
508 char* cp = s;
509 while (True) {
510 // We have alternating sequences: blanks, non-blanks, blanks...
511 // count the non-blanks sequences.
512 while ( ISSPACE(*cp) ) cp++;
513 if ( !*cp ) break;
514 n++;
515 while ( !ISSPACE(*cp) && *cp ) cp++;
516 }
517 }
518 return n;
519}
520
521/* add args out of environment, skipping multiple spaces and -- args */
522static char** copy_args( char* s, char** to )
523{
524 if (s) {
525 char* cp = s;
526 while (True) {
527 // We have alternating sequences: blanks, non-blanks, blanks...
528 // copy the non-blanks sequences, and add terminating '\0'
529 while ( ISSPACE(*cp) ) cp++;
530 if ( !*cp ) break;
531 *to++ = cp;
532 while ( !ISSPACE(*cp) && *cp ) cp++;
533 if ( *cp ) *cp++ = '\0'; // terminate if necessary
534 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
535 }
536 }
537 return to;
538}
539
nethercotee2097312004-06-27 12:29:56 +0000540#undef ISSPACE
541
nethercote71980f02004-01-24 18:18:54 +0000542// Augment command line with arguments from environment and .valgrindrc
543// files.
544static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
545{
nethercotef6a1d502004-08-09 12:21:57 +0000546 int vg_argc0 = *vg_argc_inout;
547 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000548
549 char* env_clo = getenv(VALGRINDOPTS);
550 char* f1_clo = get_file_clo( getenv("HOME") );
551 char* f2_clo = get_file_clo(".");
552
553 /* copy any extra args from file or environment, if present */
554 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
555 /* ' ' separated extra options */
556 char **from;
557 char **to;
thughescaca0022004-09-13 10:20:34 +0000558 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
559
560 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
561
nethercote71980f02004-01-24 18:18:54 +0000562 env_arg_count = count_args(env_clo);
563 f1_arg_count = count_args(f1_clo);
564 f2_arg_count = count_args(f2_clo);
565
566 if (0)
567 printf("extra-argc=%d %d %d\n",
568 env_arg_count, f1_arg_count, f2_arg_count);
569
570 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000571 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000572 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000573 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000574 vg_assert(vg_argv0);
575 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000576
577 /* copy argv[0] */
578 *to++ = *from++;
579
580 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
581 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
582 * to override less local ones. */
583 to = copy_args(f1_clo, to);
584 to = copy_args(env_clo, to);
585 to = copy_args(f2_clo, to);
586
587 /* copy original arguments, stopping at command or -- */
588 while (*from) {
589 if (**from != '-')
590 break;
591 if (VG_STREQ(*from, "--")) {
592 from++; /* skip -- */
593 break;
594 }
595 *to++ = *from++;
596 }
597
598 /* add -- */
599 *to++ = "--";
600
nethercotef6a1d502004-08-09 12:21:57 +0000601 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000602
603 /* copy rest of original command line, then NULL */
604 while (*from) *to++ = *from++;
605 *to = NULL;
606 }
607
nethercotef6a1d502004-08-09 12:21:57 +0000608 *vg_argc_inout = vg_argc0;
609 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000610}
611
nethercotef6a1d502004-08-09 12:21:57 +0000612#define VG_CLO_SEP '\01'
613
nethercote71980f02004-01-24 18:18:54 +0000614static void get_command_line( int argc, char** argv,
615 Int* vg_argc_out, Char*** vg_argv_out,
616 char*** cl_argv_out )
617{
nethercotef6a1d502004-08-09 12:21:57 +0000618 int vg_argc0;
619 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000620 char** cl_argv;
621 char* env_clo = getenv(VALGRINDCLO);
622
623 if (env_clo != NULL && *env_clo != '\0') {
624 char *cp;
625 char **cpp;
626
nethercotef6a1d502004-08-09 12:21:57 +0000627 /* OK, VALGRINDCLO is set, which means we must be a child of another
628 Valgrind process using --trace-children, so we're getting all our
629 arguments from VALGRINDCLO, and the entire command line belongs to
630 the client (including argv[0]) */
631 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000632 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000633 if (*cp == VG_CLO_SEP)
634 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000635
nethercotef6a1d502004-08-09 12:21:57 +0000636 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
637 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000638
nethercotef6a1d502004-08-09 12:21:57 +0000639 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000640
641 *cpp++ = "valgrind"; /* nominal argv[0] */
642 *cpp++ = env_clo;
643
nethercotef6a1d502004-08-09 12:21:57 +0000644 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000645 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000646 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000647 *cp++ = '\0'; /* chop it up in place */
648 *cpp++ = cp;
649 }
650 }
651 *cpp = NULL;
652 cl_argv = argv;
653
654 } else {
655 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000656 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000657
nethercotef6a1d502004-08-09 12:21:57 +0000658 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
659 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000660 break;
nethercotef6a1d502004-08-09 12:21:57 +0000661 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
662 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000663 break;
664 }
665 }
nethercotef6a1d502004-08-09 12:21:57 +0000666 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000667
668 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000669 Note we don't do this if getting args from VALGRINDCLO, as
670 those extra args will already be present in VALGRINDCLO. */
671 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000672 }
673
674 if (0) {
675 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000676 for (i = 0; i < vg_argc0; i++)
677 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000678 }
679
nethercotef6a1d502004-08-09 12:21:57 +0000680 *vg_argc_out = vg_argc0;
681 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000682 *cl_argv_out = cl_argv;
683}
684
685
686/*====================================================================*/
687/*=== Environment and stack setup ===*/
688/*====================================================================*/
689
690/* Scan a colon-separated list, and call a function on each element.
691 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000692 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000693 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000694
695 This routine will return True if (*func) returns True and False if
696 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000697*/
thughes4ad52d02004-06-27 17:37:21 +0000698static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000699{
700 char *cp, *entry;
701 int end;
702
703 if (colsep == NULL ||
704 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000705 return False;
nethercote71980f02004-01-24 18:18:54 +0000706
707 entry = cp = colsep;
708
709 do {
710 end = (*cp == '\0');
711
712 if (*cp == ':' || *cp == '\0') {
713 char save = *cp;
714
715 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000716 if ((*func)(entry)) {
717 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000718 return True;
thughes21942d92004-07-12 09:35:37 +0000719 }
nethercote71980f02004-01-24 18:18:54 +0000720 *cp = save;
721 entry = cp+1;
722 }
723 cp++;
724 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000725
726 return False;
727}
728
729static Bool contains(const char *p) {
730 if (VG_STREQ(p, VG_(libdir))) {
731 return True;
732 }
733 return False;
nethercote71980f02004-01-24 18:18:54 +0000734}
735
736/* Prepare the client's environment. This is basically a copy of our
737 environment, except:
738 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
739 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
740
741 If any of these is missing, then it is added.
742
743 Yummy. String hacking in C.
744
745 If this needs to handle any more variables it should be hacked
746 into something table driven.
747 */
748static char **fix_environment(char **origenv, const char *preload)
749{
750 static const char inject_so[] = "vg_inject.so";
751 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
752 static const char ld_preload[] = "LD_PRELOAD=";
753 static const char valgrind_clo[] = VALGRINDCLO "=";
754 static const int ld_library_path_len = sizeof(ld_library_path)-1;
755 static const int ld_preload_len = sizeof(ld_preload)-1;
756 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
757 int ld_preload_done = 0;
758 int ld_library_path_done = 0;
759 char *inject_path;
760 int inject_path_len;
761 int vgliblen = strlen(VG_(libdir));
762 char **cpp;
763 char **ret;
764 int envc;
765 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
766
767 /* Find the vg_inject.so; also make room for the tool preload
768 library */
769 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
770 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000771 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000772
773 if (preload)
774 snprintf(inject_path, inject_path_len, "%s/%s:%s",
775 VG_(libdir), inject_so, preload);
776 else
777 snprintf(inject_path, inject_path_len, "%s/%s",
778 VG_(libdir), inject_so);
779
780 /* Count the original size of the env */
781 envc = 0; /* trailing NULL */
782 for (cpp = origenv; cpp && *cpp; cpp++)
783 envc++;
784
785 /* Allocate a new space */
786 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000787 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000788
789 /* copy it over */
790 for (cpp = ret; *origenv; )
791 *cpp++ = *origenv++;
792 *cpp = NULL;
793
794 vg_assert(envc == (cpp - ret));
795
796 /* Walk over the new environment, mashing as we go */
797 for (cpp = ret; cpp && *cpp; cpp++) {
798 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000799 /* If the LD_LIBRARY_PATH already contains libdir, then don't
800 bother adding it again, even if it isn't the first (it
801 seems that the Java runtime will keep reexecing itself
802 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000803 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000804 int len = strlen(*cpp) + vgliblen*2 + 16;
805 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000806 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000807
808 snprintf(cp, len, "%s%s:%s",
809 ld_library_path, VG_(libdir),
810 (*cpp)+ld_library_path_len);
811
812 *cpp = cp;
813 }
814
815 ld_library_path_done = 1;
816 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
817 int len = strlen(*cpp) + inject_path_len;
818 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000819 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000820
821 snprintf(cp, len, "%s%s:%s",
822 ld_preload, inject_path, (*cpp)+ld_preload_len);
823
824 *cpp = cp;
825
826 ld_preload_done = 1;
827 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
828 *cpp = "";
829 }
830 }
831
832 /* Add the missing bits */
833
834 if (!ld_library_path_done) {
835 int len = ld_library_path_len + vgliblen*2 + 16;
836 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000837 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000838
839 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
840
841 ret[envc++] = cp;
842 }
843
844 if (!ld_preload_done) {
845 int len = ld_preload_len + inject_path_len;
846 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000847 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000848
849 snprintf(cp, len, "%s%s",
850 ld_preload, inject_path);
851
852 ret[envc++] = cp;
853 }
854
855 ret[envc] = NULL;
856
857 return ret;
858}
859
860extern char **environ; /* our environment */
861//#include <error.h>
862
863/* Add a string onto the string table, and return its address */
864static char *copy_str(char **tab, const char *str)
865{
866 char *cp = *tab;
867 char *orig = cp;
868
869 while(*str)
870 *cp++ = *str++;
871 *cp++ = '\0';
872
873 if (0)
nethercote545fe672004-11-01 16:52:43 +0000874 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000875
876 *tab = cp;
877
878 return orig;
879}
880
881/*
882 This sets up the client's initial stack, containing the args,
883 environment and aux vector.
884
885 The format of the stack is:
886
887 higher address +-----------------+
888 | Trampoline code |
889 +-----------------+
890 | |
891 : string table :
892 | |
893 +-----------------+
894 | AT_NULL |
895 - -
896 | auxv |
897 +-----------------+
898 | NULL |
899 - -
900 | envp |
901 +-----------------+
902 | NULL |
903 - -
904 | argv |
905 +-----------------+
906 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000907 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000908 | undefined |
909 : :
910 */
nethercotec25c4492004-10-18 11:52:17 +0000911static Addr setup_client_stack(void* init_sp,
912 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000913 const struct exeinfo *info,
914 UInt** client_auxv)
915{
nethercotee567e702004-07-10 17:49:17 +0000916 void* res;
nethercote71980f02004-01-24 18:18:54 +0000917 char **cpp;
918 char *strtab; /* string table */
919 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000920 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000921 struct ume_auxv *auxv;
922 const struct ume_auxv *orig_auxv;
923 const struct ume_auxv *cauxv;
924 unsigned stringsize; /* total size of strings in bytes */
925 unsigned auxsize; /* total size of auxv in bytes */
926 int argc; /* total argc */
927 int envc; /* total number of env vars */
928 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000929 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000930
931 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000932 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000933
934 /* ==================== compute sizes ==================== */
935
936 /* first of all, work out how big the client stack will be */
937 stringsize = 0;
938
939 /* paste on the extra args if the loader needs them (ie, the #!
940 interpreter and its argument) */
941 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000942 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000943 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000944 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000945 }
nethercoted6a56872004-07-26 15:32:47 +0000946 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000947 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000948 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000949 }
950
951 /* now scan the args we're given... */
952 for (cpp = orig_argv; *cpp; cpp++) {
953 argc++;
954 stringsize += strlen(*cpp) + 1;
955 }
956
957 /* ...and the environment */
958 envc = 0;
959 for (cpp = orig_envp; cpp && *cpp; cpp++) {
960 envc++;
961 stringsize += strlen(*cpp) + 1;
962 }
963
964 /* now, how big is the auxv? */
965 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
966 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
967 if (cauxv->a_type == AT_PLATFORM)
968 stringsize += strlen(cauxv->u.a_ptr) + 1;
969 auxsize += sizeof(*cauxv);
970 }
971
972 /* OK, now we know how big the client stack is */
973 stacksize =
974 sizeof(int) + /* argc */
975 sizeof(char **)*argc + /* argv */
976 sizeof(char **) + /* terminal NULL */
977 sizeof(char **)*envc + /* envp */
978 sizeof(char **) + /* terminal NULL */
979 auxsize + /* auxv */
980 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000981 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000982
nethercotef84f6952004-07-15 14:58:33 +0000983 // decide where stack goes!
984 VG_(clstk_end) = VG_(client_end);
985
nethercote73b526f2004-10-31 18:48:21 +0000986 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000987
nethercote71980f02004-01-24 18:18:54 +0000988 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000989 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000990 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
991
nethercote71980f02004-01-24 18:18:54 +0000992 /* base of the string table (aligned) */
993 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
994
995 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000996
nethercote5ee67ca2004-06-22 14:00:09 +0000997 if (0)
998 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000999 "clstk_base %p\n"
1000 "clstk_end %p\n",
1001 stringsize, auxsize, stacksize,
1002 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +00001003
1004
nethercote71980f02004-01-24 18:18:54 +00001005 /* ==================== allocate space ==================== */
1006
1007 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +00001008 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001009 PROT_READ | PROT_WRITE | PROT_EXEC,
1010 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1011 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001012
1013 /* ==================== copy client stack ==================== */
1014
nethercotea3c3cf22004-11-01 18:38:00 +00001015 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +00001016
1017 /* --- argc --- */
1018 *ptr++ = argc; /* client argc */
1019
1020 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001021 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001022 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001023 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001024 }
nethercoted6a56872004-07-26 15:32:47 +00001025 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001026 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001027 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001028 }
1029 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001030 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001031 }
1032 *ptr++ = 0;
1033
1034 /* --- envp --- */
1035 VG_(client_envp) = (Char **)ptr;
1036 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001037 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001038 *ptr++ = 0;
1039
1040 /* --- auxv --- */
1041 auxv = (struct ume_auxv *)ptr;
1042 *client_auxv = (UInt *)auxv;
1043
1044 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1045 /* copy the entry... */
1046 *auxv = *orig_auxv;
1047
1048 /* ...and fix up the copy */
1049 switch(auxv->a_type) {
1050 case AT_PHDR:
1051 if (info->phdr == 0)
1052 auxv->a_type = AT_IGNORE;
1053 else
1054 auxv->u.a_val = info->phdr;
1055 break;
1056
1057 case AT_PHNUM:
1058 if (info->phdr == 0)
1059 auxv->a_type = AT_IGNORE;
1060 else
1061 auxv->u.a_val = info->phnum;
1062 break;
1063
1064 case AT_BASE:
1065 if (info->interp_base == 0)
1066 auxv->a_type = AT_IGNORE;
1067 else
1068 auxv->u.a_val = info->interp_base;
1069 break;
1070
1071 case AT_PLATFORM: /* points to a platform description string */
1072 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1073 break;
1074
1075 case AT_ENTRY:
1076 auxv->u.a_val = info->entry;
1077 break;
1078
1079 case AT_IGNORE:
1080 case AT_EXECFD:
1081 case AT_PHENT:
1082 case AT_PAGESZ:
1083 case AT_FLAGS:
1084 case AT_NOTELF:
1085 case AT_UID:
1086 case AT_EUID:
1087 case AT_GID:
1088 case AT_EGID:
1089 case AT_CLKTCK:
1090 case AT_HWCAP:
1091 case AT_FPUCW:
1092 case AT_DCACHEBSIZE:
1093 case AT_ICACHEBSIZE:
1094 case AT_UCACHEBSIZE:
1095 /* All these are pointerless, so we don't need to do anything
1096 about them. */
1097 break;
1098
1099 case AT_SECURE:
1100 /* If this is 1, then it means that this program is running
1101 suid, and therefore the dynamic linker should be careful
1102 about LD_PRELOAD, etc. However, since stage1 (the thing
1103 the kernel actually execve's) should never be SUID, and we
1104 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1105 set AT_SECURE to 0. */
1106 auxv->u.a_val = 0;
1107 break;
1108
1109 case AT_SYSINFO:
1110 /* Leave this unmolested for now, but we'll update it later
1111 when we set up the client trampoline code page */
1112 break;
1113
1114 case AT_SYSINFO_EHDR:
1115 /* Trash this, because we don't reproduce it */
1116 auxv->a_type = AT_IGNORE;
1117 break;
1118
1119 default:
1120 /* stomp out anything we don't know about */
1121 if (0)
nethercote545fe672004-11-01 16:52:43 +00001122 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001123 auxv->a_type = AT_IGNORE;
1124 break;
1125
1126 }
1127 }
1128 *auxv = *orig_auxv;
1129 vg_assert(auxv->a_type == AT_NULL);
1130
nethercotef84f6952004-07-15 14:58:33 +00001131 /* --- trampoline page --- */
1132 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1133 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
1134
nethercote71980f02004-01-24 18:18:54 +00001135 vg_assert((strtab-stringbase) == stringsize);
1136
nethercote5ee67ca2004-06-22 14:00:09 +00001137 /* We know the initial ESP is pointing at argc/argv */
1138 VG_(client_argc) = *(Int*)cl_esp;
1139 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1140
nethercote71980f02004-01-24 18:18:54 +00001141 return cl_esp;
1142}
1143
1144/*====================================================================*/
1145/*=== Find executable ===*/
1146/*====================================================================*/
1147
thughes4ad52d02004-06-27 17:37:21 +00001148static const char* executable_name;
1149
1150static Bool match_executable(const char *entry) {
1151 char buf[strlen(entry) + strlen(executable_name) + 2];
1152
1153 /* empty PATH element means . */
1154 if (*entry == '\0')
1155 entry = ".";
1156
1157 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1158
1159 if (access(buf, R_OK|X_OK) == 0) {
1160 executable_name = strdup(buf);
1161 vg_assert(NULL != executable_name);
1162 return True;
1163 }
1164 return False;
1165}
1166
nethercote71980f02004-01-24 18:18:54 +00001167static const char* find_executable(const char* exec)
1168{
1169 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001170 executable_name = exec;
1171 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001172 /* no '/' - we need to search the path */
1173 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001174 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001175 }
thughes4ad52d02004-06-27 17:37:21 +00001176 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001177}
1178
1179
1180/*====================================================================*/
1181/*=== Loading tools ===*/
1182/*====================================================================*/
1183
1184static void list_tools(void)
1185{
1186 DIR *dir = opendir(VG_(libdir));
1187 struct dirent *de;
1188 int first = 1;
1189
1190 if (dir == NULL) {
1191 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001192 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001193 return;
1194 }
1195
nethercotef4928da2004-06-15 10:54:40 +00001196 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001197 int len = strlen(de->d_name);
1198
njn063c5402004-11-22 16:58:05 +00001199 /* look for vgtool_TOOL.so names */
1200 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1201 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001202 VG_STREQ(de->d_name + len - 3, ".so")) {
1203 if (first) {
1204 fprintf(stderr, "Available tools:\n");
1205 first = 0;
1206 }
1207 de->d_name[len-3] = '\0';
1208 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001209 }
1210 }
1211
1212 closedir(dir);
1213
1214 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001215 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1216 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001217}
1218
1219
1220/* Find and load a tool, and check it looks ok. Also looks to see if there's
1221 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1222static void load_tool( const char *toolname, void** handle_out,
1223 ToolInfo** toolinfo_out, char **preloadpath_out )
1224{
1225 Bool ok;
1226 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1227 char buf[len];
1228 void* handle;
1229 ToolInfo* toolinfo;
1230 char* preloadpath = NULL;
1231 Int* vg_malloc_redzonep;
1232
1233 // XXX: allowing full paths for --tool option -- does it make sense?
1234 // Doesn't allow for vgpreload_<tool>.so.
1235
1236 if (strchr(toolname, '/') != 0) {
1237 /* toolname contains '/', and so must be a pathname */
1238 handle = dlopen(toolname, RTLD_NOW);
1239 } else {
1240 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001241 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001242 handle = dlopen(buf, RTLD_NOW);
1243
1244 if (handle != NULL) {
1245 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1246 if (access(buf, R_OK) == 0) {
1247 preloadpath = strdup(buf);
1248 vg_assert(NULL != preloadpath);
1249 }
1250 }
1251 }
1252
1253 ok = (NULL != handle);
1254 if (!ok) {
1255 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1256 goto bad_load;
1257 }
1258
njn26f02512004-11-22 18:33:15 +00001259 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001260 ok = (NULL != toolinfo);
1261 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001262 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001263 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1264 goto bad_load;
1265 }
1266
1267 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1268 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
1269 toolinfo->sk_pre_clo_init != NULL);
1270 if (!ok) {
1271 fprintf(stderr, "Error:\n"
1272 " Tool and core interface versions do not match.\n"
1273 " Interface version used by core is: %d.%d (size %d)\n"
1274 " Interface version used by tool is: %d.%d (size %d)\n"
1275 " The major version numbers must match.\n",
1276 VG_CORE_INTERFACE_MAJOR_VERSION,
1277 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001278 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001279 toolinfo->interface_major_version,
1280 toolinfo->interface_minor_version,
1281 toolinfo->sizeof_ToolInfo);
1282 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1283 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001284 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001285 else
nethercote996901a2004-08-03 13:29:09 +00001286 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001287 goto bad_load;
1288 }
1289
1290 // Set redzone size for V's allocator
1291 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1292 if ( NULL != vg_malloc_redzonep ) {
1293 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1294 }
1295
1296 vg_assert(NULL != handle && NULL != toolinfo);
1297 *handle_out = handle;
1298 *toolinfo_out = toolinfo;
1299 *preloadpath_out = preloadpath;
1300 return;
1301
1302
1303 bad_load:
1304 if (handle != NULL)
1305 dlclose(handle);
1306
nethercotef4928da2004-06-15 10:54:40 +00001307 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001308 list_tools();
1309 exit(127);
1310}
1311
nethercotef4928da2004-06-15 10:54:40 +00001312
1313/*====================================================================*/
1314/*=== Command line errors ===*/
1315/*====================================================================*/
1316
1317static void abort_msg ( void )
1318{
nethercotef8548672004-06-21 12:42:35 +00001319 VG_(clo_log_to) = VgLogTo_Fd;
1320 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001321}
1322
1323void VG_(bad_option) ( Char* opt )
1324{
1325 abort_msg();
1326 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1327 VG_(printf)("valgrind: Use --help for more information.\n");
1328 VG_(exit)(1);
1329}
1330
1331static void missing_tool_option ( void )
1332{
1333 abort_msg();
1334 VG_(printf)("valgrind: Missing --tool option\n");
1335 list_tools();
1336 VG_(printf)("valgrind: Use --help for more information.\n");
1337 VG_(exit)(1);
1338}
1339
1340static void missing_prog ( void )
1341{
1342 abort_msg();
1343 VG_(printf)("valgrind: no program specified\n");
1344 VG_(printf)("valgrind: Use --help for more information.\n");
1345 VG_(exit)(1);
1346}
1347
1348static void config_error ( Char* msg )
1349{
1350 abort_msg();
1351 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1352 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1353 VG_(exit)(1);
1354}
1355
1356
nethercote71980f02004-01-24 18:18:54 +00001357/*====================================================================*/
1358/*=== Loading the client ===*/
1359/*====================================================================*/
1360
nethercotef4928da2004-06-15 10:54:40 +00001361static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001362 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1363{
1364 // If they didn't specify an executable with --exec, and didn't specify
1365 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001366 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001367 if (cl_argv[0] == NULL ||
1368 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1369 {
nethercotef4928da2004-06-15 10:54:40 +00001370 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001371 }
1372 }
1373
1374 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001375 info->exe_base = VG_(client_base);
1376 info->exe_end = VG_(client_end);
1377 info->argv = cl_argv;
1378
nethercotef4928da2004-06-15 10:54:40 +00001379 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001380 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001381 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001382 info->interp_name = NULL;
1383 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001384 } else {
1385 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001386 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001387 ret = do_exec(exec, info);
1388 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001389 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1390 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001391 exit(127);
1392 }
1393 }
1394
1395 /* Copy necessary bits of 'info' that were filled in */
1396 *client_eip = info->init_eip;
1397 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1398}
1399
nethercote969ecf12004-10-13 17:29:01 +00001400/*====================================================================*/
1401/*=== Address space unpadding ===*/
1402/*====================================================================*/
1403
1404typedef struct {
1405 char* killpad_start;
1406 char* killpad_end;
1407 struct stat* killpad_padstat;
1408} killpad_extra;
1409
1410static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1411 int maj, int min, int ino, void* ex)
1412{
1413 killpad_extra* extra = ex;
1414 void *b, *e;
1415 int res;
1416
1417 vg_assert(NULL != extra->killpad_padstat);
1418
1419 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1420 extra->killpad_padstat->st_ino != ino)
1421 return 1;
1422
1423 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1424 return 1;
1425
1426 if (segstart <= extra->killpad_start)
1427 b = extra->killpad_start;
1428 else
1429 b = segstart;
1430
1431 if (segend >= extra->killpad_end)
1432 e = extra->killpad_end;
1433 else
1434 e = segend;
1435
1436 res = munmap(b, (char *)e-(char *)b);
1437 vg_assert(0 == res);
1438
1439 return 1;
1440}
1441
1442// Remove padding of 'padfile' from a range of address space.
1443void as_unpad(void *start, void *end, int padfile)
1444{
1445 static struct stat padstat;
1446 killpad_extra extra;
1447 int res;
1448
1449 vg_assert(padfile > 0);
1450
1451 res = fstat(padfile, &padstat);
1452 vg_assert(0 == res);
1453 extra.killpad_padstat = &padstat;
1454 extra.killpad_start = start;
1455 extra.killpad_end = end;
1456 foreach_map(killpad, &extra);
1457}
1458
1459void as_closepadfile(int padfile)
1460{
1461 int res = close(padfile);
1462 vg_assert(0 == res);
1463}
1464
nethercote71980f02004-01-24 18:18:54 +00001465
1466/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001467/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001468/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001469
njn25e49d8e72002-09-23 09:36:25 +00001470/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001471VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001472Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001473Bool VG_(clo_db_attach) = False;
1474Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001475Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001476Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001477Int VG_(clo_verbosity) = 1;
1478Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001479Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001480
nethercotef1e5e152004-09-01 23:58:16 +00001481/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001482 fd is initially stdout, for --help, but gets moved to stderr by default
1483 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001484VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001485Int VG_(clo_log_fd) = 1;
1486Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001487
thughes6233a382004-08-21 11:10:44 +00001488Bool VG_(clo_time_stamp) = False;
1489
sewardj6024b212003-07-13 10:54:33 +00001490Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001491Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001492Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001493Bool VG_(clo_profile) = False;
1494Bool VG_(clo_single_step) = False;
1495Bool VG_(clo_optimise) = True;
1496UChar VG_(clo_trace_codegen) = 0; // 00000000b
1497Bool VG_(clo_trace_syscalls) = False;
1498Bool VG_(clo_trace_signals) = False;
1499Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001500Bool VG_(clo_trace_sched) = False;
1501Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001502Int VG_(clo_dump_error) = 0;
1503Int VG_(clo_backtrace_size) = 4;
1504Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001505Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001506Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001507Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001508Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001509Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001510Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001511
jsgf855d93d2003-10-13 22:26:55 +00001512static Bool VG_(clo_wait_for_gdb) = False;
1513
1514/* If we're doing signal routing, poll for signals every 50mS by
1515 default. */
1516Int VG_(clo_signal_polltime) = 50;
1517
1518/* These flags reduce thread wakeup latency on syscall completion and
1519 signal delivery, respectively. The downside is possible unfairness. */
1520Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1521Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1522
sewardjde4a1d02002-03-22 01:27:54 +00001523
nethercote6c999f22004-01-31 22:55:15 +00001524void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001525{
njn25e49d8e72002-09-23 09:36:25 +00001526 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001527"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001528"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001529" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001530" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001531" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001532" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001533" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001534" -q --quiet run silently; only print error msgs\n"
1535" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001536" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001537" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001538" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001539"\n"
1540" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001541" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1542" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1543" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1544" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1545" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001546" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001548" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001549" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1550" --log-file=<file> log messages to <file>.pid<pid>\n"
1551" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001552" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1553" --num-callers=<number> show <num> callers in stack traces [4]\n"
1554" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1555" --show-below-main=no|yes continue stack traces below main() [no]\n"
1556" --suppressions=<filename> suppress errors described in <filename>\n"
1557" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001558" --db-attach=no|yes start debugger when errors detected? [no]\n"
1559" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1560" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001561"\n";
njn7cf0bd32002-06-08 13:36:03 +00001562
njn25e49d8e72002-09-23 09:36:25 +00001563 Char* usage2 =
1564"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001565" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001566" --sanity-level=<number> level of sanity checking to do [1]\n"
1567" --single-step=no|yes translate each instr separately? [no]\n"
1568" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001569" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001570" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001571" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001572" --trace-codegen=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
njn25e49d8e72002-09-23 09:36:25 +00001573" --trace-syscalls=no|yes show all system calls? [no]\n"
1574" --trace-signals=no|yes show signal handling details? [no]\n"
1575" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001576" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001577" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001578" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001579"\n"
sewardj8b635a42004-11-22 19:01:47 +00001580" --vex-iropt-verbosity 0 .. 9 [0]\n"
1581" --vex-iropt-level 0 .. 2 [2]\n"
1582" --vex-iropt-precise-memory-exns [no]\n"
1583" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1584" --vex-guest-max-insns 1 .. 100 [50]\n"
1585" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1586"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001587" debugging options for Valgrind tools that report errors\n"
1588" --dump-error=<number> show translation for basic block associated\n"
1589" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001590"\n";
njn3e884182003-04-15 13:03:23 +00001591
1592 Char* usage3 =
1593"\n"
nethercote71980f02004-01-24 18:18:54 +00001594" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001595"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001596" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001597" and licensed under the GNU General Public License, version 2.\n"
1598" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001599"\n"
nethercote137bc552003-11-14 17:47:54 +00001600" Tools are copyright and licensed by their authors. See each\n"
1601" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001602"\n";
njn7cf0bd32002-06-08 13:36:03 +00001603
fitzhardinge98abfc72003-12-16 02:05:15 +00001604 VG_(printf)(usage1);
1605 if (VG_(details).name) {
1606 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001607 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001608 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001609 else
1610 VG_(printf)(" (none)\n");
1611 }
nethercote6c999f22004-01-31 22:55:15 +00001612 if (debug_help) {
1613 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001614
nethercote6c999f22004-01-31 22:55:15 +00001615 if (VG_(details).name) {
1616 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1617
1618 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001619 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001620 else
1621 VG_(printf)(" (none)\n");
1622 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001623 }
nethercote421281e2003-11-20 16:20:55 +00001624 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001625 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001626}
sewardjde4a1d02002-03-22 01:27:54 +00001627
nethercote71980f02004-01-24 18:18:54 +00001628static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001629 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001630{
nethercote71980f02004-01-24 18:18:54 +00001631 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001632
sewardj8b635a42004-11-22 19:01:47 +00001633 LibVEX_default_VexControl(& VG_(clo_vex_control));
1634
nethercote71980f02004-01-24 18:18:54 +00001635 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001636 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001637
nethercotef6a1d502004-08-09 12:21:57 +00001638 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001639 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001640 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001641
nethercotef6a1d502004-08-09 12:21:57 +00001642 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1643 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001644 *need_help = 1;
1645
nethercotef6a1d502004-08-09 12:21:57 +00001646 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001647 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001648
nethercotef6c99d72004-11-09 14:35:43 +00001649 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001650 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001651
nethercotef6a1d502004-08-09 12:21:57 +00001652 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1653 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001654 }
1655 }
1656
nethercotef4928da2004-06-15 10:54:40 +00001657 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001658 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001659 if (0 == *need_help) {
1660 // neither --tool nor --help/--help-debug specified
1661 missing_tool_option();
1662 } else {
1663 // Give help message, without any tool-specific help
1664 usage(/*help-debug?*/2 == *need_help);
1665 }
nethercote71980f02004-01-24 18:18:54 +00001666 }
1667}
1668
nethercote5ee67ca2004-06-22 14:00:09 +00001669static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001670{
nethercotef8548672004-06-21 12:42:35 +00001671 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001672 Int *auxp;
1673 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001674
nethercotee1730692003-11-20 10:38:07 +00001675 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001676 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001677
sewardj19d81412002-06-03 01:10:40 +00001678 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001679 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001680 config_error("Please use absolute paths in "
1681 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001682
nethercote73b526f2004-10-31 18:48:21 +00001683 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001684 switch(auxp[0]) {
nethercote73b526f2004-10-31 18:48:21 +00001685 case AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001686 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001687 break;
sewardjde4a1d02002-03-22 01:27:54 +00001688 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001689 }
sewardjde4a1d02002-03-22 01:27:54 +00001690
nethercotef6a1d502004-08-09 12:21:57 +00001691 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001692
nethercotef6a1d502004-08-09 12:21:57 +00001693 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001694 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001695
thughes3bfd5a02004-07-18 08:05:44 +00001696 /* Look for a colon in the switch name */
1697 while (*colon && *colon != ':' && *colon != '=')
1698 colon++;
nethercote71980f02004-01-24 18:18:54 +00001699
1700 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001701 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001702 if (VG_CLO_STREQN(2, arg, "--") &&
1703 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1704 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1705 {
1706 // prefix matches, convert "--toolname:foo" to "--foo"
1707 if (0)
1708 VG_(printf)("tool-specific arg: %s\n", arg);
1709 arg += toolname_len + 1;
1710 arg[0] = '-';
1711 arg[1] = '-';
1712
1713 } else {
1714 // prefix doesn't match, skip to next arg
1715 continue;
1716 }
1717 }
1718
fitzhardinge98abfc72003-12-16 02:05:15 +00001719 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001720 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 continue;
nethercote71980f02004-01-24 18:18:54 +00001722 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001723 continue;
1724
nethercote71980f02004-01-24 18:18:54 +00001725 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001726 continue;
nethercote27fec902004-06-16 21:26:32 +00001727
nethercote71980f02004-01-24 18:18:54 +00001728 else if (VG_CLO_STREQ(arg, "-v") ||
1729 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001730 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001731
nethercote71980f02004-01-24 18:18:54 +00001732 else if (VG_CLO_STREQ(arg, "-q") ||
1733 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001734 VG_(clo_verbosity)--;
1735
nethercote27fec902004-06-16 21:26:32 +00001736 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1737 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1738 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1739 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1740 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1741 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1742 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1743 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1744 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1745 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1746 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1747 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1748 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1749 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001750 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001751 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1752 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1753 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1754 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1755 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1756 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1757 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001758
nethercote27fec902004-06-16 21:26:32 +00001759 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1760 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001761
nethercote27fec902004-06-16 21:26:32 +00001762 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1763 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1764 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001765 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001766 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1767 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001768
sewardj8b635a42004-11-22 19:01:47 +00001769 else VG_BNUM_CLO("--vex-iropt-verbosity",
1770 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1771 else VG_BNUM_CLO("--vex-iropt-level",
1772 VG_(clo_vex_control).iropt_level, 0, 2)
1773 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1774 VG_(clo_vex_control).iropt_precise_memory_exns)
1775 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1776 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1777 else VG_BNUM_CLO("--vex-guest-max-insns",
1778 VG_(clo_vex_control).guest_max_insns, 1, 100)
1779 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1780 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1781
nethercotef8548672004-06-21 12:42:35 +00001782 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001783 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001784 VG_(clo_log_to) = VgLogTo_Fd;
1785 VG_(clo_log_name) = NULL;
1786 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1787 }
1788 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1789 VG_(clo_log_to) = VgLogTo_Fd;
1790 VG_(clo_log_name) = NULL;
1791 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001792 }
1793
nethercotef8548672004-06-21 12:42:35 +00001794 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001796 VG_(clo_log_to) = VgLogTo_File;
1797 VG_(clo_log_name) = &arg[10];
1798 }
1799 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1800 VG_(clo_log_to) = VgLogTo_File;
1801 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
nethercotef8548672004-06-21 12:42:35 +00001804 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001805 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001806 VG_(clo_log_to) = VgLogTo_Socket;
1807 VG_(clo_log_name) = &arg[12];
1808 }
1809 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1810 VG_(clo_log_to) = VgLogTo_Socket;
1811 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001812 }
1813
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001815 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001816 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001817 VG_(message)(Vg_UserMsg,
1818 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001819 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001822 VG_(clo_n_suppressions)++;
1823 }
sewardjde4a1d02002-03-22 01:27:54 +00001824
njn25e49d8e72002-09-23 09:36:25 +00001825 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001826 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001827 Int j;
nethercote71980f02004-01-24 18:18:54 +00001828 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001829
1830 if (5 != VG_(strlen)(opt)) {
1831 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +00001832 "--trace-codegen argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001833 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001834 }
sewardj8b635a42004-11-22 19:01:47 +00001835 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001836 if ('0' == opt[j]) { /* do nothing */ }
sewardj8b635a42004-11-22 19:01:47 +00001837 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001838 else {
1839 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1840 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001841 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001842 }
1843 }
1844 }
sewardjde4a1d02002-03-22 01:27:54 +00001845
nethercote71980f02004-01-24 18:18:54 +00001846 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001847 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001848 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001849 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001850 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001851 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001852
nethercote71980f02004-01-24 18:18:54 +00001853 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001854 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001855 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001856 }
sewardjde4a1d02002-03-22 01:27:54 +00001857 }
1858
nethercote27fec902004-06-16 21:26:32 +00001859 // Check various option values
1860
njnf9ebf672003-05-12 21:41:30 +00001861 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001862 VG_(clo_verbosity) = 0;
1863
nethercote04d0fbc2004-01-26 16:48:06 +00001864 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001865 VG_(message)(Vg_UserMsg, "");
1866 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001867 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001868 VG_(message)(Vg_UserMsg,
1869 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001870 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001871 }
1872
nethercotef8548672004-06-21 12:42:35 +00001873 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001874 should be connected to whatever sink has been selected, and we
1875 indiscriminately chuck stuff into it without worrying what the
1876 nature of it is. Oh the wonder of Unix streams. */
1877
nethercotee1730692003-11-20 10:38:07 +00001878 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001879 the terminal any problems to do with processing command line
1880 opts. */
nethercotef8548672004-06-21 12:42:35 +00001881 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001882 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001883
1884 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001885
sewardj4cf05692002-10-27 20:28:29 +00001886 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001887 vg_assert(VG_(clo_log_name) == NULL);
1888 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001889 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001890
sewardj4cf05692002-10-27 20:28:29 +00001891 case VgLogTo_File: {
1892 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001893 Int seq = 0;
1894 Int pid = VG_(getpid)();
1895
nethercotef8548672004-06-21 12:42:35 +00001896 vg_assert(VG_(clo_log_name) != NULL);
1897 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001898
nethercote71980f02004-01-24 18:18:54 +00001899 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001900 if (seq == 0)
1901 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001902 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001903 else
1904 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001905 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001906 seq++;
1907
nethercotef8548672004-06-21 12:42:35 +00001908 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001909 = VG_(open)(logfilename,
1910 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1911 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001912 if (eventually_log_fd >= 0) {
1913 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001914 break;
1915 } else {
nethercotef8548672004-06-21 12:42:35 +00001916 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001917 VG_(message)(Vg_UserMsg,
1918 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001919 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001920 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001921 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001922 break;
1923 }
1924 }
1925 }
sewardj4cf05692002-10-27 20:28:29 +00001926 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001927 }
1928
1929 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001930 vg_assert(VG_(clo_log_name) != NULL);
1931 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1932 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1933 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001934 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001935 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001937 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001938 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001939 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001940 }
nethercotef8548672004-06-21 12:42:35 +00001941 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001942 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001943 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001944 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001945 VG_(message)(Vg_UserMsg,
1946 "Log messages will sent to stderr instead." );
1947 VG_(message)(Vg_UserMsg,
1948 "" );
1949 /* We don't change anything here. */
1950 } else {
nethercotef8548672004-06-21 12:42:35 +00001951 vg_assert(eventually_log_fd > 0);
1952 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001953 VG_(logging_to_filedes) = False;
1954 }
sewardj73cf3bc2002-11-03 03:20:15 +00001955 break;
1956 }
1957
sewardj4cf05692002-10-27 20:28:29 +00001958 }
1959
nethercotef8548672004-06-21 12:42:35 +00001960 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001961 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001962 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001963 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1964 else {
nethercotef8548672004-06-21 12:42:35 +00001965 VG_(clo_log_fd) = eventually_log_fd;
1966 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001967 }
1968
sewardj4cf05692002-10-27 20:28:29 +00001969 /* Ok, the logging sink is running now. Print a suitable preamble.
1970 If logging to file or a socket, write details of parent PID and
1971 command line args, to help people trying to interpret the
1972 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001973
sewardj83adf412002-05-01 01:25:45 +00001974 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001975 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001976 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001977 VG_(details).name,
1978 NULL == VG_(details).version ? "" : "-",
1979 NULL == VG_(details).version
1980 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001981 VG_(details).description,
1982 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001983 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001984
njnd04b7c62002-10-03 14:05:52 +00001985 /* Core details */
1986 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001987 "Using valgrind-%s, a program supervision framework for %s.",
1988 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001989 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001990 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001991 }
1992
nethercotec1e395d2003-11-10 13:26:49 +00001993 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001994 VG_(message)(Vg_UserMsg, "");
1995 VG_(message)(Vg_UserMsg,
1996 "My PID = %d, parent PID = %d. Prog and args are:",
1997 VG_(getpid)(), VG_(getppid)() );
1998 for (i = 0; i < VG_(client_argc); i++)
1999 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2000 }
2001
sewardjde4a1d02002-03-22 01:27:54 +00002002 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002003 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002004 if (VG_(clo_log_to) != VgLogTo_Fd)
2005 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002006 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002007 VG_(message)(Vg_UserMsg, "Command line");
2008 for (i = 0; i < VG_(client_argc); i++)
2009 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2010
sewardjde4a1d02002-03-22 01:27:54 +00002011 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002012 for (i = 1; i < vg_argc; i++) {
2013 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002014 }
nethercotea70f7352004-04-18 12:08:46 +00002015
2016 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2017 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2018 if (fd < 0) {
2019 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2020 } else {
2021 #define BUF_LEN 256
2022 Char version_buf[BUF_LEN];
2023 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2024 vg_assert(n <= 256);
2025 if (n > 0) {
2026 version_buf[n-1] = '\0';
2027 VG_(message)(Vg_UserMsg, " %s", version_buf);
2028 } else {
2029 VG_(message)(Vg_UserMsg, " (empty?)");
2030 }
2031 VG_(close)(fd);
2032 #undef BUF_LEN
2033 }
sewardjde4a1d02002-03-22 01:27:54 +00002034 }
2035
fitzhardinge98abfc72003-12-16 02:05:15 +00002036 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002037 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002038 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002039 needs one, load the default */
2040 static const Char default_supp[] = "default.supp";
2041 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2042 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2043 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2044 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2045 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002046 }
sewardj4cf05692002-10-27 20:28:29 +00002047
njn6a230532003-07-21 10:38:23 +00002048 if (VG_(clo_gen_suppressions) &&
njn95ec8702004-11-22 16:46:13 +00002049 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002050 VG_(message)(Vg_UserMsg,
2051 "Can't use --gen-suppressions=yes with this tool,");
2052 VG_(message)(Vg_UserMsg,
2053 "as it doesn't generate errors.");
2054 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002055 }
sewardjde4a1d02002-03-22 01:27:54 +00002056}
2057
nethercotef6a1d502004-08-09 12:21:57 +00002058// Build the string for VALGRINDCLO.
2059Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2060{
2061 /* If we're tracing the children, then we need to start it
2062 with our starter+arguments, which are copied into VALGRINDCLO,
2063 except the --exec= option is changed if present.
2064 */
2065 Int i;
2066 Char *exec;
2067 Char *cp;
2068 Char *optvar;
2069 Int optlen, execlen;
2070
2071 // All these allocated blocks are not free - because we're either
2072 // going to exec, or panic when we fail.
2073
2074 // Create --exec= option: "--exec=<exename>"
2075 exec = VG_(arena_malloc)(VG_AR_CORE,
2076 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2077 vg_assert(NULL != exec);
2078 VG_(sprintf)(exec, "--exec=%s", exename);
2079
2080 // Allocate space for optvar (may overestimate by counting --exec twice,
2081 // no matter)
2082 optlen = 1;
2083 for (i = 0; i < vg_argc; i++)
2084 optlen += VG_(strlen)(vg_argv[i]) + 1;
2085 optlen += VG_(strlen)(exec)+1;
2086 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2087
2088 // Copy all valgrind args except the old --exec (if present)
2089 // VG_CLO_SEP is the separator.
2090 cp = optvar;
2091 for (i = 1; i < vg_argc; i++) {
2092 Char *arg = vg_argv[i];
2093
2094 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2095 // don't copy existing --exec= arg
2096 } else if (VG_(strcmp)(arg, "--") == 0) {
2097 // stop at "--"
2098 break;
2099 } else {
2100 // copy non "--exec" arg
2101 Int len = VG_(strlen)(arg);
2102 VG_(memcpy)(cp, arg, len);
2103 cp += len;
2104 *cp++ = VG_CLO_SEP;
2105 }
2106 }
2107 // Add the new --exec= option
2108 execlen = VG_(strlen)(exec);
2109 VG_(memcpy)(cp, exec, execlen);
2110 cp += execlen;
2111 *cp++ = VG_CLO_SEP;
2112
2113 *cp = '\0';
2114
2115 return optvar;
2116}
2117
2118// Build "/proc/self/fd/<execfd>".
2119Char* VG_(build_child_exename)( void )
2120{
2121 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2122 vg_assert(NULL != exename);
2123 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2124 return exename;
2125}
2126
sewardjde4a1d02002-03-22 01:27:54 +00002127
nethercote71980f02004-01-24 18:18:54 +00002128/*====================================================================*/
2129/*=== File descriptor setup ===*/
2130/*====================================================================*/
2131
2132static void setup_file_descriptors(void)
2133{
2134 struct vki_rlimit rl;
2135
2136 /* Get the current file descriptor limits. */
2137 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2138 rl.rlim_cur = 1024;
2139 rl.rlim_max = 1024;
2140 }
2141
2142 /* Work out where to move the soft limit to. */
2143 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2144 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2145 } else {
2146 rl.rlim_cur = rl.rlim_max;
2147 }
2148
2149 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002150 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2151 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002152
2153 /* Update the soft limit. */
2154 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2155
nethercotef6a1d502004-08-09 12:21:57 +00002156 if (vgexecfd != -1)
2157 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002158 if (VG_(clexecfd) != -1)
2159 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2160}
2161
2162
2163/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002164/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002165/*====================================================================*/
2166
nethercote71980f02004-01-24 18:18:54 +00002167Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2168
2169/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2170 * increased too much, they won't really be compact any more... */
2171#define MAX_COMPACT_HELPERS 8
2172#define MAX_NONCOMPACT_HELPERS 50
2173
nethercote81f9a6f2004-08-03 15:45:46 +00002174/* For storing tool-specific helpers, determined at runtime. The addr
2175 * and offset arrays together form a (addr, offset) map that allows a
2176 * helper's baseBlock offset to be computed from its address. It's done
2177 * like this so CCALLs can use the function address rather than having to
2178 * muck around with offsets. */
2179static UInt VG_(n_compact_helpers) = 0;
2180static UInt VG_(n_noncompact_helpers) = 0;
2181static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2182static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2183static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2184static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002185
2186/* This is the actual defn of baseblock. */
2187UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2188
nethercote71980f02004-01-24 18:18:54 +00002189/* Words. */
2190static Int baB_off = 0;
2191
2192
nethercote71980f02004-01-24 18:18:54 +00002193/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002194Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002195{
nethercote71980f02004-01-24 18:18:54 +00002196 Int off = baB_off;
2197 baB_off += words;
2198 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002199 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002200
nethercote71980f02004-01-24 18:18:54 +00002201 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002202}
2203
nethercote71980f02004-01-24 18:18:54 +00002204/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002205void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002206{
nethercote71980f02004-01-24 18:18:54 +00002207 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2208 baB_off += (align-1);
2209 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002210}
2211
nethercote71980f02004-01-24 18:18:54 +00002212/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002213Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002214{
nethercote2e05c332004-09-06 16:43:37 +00002215 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002216 VG_(baseBlock)[off] = (UInt)a;
2217 return off;
njn25e49d8e72002-09-23 09:36:25 +00002218}
2219
nethercote71980f02004-01-24 18:18:54 +00002220/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2221 filled in later. */
2222void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002223{
nethercote71980f02004-01-24 18:18:54 +00002224 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2225 VG_(printf)("Can only register %d compact helpers\n",
2226 MAX_COMPACT_HELPERS);
2227 VG_(core_panic)("Too many compact helpers registered");
2228 }
2229 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2230 VG_(n_compact_helpers)++;
2231}
2232
2233/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2234 * is filled in later.
2235 */
2236void VG_(register_noncompact_helper)(Addr a)
2237{
2238 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2239 VG_(printf)("Can only register %d non-compact helpers\n",
2240 MAX_NONCOMPACT_HELPERS);
2241 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2242 VG_(core_panic)("Too many non-compact helpers registered");
2243 }
2244 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2245 VG_(n_noncompact_helpers)++;
2246}
2247
nethercote996901a2004-08-03 13:29:09 +00002248/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002249static
2250void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2251{
2252 UInt i;
2253 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002254 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002255}
2256
nethercote4ad74312004-10-26 09:59:49 +00002257Bool VG_(need_to_handle_SP_assignment)(void)
nethercote71980f02004-01-24 18:18:54 +00002258{
2259 return ( VG_(defined_new_mem_stack_4)() ||
2260 VG_(defined_die_mem_stack_4)() ||
2261 VG_(defined_new_mem_stack_8)() ||
2262 VG_(defined_die_mem_stack_8)() ||
2263 VG_(defined_new_mem_stack_12)() ||
2264 VG_(defined_die_mem_stack_12)() ||
2265 VG_(defined_new_mem_stack_16)() ||
2266 VG_(defined_die_mem_stack_16)() ||
2267 VG_(defined_new_mem_stack_32)() ||
2268 VG_(defined_die_mem_stack_32)() ||
2269 VG_(defined_new_mem_stack)() ||
2270 VG_(defined_die_mem_stack)()
2271 );
2272}
2273
nethercote2e05c332004-09-06 16:43:37 +00002274// The low/high split is for x86, so that the more common helpers can be
2275// in the first 128 bytes of the start, which allows the use of a more
2276// compact addressing mode.
nethercote4ad74312004-10-26 09:59:49 +00002277static void init_baseBlock ( Addr client_eip, Addr sp_at_startup )
nethercote71980f02004-01-24 18:18:54 +00002278{
nethercote4ad74312004-10-26 09:59:49 +00002279 VGA_(init_low_baseBlock)(client_eip, sp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002280
nethercote71980f02004-01-24 18:18:54 +00002281 /* Allocate slots for compact helpers */
2282 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2283 VG_(compact_helper_offsets),
2284 VG_(compact_helper_addrs));
2285
nethercote4ad74312004-10-26 09:59:49 +00002286 VGA_(init_high_baseBlock)(client_eip, sp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002287
nethercote71980f02004-01-24 18:18:54 +00002288#define REG(kind, size) \
2289 if (VG_(defined_##kind##_mem_stack##size)()) \
2290 VG_(register_noncompact_helper)( \
2291 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2292 REG(new, _8);
2293 REG(new, _12);
2294 REG(new, _16);
2295 REG(new, _32);
2296 REG(new, );
2297 REG(die, _8);
2298 REG(die, _12);
2299 REG(die, _16);
2300 REG(die, _32);
2301 REG(die, );
2302#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002303
nethercote4ad74312004-10-26 09:59:49 +00002304 if (VG_(need_to_handle_SP_assignment)())
2305 VG_(register_noncompact_helper)((Addr) VG_(unknown_SP_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002306
nethercote2e05c332004-09-06 16:43:37 +00002307 VGOFF_(helper_undefined_instruction)
2308 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002309
nethercote71980f02004-01-24 18:18:54 +00002310 /* Allocate slots for noncompact helpers */
2311 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2312 VG_(noncompact_helper_offsets),
2313 VG_(noncompact_helper_addrs));
2314}
sewardjde4a1d02002-03-22 01:27:54 +00002315
nethercote81f9a6f2004-08-03 15:45:46 +00002316// Finds the baseBlock offset of a tool-specified helper.
2317// Searches through compacts first, then non-compacts.
2318Int VG_(helper_offset)(Addr a)
2319{
2320 UInt i;
2321 Char buf[100];
2322
2323 for (i = 0; i < VG_(n_compact_helpers); i++)
2324 if (VG_(compact_helper_addrs)[i] == a)
2325 return VG_(compact_helper_offsets)[i];
2326 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2327 if (VG_(noncompact_helper_addrs)[i] == a)
2328 return VG_(noncompact_helper_offsets)[i];
2329
2330 /* Shouldn't get here */
2331 VG_(get_fnname) ( a, buf, 100 );
2332
2333 VG_(printf)(
2334 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2335 "A helper function probably used hasn't been registered?\n\n", a, buf);
2336
2337 VG_(printf)(" compact helpers: ");
2338 for (i = 0; i < VG_(n_compact_helpers); i++)
2339 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2340
2341 VG_(printf)("\n non-compact helpers: ");
2342 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2343 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2344
2345 VG_(printf)("\n");
njn67993252004-11-22 18:02:32 +00002346 VG_(tool_panic)("Unfound helper");
nethercote81f9a6f2004-08-03 15:45:46 +00002347}
2348
sewardj5f07b662002-04-23 16:52:51 +00002349
nethercote71980f02004-01-24 18:18:54 +00002350/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002351/*=== Initialise program data/text, etc. ===*/
2352/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002353
nethercote71980f02004-01-24 18:18:54 +00002354static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002355 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002356 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002357{
nethercote71980f02004-01-24 18:18:54 +00002358 UInt prot = 0;
2359 UInt flags = SF_MMAP|SF_NOSYMS;
2360 Bool is_stack_segment;
2361
2362 is_stack_segment =
2363 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2364
2365 /* Only record valgrind mappings for now, without loading any
2366 symbols. This is so we know where the free space is before we
2367 start allocating more memory (note: heap is OK, it's just mmap
2368 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002369 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002370 flags |= SF_VALGRIND;
2371 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2372 }
sewardjde4a1d02002-03-22 01:27:54 +00002373}
2374
nethercote71980f02004-01-24 18:18:54 +00002375// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002376Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002377
nethercote71980f02004-01-24 18:18:54 +00002378static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002379 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002380 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002381{
nethercote71980f02004-01-24 18:18:54 +00002382 UInt prot = 0;
2383 UInt flags;
2384 Bool is_stack_segment;
2385 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002386
nethercote71980f02004-01-24 18:18:54 +00002387 is_stack_segment
2388 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002389
nethercote71980f02004-01-24 18:18:54 +00002390 if (rr == 'r') prot |= VKI_PROT_READ;
2391 if (ww == 'w') prot |= VKI_PROT_WRITE;
2392 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002393
nethercote71980f02004-01-24 18:18:54 +00002394 if (is_stack_segment)
2395 flags = SF_STACK | SF_GROWDOWN;
2396 else
2397 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002398
nethercote71980f02004-01-24 18:18:54 +00002399 if (filename != NULL)
2400 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002401
nethercote820bd8c2004-09-07 23:04:49 +00002402 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002403 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002404
nethercote71980f02004-01-24 18:18:54 +00002405 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002406
nethercote71980f02004-01-24 18:18:54 +00002407 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2408 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002409
nethercote71980f02004-01-24 18:18:54 +00002410 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002411 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002412 vg_assert(0 != r_esp);
2413 if (is_stack_segment) {
2414 if (0)
2415 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2416 start,r_esp);
2417 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002418 }
sewardjde4a1d02002-03-22 01:27:54 +00002419}
2420
2421
nethercote71980f02004-01-24 18:18:54 +00002422/*====================================================================*/
2423/*=== Sanity check machinery (permanently engaged) ===*/
2424/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002425
2426/* A fast sanity check -- suitable for calling circa once per
2427 millisecond. */
2428
nethercote885dd912004-08-03 23:14:00 +00002429void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002430{
njn37cea302002-09-30 11:24:00 +00002431 VGP_PUSHCC(VgpCoreCheapSanity);
2432
nethercote27fec902004-06-16 21:26:32 +00002433 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002434
2435 /* --- First do all the tests that we can do quickly. ---*/
2436
nethercote297effd2004-08-02 15:07:57 +00002437 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002438
njn25e49d8e72002-09-23 09:36:25 +00002439 /* Check stuff pertaining to the memory check system. */
2440
2441 /* Check that nobody has spuriously claimed that the first or
2442 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002443 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002444 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002445 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002446 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002447 }
njn25e49d8e72002-09-23 09:36:25 +00002448
2449 /* --- Now some more expensive checks. ---*/
2450
2451 /* Once every 25 times, check some more expensive stuff. */
2452 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002453 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002454 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002455
njn37cea302002-09-30 11:24:00 +00002456 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002457 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002458
nethercote885dd912004-08-03 23:14:00 +00002459 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002460
njn25e49d8e72002-09-23 09:36:25 +00002461# if 0
2462 { void zzzmemscan(void); zzzmemscan(); }
2463# endif
2464
nethercote297effd2004-08-02 15:07:57 +00002465 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002466 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002467
2468 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002469 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002470 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002471 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002472 }
2473 /*
nethercote297effd2004-08-02 15:07:57 +00002474 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002475 */
njn37cea302002-09-30 11:24:00 +00002476 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002477 }
2478
nethercote27fec902004-06-16 21:26:32 +00002479 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002480 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002481 /* Check sanity of the low-level memory manager. Note that bugs
2482 in the client's code can cause this to fail, so we don't do
2483 this check unless specially asked for. And because it's
2484 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002485 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002486 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002487 }
njn37cea302002-09-30 11:24:00 +00002488 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002489}
nethercote71980f02004-01-24 18:18:54 +00002490
2491
2492/*====================================================================*/
2493/*=== main() ===*/
2494/*====================================================================*/
2495
nethercotec314eba2004-07-15 12:59:41 +00002496/*
2497 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002498 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002499 loads the client executable (and the dynamic linker, if necessary)
2500 into the client part, and calls into Valgrind proper.
2501
2502 The code is careful not to allow spurious mappings to appear in the
2503 wrong parts of the address space. In particular, to make sure
2504 dlopen puts things in the right place, it will pad out the forbidden
2505 chunks of address space so that dlopen is forced to put things where
2506 we want them.
2507
2508 The memory map it creates is:
2509
2510 CLIENT_BASE +-------------------------+
2511 | client address space |
2512 : :
2513 : :
2514 | client stack |
2515 client_end +-------------------------+
2516 | redzone |
2517 shadow_base +-------------------------+
2518 | |
nethercote996901a2004-08-03 13:29:09 +00002519 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002520 | (may be 0 sized) |
2521 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002522 valgrind_base +-------------------------+
2523 | kickstart executable |
2524 | valgrind heap vvvvvvvvv| (barely used)
2525 - -
2526 | valgrind .so files |
2527 | and mappings |
2528 - -
2529 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002530 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002531 : kernel :
2532
2533 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2534 VG_(mmap)(), we need to build the segment skip-list, so we know where
2535 we can put things. However, building that structure requires
2536 allocating memory. So we need to a bootstrapping process. It's done
2537 by making VG_(arena_malloc)() have a special static superblock that's
2538 used for the first 1MB's worth of allocations. This is enough to
2539 build the segment skip-list.
2540*/
2541
nethercote31779c72004-07-30 21:50:15 +00002542static int prmap(char *start, char *end, const char *perm, off_t off,
2543 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002544 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2545 start, end, perm, maj, min, ino);
2546 return True;
2547}
2548
nethercote71980f02004-01-24 18:18:54 +00002549int main(int argc, char **argv)
2550{
2551 char **cl_argv;
2552 const char *tool = NULL;
2553 const char *exec = NULL;
2554 char *preload; /* tool-specific LD_PRELOAD .so */
2555 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002556 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002557 struct exeinfo info;
2558 ToolInfo *toolinfo = NULL;
2559 void *tool_dlhandle;
2560 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002561 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002562 UInt * client_auxv;
2563 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002564 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002565 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002566 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002567 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002568 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2569
nethercote71980f02004-01-24 18:18:54 +00002570
2571 //============================================================
2572 // Nb: startup is complex. Prerequisites are shown at every step.
2573 //
2574 // *** Be very careful when messing with the order ***
2575 //============================================================
2576
nethercotef4928da2004-06-15 10:54:40 +00002577 //============================================================
2578 // Command line argument handling order:
2579 // * If --help/--help-debug are present, show usage message
2580 // (if --tool is also present, that includes the tool-specific usage)
2581 // * Then, if --tool is missing, abort with error msg
2582 // * Then, if client is missing, abort with error msg
2583 // * Then, if any cmdline args are bad, abort with error msg
2584 //============================================================
2585
fitzhardingeb50068f2004-02-24 23:42:55 +00002586 // Get the current process datasize rlimit, and set it to zero.
2587 // This prevents any internal uses of brk() from having any effect.
2588 // We remember the old value so we can restore it on exec, so that
2589 // child processes will have a reasonable brk value.
2590 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2591 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2592 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002593
2594 // Get the current process stack rlimit.
2595 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2596
nethercote71980f02004-01-24 18:18:54 +00002597 //--------------------------------------------------------------
2598 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002599 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002600 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002601 {
2602 void* init_sp = argv - 1;
2603 padfile = scan_auxv(init_sp);
2604 }
nethercote71980f02004-01-24 18:18:54 +00002605
2606 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002607 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002608 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002609 }
2610
2611 //--------------------------------------------------------------
2612 // Look for alternative libdir
2613 // p: n/a
2614 //--------------------------------------------------------------
2615 { char *cp = getenv(VALGRINDLIB);
2616 if (cp != NULL)
2617 VG_(libdir) = cp;
2618 }
2619
2620 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002621 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2622 // Pre-process the command line.
2623 // p: n/a
2624 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002625 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002626 pre_process_cmd_line_options(&need_help, &tool, &exec);
2627
2628 //==============================================================
2629 // Nb: once a tool is specified, the tool.so must be loaded even if
2630 // they specified --help or didn't specify a client program.
2631 //==============================================================
2632
2633 //--------------------------------------------------------------
2634 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002635 // p: set-libdir [for VG_(libdir)]
2636 // p: pre_process_cmd_line_options() [for 'tool']
2637 //--------------------------------------------------------------
2638 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2639
2640 //==============================================================
2641 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002642 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002643 //==============================================================
2644
2645 //--------------------------------------------------------------
2646 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002647 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002648 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002649 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002650
2651 //--------------------------------------------------------------
2652 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002653 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2654 // p: layout_remaining_space [so there's space]
2655 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002656 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002657
2658 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002659 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002660 // p: layout_remaining_space() [everything must be mapped in before now]
2661 // p: load_client() [ditto]
2662 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002663 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2664 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002665
2666 //--------------------------------------------------------------
2667 // Set up client's environment
2668 // p: set-libdir [for VG_(libdir)]
2669 // p: load_tool() [for 'preload']
2670 //--------------------------------------------------------------
2671 env = fix_environment(environ, preload);
2672
2673 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002674 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002675 // p: load_client() [for 'info']
2676 // p: fix_environment() [for 'env']
2677 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002678 {
2679 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002680 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2681 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002682 }
nethercote71980f02004-01-24 18:18:54 +00002683
2684 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002685 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002686 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002687 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002688
2689 //==============================================================
2690 // Finished setting up operating environment. Now initialise
2691 // Valgrind. (This is where the old VG_(main)() started.)
2692 //==============================================================
2693
2694 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002695 // atfork
2696 // p: n/a
2697 //--------------------------------------------------------------
2698 VG_(atfork)(NULL, NULL, newpid);
2699 newpid(VG_INVALID_THREADID);
2700
2701 //--------------------------------------------------------------
2702 // setup file descriptors
2703 // p: n/a
2704 //--------------------------------------------------------------
2705 setup_file_descriptors();
2706
2707 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002708 // Read /proc/self/maps into a buffer
2709 // p: all memory layout, environment setup [so memory maps are right]
2710 //--------------------------------------------------------------
2711 VG_(read_procselfmaps)();
2712
2713 //--------------------------------------------------------------
2714 // Build segment map (Valgrind segments only)
2715 // p: read proc/self/maps
2716 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2717 //--------------------------------------------------------------
2718 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2719
2720 //==============================================================
2721 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2722 //==============================================================
2723
2724 //--------------------------------------------------------------
2725 // Init tool: pre_clo_init, process cmd line, post_clo_init
2726 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2727 // p: load_tool() [for 'tool']
2728 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2729 // p: parse_procselfmaps [so VG segments are setup so tool can
2730 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002731 //--------------------------------------------------------------
2732 (*toolinfo->sk_pre_clo_init)();
2733 VG_(tool_init_dlsym)(tool_dlhandle);
2734 VG_(sanity_check_needs)();
2735
nethercotef4928da2004-06-15 10:54:40 +00002736 // If --tool and --help/--help-debug was given, now give the core+tool
2737 // help message
nethercotef4928da2004-06-15 10:54:40 +00002738 if (need_help) {
2739 usage(/*--help-debug?*/2 == need_help);
2740 }
nethercotec314eba2004-07-15 12:59:41 +00002741 process_cmd_line_options(client_auxv, tool);
2742
njn26f02512004-11-22 18:33:15 +00002743 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002744
2745 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002746 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002747 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002748 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002749 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002750 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002751 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002752 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002753
2754 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002755 // Protect client trampoline page (which is also sysinfo stuff)
2756 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002757 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002758 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2759 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2760
2761 //==============================================================
2762 // Can use VG_(map)() after segments set up
2763 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002764
2765 //--------------------------------------------------------------
2766 // Allow GDB attach
2767 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2768 //--------------------------------------------------------------
2769 /* Hook to delay things long enough so we can get the pid and
2770 attach GDB in another shell. */
2771 if (VG_(clo_wait_for_gdb)) {
2772 VG_(printf)("pid=%d\n", VG_(getpid)());
2773 /* do "jump *$eip" to skip this in gdb */
2774 VG_(do_syscall)(__NR_pause);
2775 }
2776
2777 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002778 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002779 // p: {pre,post}_clo_init() [for tool helper registration]
2780 // load_client() [for 'client_eip']
nethercote4ad74312004-10-26 09:59:49 +00002781 // setup_client_stack() [for 'sp_at_startup']
nethercote71980f02004-01-24 18:18:54 +00002782 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002783 init_baseBlock(client_eip, sp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002784
2785 //--------------------------------------------------------------
2786 // Search for file descriptors that are inherited from our parent
2787 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2788 //--------------------------------------------------------------
2789 if (VG_(clo_track_fds))
2790 VG_(init_preopened_fds)();
2791
2792 //--------------------------------------------------------------
2793 // Initialise the scheduler
2794 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2795 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2796 //--------------------------------------------------------------
2797 VG_(scheduler_init)();
2798
2799 //--------------------------------------------------------------
2800 // Set up the ProxyLWP machinery
2801 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002802 //--------------------------------------------------------------
2803 VG_(proxy_init)();
2804
2805 //--------------------------------------------------------------
2806 // Initialise the signal handling subsystem
2807 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2808 // p: VG_(proxy_init)() [else breaks...]
2809 //--------------------------------------------------------------
2810 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2811 VG_(sigstartup_actions)();
2812
2813 //--------------------------------------------------------------
2814 // Perhaps we're profiling Valgrind?
2815 // p: process_cmd_line_options() [for VG_(clo_profile)]
2816 // p: others?
2817 //
2818 // XXX: this seems to be broken? It always says the tool wasn't built
2819 // for profiling; vg_profile.c's functions don't seem to be overriding
2820 // vg_dummy_profile.c's?
2821 //
2822 // XXX: want this as early as possible. Looking for --profile
2823 // in pre_process_cmd_line_options() could get it earlier.
2824 //--------------------------------------------------------------
2825 if (VG_(clo_profile))
2826 VGP_(init_profiling)();
2827
2828 VGP_PUSHCC(VgpStartup);
2829
2830 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002831 // Read suppression file
2832 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2833 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002834 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002835 VG_(load_suppressions)();
2836
2837 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002838 // Initialise translation table and translation cache
2839 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2840 // aren't identified as part of the client, which would waste
2841 // > 20M of virtual address space.]
2842 //--------------------------------------------------------------
2843 VG_(init_tt_tc)();
2844
2845 //--------------------------------------------------------------
2846 // Read debug info to find glibc entry points to intercept
2847 // p: parse_procselfmaps? [XXX for debug info?]
2848 // p: init_tt_tc? [XXX ???]
2849 //--------------------------------------------------------------
2850 VG_(setup_code_redirect_table)();
2851
2852 //--------------------------------------------------------------
2853 // Verbosity message
2854 // p: end_rdtsc_calibration [so startup message is printed first]
2855 //--------------------------------------------------------------
2856 if (VG_(clo_verbosity) == 1)
2857 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2858 if (VG_(clo_verbosity) > 0)
2859 VG_(message)(Vg_UserMsg, "");
2860
2861 //--------------------------------------------------------------
2862 // Setup pointercheck
2863 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2864 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002865 if (VG_(clo_pointercheck))
2866 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002867
nethercote71980f02004-01-24 18:18:54 +00002868 //--------------------------------------------------------------
2869 // Run!
2870 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002871 VGP_POPCC(VgpStartup);
2872 VGP_PUSHCC(VgpSched);
2873
nethercote238a3c32004-08-09 13:13:31 +00002874 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002875
nethercote238a3c32004-08-09 13:13:31 +00002876 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002877
2878
2879 //--------------------------------------------------------------
2880 // Finalisation: cleanup, messages, etc. Order no so important, only
2881 // affects what order the messages come.
2882 //--------------------------------------------------------------
2883 if (VG_(clo_verbosity) > 0)
2884 VG_(message)(Vg_UserMsg, "");
2885
2886 if (src == VgSrc_Deadlock) {
2887 VG_(message)(Vg_UserMsg,
2888 "Warning: pthread scheduler exited due to deadlock");
2889 }
2890
2891 /* Print out file descriptor summary and stats. */
2892 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002893 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002894
njn95ec8702004-11-22 16:46:13 +00002895 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002896 VG_(show_all_errors)();
2897
njn26f02512004-11-22 18:33:15 +00002898 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002899
nethercote885dd912004-08-03 23:14:00 +00002900 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002901
2902 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002903 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002904
nethercote71980f02004-01-24 18:18:54 +00002905 if (VG_(clo_profile))
2906 VGP_(done_profiling)();
2907
nethercote71980f02004-01-24 18:18:54 +00002908 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2909 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002910 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2911 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002912 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2913
sewardj8b635a42004-11-22 19:01:47 +00002914 /* Print Vex storage stats */
2915 LibVEX_ClearTemporary( True/*show stats*/ );
2916
nethercote71980f02004-01-24 18:18:54 +00002917 //--------------------------------------------------------------
2918 // Exit, according to the scheduler's return code
2919 //--------------------------------------------------------------
2920 switch (src) {
2921 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002922 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002923 VG_(proxy_shutdown)();
2924
2925 /* The thread's %EBX at the time it did __NR_exit() will hold
2926 the arg to __NR_exit(), so we just do __NR_exit() with
2927 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002928 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002929 /* NOT ALIVE HERE! */
2930 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2931 break; /* what the hell :) */
2932
2933 case VgSrc_Deadlock:
2934 /* Just exit now. No point in continuing. */
2935 VG_(proxy_shutdown)();
2936 VG_(exit)(0);
2937 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2938 break;
2939
nethercote71980f02004-01-24 18:18:54 +00002940 case VgSrc_FatalSig:
2941 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002942 vg_assert(fatal_sigNo != -1);
2943 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002944 VG_(core_panic)("main(): signal was supposed to be fatal");
2945 break;
2946
2947 default:
2948 VG_(core_panic)("main(): unexpected scheduler return code");
2949 }
2950
2951 abort();
2952}
2953
2954
sewardjde4a1d02002-03-22 01:27:54 +00002955/*--------------------------------------------------------------------*/
2956/*--- end vg_main.c ---*/
2957/*--------------------------------------------------------------------*/