blob: cf61287d6809bd5fd95f2292c1f42bb2c1be1b2f [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 ------------------------------------------------------------------ */
nethercote71980f02004-01-24 18:18:54 +000088/* linker-defined base address */
89extern char kickstart_base;
sewardjde4a1d02002-03-22 01:27:54 +000090
nethercote71980f02004-01-24 18:18:54 +000091/* Client address space, lowest to highest (see top of ume.c) */
92Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000093Addr VG_(client_end);
94Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000095Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000096Addr VG_(clstk_base);
97Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000098
99Addr VG_(brk_base); /* start of brk */
100Addr VG_(brk_limit); /* current brk */
101
nethercote996901a2004-08-03 13:29:09 +0000102Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000104
105Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000106
nethercote820bd8c2004-09-07 23:04:49 +0000107// Note that VG_(valgrind_last) names the last byte of the section, whereas
108// the VG_(*_end) vars name the byte one past the end of the section.
109Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000110
fitzhardingeb50068f2004-02-24 23:42:55 +0000111vki_rlimit VG_(client_rlimit_data);
thughesc37184f2004-09-11 14:16:57 +0000112vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000113
nethercote71980f02004-01-24 18:18:54 +0000114/* This is set early to indicate whether this CPU has the
115 SSE/fxsave/fxrestor features. */
116Bool VG_(have_ssestate);
117
fitzhardinge98abfc72003-12-16 02:05:15 +0000118/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000119static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000120
121/* client executable */
122Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000123
124/* Path to library directory */
125const Char *VG_(libdir) = VG_LIBDIR;
126
127/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000128static Int vg_argc;
129static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000130
jsgf855d93d2003-10-13 22:26:55 +0000131/* PID of the main thread */
132Int VG_(main_pid);
133
134/* PGRP of process */
135Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000136
thughesad1c9562004-06-26 11:27:52 +0000137/* Application-visible file descriptor limits */
138Int VG_(fd_soft_limit) = -1;
139Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000140
nethercote71980f02004-01-24 18:18:54 +0000141/* As deduced from esp_at_startup, the client's argc, argv[] and
142 envp[] as extracted from the client's stack at startup-time. */
143Int VG_(client_argc);
144Char** VG_(client_argv);
145Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000146
147/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000148 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000149 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000150
nethercote71980f02004-01-24 18:18:54 +0000151/* Counts downwards in VG_(run_innerloop). */
152UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000153
154/* 64-bit counter for the number of basic blocks done. */
155ULong VG_(bbs_done);
sewardjde4a1d02002-03-22 01:27:54 +0000156
nethercote71980f02004-01-24 18:18:54 +0000157/* Tell the logging mechanism whether we are logging to a file
158 descriptor or a socket descriptor. */
159Bool VG_(logging_to_filedes) = True;
160
sewardj73cf3bc2002-11-03 03:20:15 +0000161
nethercote71980f02004-01-24 18:18:54 +0000162/*====================================================================*/
163/*=== Counters, for profiling purposes only ===*/
164/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000165
nethercote92e7b7f2004-08-07 17:52:25 +0000166// These ones maintained by vg_dispatch.S
167UInt VG_(bb_enchain_count) = 0; // Number of chain operations done
168UInt VG_(bb_dechain_count) = 0; // Number of unchain operations done
169UInt VG_(unchained_jumps_done) = 0; // Number of unchained jumps done
sewardjde4a1d02002-03-22 01:27:54 +0000170
sewardjde4a1d02002-03-22 01:27:54 +0000171/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000172static UInt sanity_fast_count = 0;
173static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000174
nethercote3a42fb82004-08-03 18:08:50 +0000175static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000176{
nethercote3a42fb82004-08-03 18:08:50 +0000177 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000178 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000179 VG_(message)(Vg_DebugMsg,
nethercote92e7b7f2004-08-07 17:52:25 +0000180 "chainings: %d chainings, %d unchainings.",
nethercote71980f02004-01-24 18:18:54 +0000181 VG_(bb_enchain_count), VG_(bb_dechain_count) );
182 VG_(message)(Vg_DebugMsg,
nethercote3a42fb82004-08-03 18:08:50 +0000183 " dispatch: %llu jumps (bb entries); of them %u (%lu%%) unchained.",
nethercote71980f02004-01-24 18:18:54 +0000184 VG_(bbs_done),
185 VG_(unchained_jumps_done),
186 ((ULong)(100) * (ULong)(VG_(unchained_jumps_done)))
187 / ( VG_(bbs_done)==0 ? 1 : VG_(bbs_done) )
188 );
189
nethercote3a42fb82004-08-03 18:08:50 +0000190 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000191 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000192
nethercote3a42fb82004-08-03 18:08:50 +0000193 // Reg-alloc stats
nethercotebee3fd92004-08-02 15:17:43 +0000194 VG_(print_reg_alloc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000195 VG_(message)(Vg_DebugMsg,
196 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000197 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000198
199 // C call stats
nethercote71980f02004-01-24 18:18:54 +0000200 VG_(print_ccall_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000201
202 // UInstr histogram
203 if (VG_(clo_verbosity) > 3)
204 VG_(print_UInstr_histogram)();
205
206 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000207 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000208 VG_(message)(Vg_DebugMsg, "");
209 VG_(message)(Vg_DebugMsg,
210 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000211 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000212 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000213 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000214 VG_(message)(Vg_DebugMsg,
215 "------ Valgrind's ExeContext management stats follow ------" );
216 VG_(print_ExeContext_stats)();
217 }
nethercote71980f02004-01-24 18:18:54 +0000218}
219
220
221/*====================================================================*/
222/*=== Miscellaneous global functions ===*/
223/*====================================================================*/
224
nethercotecf97ffb2004-09-09 13:40:31 +0000225static Int ptrace_setregs(Int pid, ThreadId tid)
226{
227 if (VG_(is_running_thread)( tid ))
228 return VGA_(ptrace_setregs_from_BB)(pid);
229 else
230 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
231}
232
nethercote04d0fbc2004-01-26 16:48:06 +0000233/* Start debugger and get it to attach to this process. Called if the
234 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000235 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000236 meaningfully get the debugger to continue the program, though; to
237 continue, quit the debugger. */
238void VG_(start_debugger) ( Int tid )
nethercote71980f02004-01-24 18:18:54 +0000239{
240 Int pid;
241
242 if ((pid = fork()) == 0) {
243 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
244 VG_(kkill)(VG_(getpid)(), VKI_SIGSTOP);
245
246 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000247 Int status;
248 Int res;
249
nethercote71980f02004-01-24 18:18:54 +0000250 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
251 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000252 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000253 kill(pid, SIGSTOP) == 0 &&
254 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000255 Char pidbuf[15];
256 Char file[30];
257 Char buf[100];
258 Char *bufptr;
259 Char *cmdptr;
260
261 VG_(sprintf)(pidbuf, "%d", pid);
262 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
263
264 bufptr = buf;
265 cmdptr = VG_(clo_db_command);
266
267 while (*cmdptr) {
268 switch (*cmdptr) {
269 case '%':
270 switch (*++cmdptr) {
271 case 'f':
272 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
273 bufptr += VG_(strlen)(file);
274 cmdptr++;
275 break;
276 case 'p':
277 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
278 bufptr += VG_(strlen)(pidbuf);
279 cmdptr++;
280 break;
281 default:
282 *bufptr++ = *cmdptr++;
283 break;
284 }
285 break;
286 default:
287 *bufptr++ = *cmdptr++;
288 break;
289 }
290 }
291
292 *bufptr++ = '\0';
293
294 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000295 res = VG_(system)(buf);
296 if (res == 0) {
297 VG_(message)(Vg_UserMsg, "");
298 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000299 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000300 } else {
301 VG_(message)(Vg_UserMsg, "Apparently failed!");
302 VG_(message)(Vg_UserMsg, "");
303 }
304 }
305
306 VG_(kkill)(pid, VKI_SIGKILL);
307 VG_(waitpid)(pid, &status, 0);
308 }
309}
310
311
312/* Print some helpful-ish text about unimplemented things, and give
313 up. */
314void VG_(unimplemented) ( Char* msg )
315{
316 VG_(message)(Vg_UserMsg, "");
317 VG_(message)(Vg_UserMsg,
318 "Valgrind detected that your program requires");
319 VG_(message)(Vg_UserMsg,
320 "the following unimplemented functionality:");
321 VG_(message)(Vg_UserMsg, " %s", msg);
322 VG_(message)(Vg_UserMsg,
323 "This may be because the functionality is hard to implement,");
324 VG_(message)(Vg_UserMsg,
325 "or because no reasonable program would behave this way,");
326 VG_(message)(Vg_UserMsg,
327 "or because nobody has yet needed it. In any case, let us know at");
328 VG_(message)(Vg_UserMsg,
329 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
330 VG_(message)(Vg_UserMsg,
331 "");
332 VG_(message)(Vg_UserMsg,
333 "Valgrind has to exit now. Sorry. Bye!");
334 VG_(message)(Vg_UserMsg,
335 "");
336 VG_(pp_sched_status)();
337 VG_(exit)(1);
338}
339
340Addr VG_(get_stack_pointer) ( void )
341{
342 return VG_(baseBlock)[VGOFF_(m_esp)];
343}
344
345/* Debugging thing .. can be called from assembly with OYNK macro. */
346void VG_(oynk) ( Int n )
347{
348 OINK(n);
349}
350
351/* Initialize the PID and PGRP of scheduler LWP; this is also called
352 in any new children after fork. */
353static void newpid(ThreadId unused)
354{
355 /* PID of scheduler LWP */
356 VG_(main_pid) = VG_(getpid)();
357 VG_(main_pgrp) = VG_(getpgrp)();
358}
359
360/*====================================================================*/
361/*=== Check we were launched by stage 1 ===*/
362/*====================================================================*/
363
364/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000365int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000366{
nethercotec25c4492004-10-18 11:52:17 +0000367 const struct ume_auxv *auxv = find_auxv((int *)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000368 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000369
370 for (; auxv->a_type != AT_NULL; auxv++)
371 switch(auxv->a_type) {
372 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000373 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000374 found |= 1;
375 break;
376
377 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000378 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000379 found |= 2;
380 break;
381 }
382
nethercote361a14e2004-07-26 11:11:56 +0000383 if ( found != (1|2) ) {
384 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000385 exit(127);
386 }
nethercote31779c72004-07-30 21:50:15 +0000387 vg_assert(padfile >= 0);
388 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000389}
390
391
392/*====================================================================*/
393/*=== Address space determination ===*/
394/*====================================================================*/
395
nethercote31779c72004-07-30 21:50:15 +0000396static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000397{
nethercote31779c72004-07-30 21:50:15 +0000398 Int ires;
399 void* vres;
400 addr_t client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000401
nethercote31779c72004-07-30 21:50:15 +0000402 VG_(valgrind_base) = (addr_t)&kickstart_base;
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) +
413 PGROUNDDN((addr_t)(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)
nethercotef84f6952004-07-15 14:58:33 +0000874 printf("copied %p \"%s\" len %d\n", orig, orig, 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 |
907 lower address +-----------------+ <- esp
908 | 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;
920 addr_t *ptr;
921 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 */
929 addr_t cl_esp; /* client stack base (initial esp) */
930
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) */
981 VKI_BYTES_PER_PAGE; /* page for trampoline code */
982
nethercotef84f6952004-07-15 14:58:33 +0000983 // decide where stack goes!
984 VG_(clstk_end) = VG_(client_end);
985
986 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_BYTES_PER_PAGE;
987
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
1015 ptr = (addr_t *)cl_esp;
1016
1017 /* --- argc --- */
1018 *ptr++ = argc; /* client argc */
1019
1020 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001021 if (info->interp_name) {
1022 *ptr++ = (addr_t)copy_str(&strtab, info->interp_name);
1023 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001024 }
nethercoted6a56872004-07-26 15:32:47 +00001025 if (info->interp_args) {
1026 *ptr++ = (addr_t)copy_str(&strtab, info->interp_args);
1027 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001028 }
1029 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
1030 *ptr = (addr_t)copy_str(&strtab, *cpp);
1031 }
1032 *ptr++ = 0;
1033
1034 /* --- envp --- */
1035 VG_(client_envp) = (Char **)ptr;
1036 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
1037 *ptr = (addr_t)copy_str(&strtab, *cpp);
1038 *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)
1122 printf("stomping auxv entry %d\n", auxv->a_type);
1123 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
1199 /* look for vgskin_TOOL.so names */
1200 if (len > (7+1+3) && /* "vgskin_" + at least 1-char toolname + ".so" */
nethercotef4928da2004-06-15 10:54:40 +00001201 strncmp(de->d_name, "vgskin_", 7) == 0 &&
1202 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 */
1241 snprintf(buf, len, "%s/vgskin_%s.so", VG_(libdir), toolname);
1242 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
1259 toolinfo = dlsym(handle, "vgSkin_tool_info");
1260 ok = (NULL != toolinfo);
1261 if (!ok) {
1262 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - "
1263 "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,
1278 sizeof(*toolinfo),
1279 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. */
1471Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001472Bool VG_(clo_db_attach) = False;
1473Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001474Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001475Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001476Int VG_(clo_verbosity) = 1;
1477Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001478Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001479
nethercotef1e5e152004-09-01 23:58:16 +00001480/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001481 fd is initially stdout, for --help, but gets moved to stderr by default
1482 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001483VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001484Int VG_(clo_log_fd) = 1;
1485Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001486
thughes6233a382004-08-21 11:10:44 +00001487Bool VG_(clo_time_stamp) = False;
1488
sewardj6024b212003-07-13 10:54:33 +00001489Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001490Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001491Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001492Bool VG_(clo_profile) = False;
1493Bool VG_(clo_single_step) = False;
1494Bool VG_(clo_optimise) = True;
1495UChar VG_(clo_trace_codegen) = 0; // 00000000b
1496Bool VG_(clo_trace_syscalls) = False;
1497Bool VG_(clo_trace_signals) = False;
1498Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001499Bool VG_(clo_trace_sched) = False;
1500Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001501Int VG_(clo_dump_error) = 0;
1502Int VG_(clo_backtrace_size) = 4;
1503Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001504Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001505Bool VG_(clo_track_fds) = False;
sewardj22854b92002-11-30 14:00:47 +00001506Bool VG_(clo_chain_bb) = True;
nethercote77eba602003-11-13 17:35:04 +00001507Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001508Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001509Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001510
jsgf855d93d2003-10-13 22:26:55 +00001511static Bool VG_(clo_wait_for_gdb) = False;
1512
1513/* If we're doing signal routing, poll for signals every 50mS by
1514 default. */
1515Int VG_(clo_signal_polltime) = 50;
1516
1517/* These flags reduce thread wakeup latency on syscall completion and
1518 signal delivery, respectively. The downside is possible unfairness. */
1519Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1520Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1521
sewardjde4a1d02002-03-22 01:27:54 +00001522
nethercote6c999f22004-01-31 22:55:15 +00001523void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001524{
njn25e49d8e72002-09-23 09:36:25 +00001525 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001526"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001527"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001528" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001529" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001530" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001531" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001532" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001533" -q --quiet run silently; only print error msgs\n"
1534" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001535" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001536" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001537" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001538"\n"
1539" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001540" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1541" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1542" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1543" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1544" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001545" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001546"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001547" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001548" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1549" --log-file=<file> log messages to <file>.pid<pid>\n"
1550" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001551" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1552" --num-callers=<number> show <num> callers in stack traces [4]\n"
1553" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1554" --show-below-main=no|yes continue stack traces below main() [no]\n"
1555" --suppressions=<filename> suppress errors described in <filename>\n"
1556" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001557" --db-attach=no|yes start debugger when errors detected? [no]\n"
1558" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1559" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001560"\n";
njn7cf0bd32002-06-08 13:36:03 +00001561
njn25e49d8e72002-09-23 09:36:25 +00001562 Char* usage2 =
1563"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001564" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001565" --sanity-level=<number> level of sanity checking to do [1]\n"
1566" --single-step=no|yes translate each instr separately? [no]\n"
1567" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001568" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj22854b92002-11-30 14:00:47 +00001569" --chain-bb=no|yes do basic-block chaining? [yes]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001570" --branchpred=yes|no generate branch prediction hints [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001571" --trace-codegen=<XXXXX> show generated code? (X = 0|1) [00000]\n"
1572" --trace-syscalls=no|yes show all system calls? [no]\n"
1573" --trace-signals=no|yes show signal handling details? [no]\n"
1574" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001575" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001576" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001577" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001578"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001579" debugging options for Valgrind tools that report errors\n"
1580" --dump-error=<number> show translation for basic block associated\n"
1581" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001582"\n";
njn3e884182003-04-15 13:03:23 +00001583
1584 Char* usage3 =
1585"\n"
nethercote71980f02004-01-24 18:18:54 +00001586" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001587"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001588" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001589" and licensed under the GNU General Public License, version 2.\n"
1590" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001591"\n"
nethercote137bc552003-11-14 17:47:54 +00001592" Tools are copyright and licensed by their authors. See each\n"
1593" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001594"\n";
njn7cf0bd32002-06-08 13:36:03 +00001595
fitzhardinge98abfc72003-12-16 02:05:15 +00001596 VG_(printf)(usage1);
1597 if (VG_(details).name) {
1598 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001599 if (VG_(needs).command_line_options)
1600 SK_(print_usage)();
1601 else
1602 VG_(printf)(" (none)\n");
1603 }
nethercote6c999f22004-01-31 22:55:15 +00001604 if (debug_help) {
1605 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001606
nethercote6c999f22004-01-31 22:55:15 +00001607 if (VG_(details).name) {
1608 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1609
1610 if (VG_(needs).command_line_options)
1611 SK_(print_debug_usage)();
1612 else
1613 VG_(printf)(" (none)\n");
1614 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001615 }
nethercote421281e2003-11-20 16:20:55 +00001616 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001617 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001618}
sewardjde4a1d02002-03-22 01:27:54 +00001619
nethercote71980f02004-01-24 18:18:54 +00001620static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001621 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001622{
nethercote71980f02004-01-24 18:18:54 +00001623 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001624
nethercote71980f02004-01-24 18:18:54 +00001625 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001626 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001627
nethercotef6a1d502004-08-09 12:21:57 +00001628 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001629 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001630 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001631
nethercotef6a1d502004-08-09 12:21:57 +00001632 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1633 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001634 *need_help = 1;
1635
nethercotef6a1d502004-08-09 12:21:57 +00001636 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001637 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=") ||
1640 VG_CLO_STREQN(7, vg_argv[i], "--skin=")) {
1641 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001642
nethercotef6a1d502004-08-09 12:21:57 +00001643 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1644 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001645 }
1646 }
1647
nethercotef4928da2004-06-15 10:54:40 +00001648 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001649 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001650 if (0 == *need_help) {
1651 // neither --tool nor --help/--help-debug specified
1652 missing_tool_option();
1653 } else {
1654 // Give help message, without any tool-specific help
1655 usage(/*help-debug?*/2 == *need_help);
1656 }
nethercote71980f02004-01-24 18:18:54 +00001657 }
1658}
1659
nethercote5ee67ca2004-06-22 14:00:09 +00001660static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001661{
nethercotef8548672004-06-21 12:42:35 +00001662 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001663 Int *auxp;
1664 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001665
nethercotee1730692003-11-20 10:38:07 +00001666 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001667 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001668
sewardj19d81412002-06-03 01:10:40 +00001669 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001670 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001671 config_error("Please use absolute paths in "
1672 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001673
nethercote71980f02004-01-24 18:18:54 +00001674 for (auxp = client_auxv; auxp[0] != VKI_AT_NULL; auxp += 2) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 switch(auxp[0]) {
1676 case VKI_AT_SYSINFO:
fitzhardinge92360792003-12-24 10:11:11 +00001677 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
fitzhardinge98abfc72003-12-16 02:05:15 +00001678 break;
sewardjde4a1d02002-03-22 01:27:54 +00001679 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001680 }
sewardjde4a1d02002-03-22 01:27:54 +00001681
nethercotef6a1d502004-08-09 12:21:57 +00001682 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001683
nethercotef6a1d502004-08-09 12:21:57 +00001684 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001685 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001686
thughes3bfd5a02004-07-18 08:05:44 +00001687 /* Look for a colon in the switch name */
1688 while (*colon && *colon != ':' && *colon != '=')
1689 colon++;
nethercote71980f02004-01-24 18:18:54 +00001690
1691 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001692 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001693 if (VG_CLO_STREQN(2, arg, "--") &&
1694 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1695 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1696 {
1697 // prefix matches, convert "--toolname:foo" to "--foo"
1698 if (0)
1699 VG_(printf)("tool-specific arg: %s\n", arg);
1700 arg += toolname_len + 1;
1701 arg[0] = '-';
1702 arg[1] = '-';
1703
1704 } else {
1705 // prefix doesn't match, skip to next arg
1706 continue;
1707 }
1708 }
1709
fitzhardinge98abfc72003-12-16 02:05:15 +00001710 /* Ignore these options - they've already been handled */
nethercote71980f02004-01-24 18:18:54 +00001711 if (VG_CLO_STREQN(7, arg, "--tool=") ||
1712 VG_CLO_STREQN(7, arg, "--skin="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001713 continue;
nethercote71980f02004-01-24 18:18:54 +00001714 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001715 continue;
1716
nethercote71980f02004-01-24 18:18:54 +00001717 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001718 continue;
nethercote27fec902004-06-16 21:26:32 +00001719
nethercote71980f02004-01-24 18:18:54 +00001720 else if (VG_CLO_STREQ(arg, "-v") ||
1721 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001722 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001723
nethercote71980f02004-01-24 18:18:54 +00001724 else if (VG_CLO_STREQ(arg, "-q") ||
1725 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001726 VG_(clo_verbosity)--;
1727
nethercote27fec902004-06-16 21:26:32 +00001728 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
1729 else VG_BOOL_CLO("--chain-bb", VG_(clo_chain_bb))
1730 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1731 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1732 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1733 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1734 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1735 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
1736 else VG_BOOL_CLO("--optimise", VG_(clo_optimise))
1737 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1738 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1739 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1740 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
1741 else VG_BOOL_CLO("--single-step", VG_(clo_single_step))
thughes6233a382004-08-21 11:10:44 +00001742 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001743 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1744 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1745 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1746 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1747 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1748 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1749 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001750
nethercote27fec902004-06-16 21:26:32 +00001751 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1752 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001753
nethercote27fec902004-06-16 21:26:32 +00001754 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1755 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1756 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
1757 else VG_NUM_CLO ("--signal­polltime", VG_(clo_signal_polltime))
1758 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1759 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001760
nethercotef8548672004-06-21 12:42:35 +00001761 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001762 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001763 VG_(clo_log_to) = VgLogTo_Fd;
1764 VG_(clo_log_name) = NULL;
1765 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1766 }
1767 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1768 VG_(clo_log_to) = VgLogTo_Fd;
1769 VG_(clo_log_name) = NULL;
1770 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001771 }
1772
nethercotef8548672004-06-21 12:42:35 +00001773 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001774 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001775 VG_(clo_log_to) = VgLogTo_File;
1776 VG_(clo_log_name) = &arg[10];
1777 }
1778 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1779 VG_(clo_log_to) = VgLogTo_File;
1780 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001781 }
sewardjde4a1d02002-03-22 01:27:54 +00001782
nethercotef8548672004-06-21 12:42:35 +00001783 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001784 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001785 VG_(clo_log_to) = VgLogTo_Socket;
1786 VG_(clo_log_name) = &arg[12];
1787 }
1788 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1789 VG_(clo_log_to) = VgLogTo_Socket;
1790 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001791 }
1792
nethercote71980f02004-01-24 18:18:54 +00001793 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001794 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001795 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001796 VG_(message)(Vg_UserMsg,
1797 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001798 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001799 }
nethercote71980f02004-01-24 18:18:54 +00001800 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001801 VG_(clo_n_suppressions)++;
1802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
njn25e49d8e72002-09-23 09:36:25 +00001804 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001805 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001806 Int j;
nethercote71980f02004-01-24 18:18:54 +00001807 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001808
1809 if (5 != VG_(strlen)(opt)) {
1810 VG_(message)(Vg_UserMsg,
1811 "--trace-codegen argument must have 5 digits");
nethercote71980f02004-01-24 18:18:54 +00001812 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001813 }
1814 for (j = 0; j < 5; j++) {
1815 if ('0' == opt[j]) { /* do nothing */ }
1816 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << j);
1817 else {
1818 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1819 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001820 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001821 }
1822 }
1823 }
sewardjde4a1d02002-03-22 01:27:54 +00001824
nethercote71980f02004-01-24 18:18:54 +00001825 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001826 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001827 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001828 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001829 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001830 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001831
nethercote71980f02004-01-24 18:18:54 +00001832 else if ( ! VG_(needs).command_line_options
1833 || ! SK_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001834 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001835 }
sewardjde4a1d02002-03-22 01:27:54 +00001836 }
1837
nethercote27fec902004-06-16 21:26:32 +00001838 // Check various option values
1839
njnf9ebf672003-05-12 21:41:30 +00001840 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001841 VG_(clo_verbosity) = 0;
1842
nethercote04d0fbc2004-01-26 16:48:06 +00001843 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001844 VG_(message)(Vg_UserMsg, "");
1845 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001846 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001847 VG_(message)(Vg_UserMsg,
1848 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001849 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001850 }
1851
nethercotef8548672004-06-21 12:42:35 +00001852 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001853 should be connected to whatever sink has been selected, and we
1854 indiscriminately chuck stuff into it without worrying what the
1855 nature of it is. Oh the wonder of Unix streams. */
1856
nethercotee1730692003-11-20 10:38:07 +00001857 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001858 the terminal any problems to do with processing command line
1859 opts. */
nethercotef8548672004-06-21 12:42:35 +00001860 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001861 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001862
1863 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001864
sewardj4cf05692002-10-27 20:28:29 +00001865 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001866 vg_assert(VG_(clo_log_name) == NULL);
1867 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001868 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001869
sewardj4cf05692002-10-27 20:28:29 +00001870 case VgLogTo_File: {
1871 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001872 Int seq = 0;
1873 Int pid = VG_(getpid)();
1874
nethercotef8548672004-06-21 12:42:35 +00001875 vg_assert(VG_(clo_log_name) != NULL);
1876 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001877
nethercote71980f02004-01-24 18:18:54 +00001878 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001879 if (seq == 0)
1880 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001881 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001882 else
1883 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001884 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001885 seq++;
1886
nethercotef8548672004-06-21 12:42:35 +00001887 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001888 = VG_(open)(logfilename,
1889 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1890 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001891 if (eventually_log_fd >= 0) {
1892 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001893 break;
1894 } else {
nethercotef8548672004-06-21 12:42:35 +00001895 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001896 VG_(message)(Vg_UserMsg,
1897 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001898 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001899 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001900 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001901 break;
1902 }
1903 }
1904 }
sewardj4cf05692002-10-27 20:28:29 +00001905 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001906 }
1907
1908 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001909 vg_assert(VG_(clo_log_name) != NULL);
1910 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1911 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1912 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001913 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001914 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001915 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001916 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001917 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001918 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001919 }
nethercotef8548672004-06-21 12:42:35 +00001920 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001921 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001922 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001923 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001924 VG_(message)(Vg_UserMsg,
1925 "Log messages will sent to stderr instead." );
1926 VG_(message)(Vg_UserMsg,
1927 "" );
1928 /* We don't change anything here. */
1929 } else {
nethercotef8548672004-06-21 12:42:35 +00001930 vg_assert(eventually_log_fd > 0);
1931 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001932 VG_(logging_to_filedes) = False;
1933 }
sewardj73cf3bc2002-11-03 03:20:15 +00001934 break;
1935 }
1936
sewardj4cf05692002-10-27 20:28:29 +00001937 }
1938
nethercotef8548672004-06-21 12:42:35 +00001939 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001940 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001941 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001942 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1943 else {
nethercotef8548672004-06-21 12:42:35 +00001944 VG_(clo_log_fd) = eventually_log_fd;
1945 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001946 }
1947
sewardj4cf05692002-10-27 20:28:29 +00001948 /* Ok, the logging sink is running now. Print a suitable preamble.
1949 If logging to file or a socket, write details of parent PID and
1950 command line args, to help people trying to interpret the
1951 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001952
sewardj83adf412002-05-01 01:25:45 +00001953 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001954 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001955 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001956 VG_(details).name,
1957 NULL == VG_(details).version ? "" : "-",
1958 NULL == VG_(details).version
1959 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001960 VG_(details).description,
1961 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001962 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001963
njnd04b7c62002-10-03 14:05:52 +00001964 /* Core details */
1965 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001966 "Using valgrind-%s, a program supervision framework for %s.",
1967 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001968 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001969 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001970 }
1971
nethercotec1e395d2003-11-10 13:26:49 +00001972 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001973 VG_(message)(Vg_UserMsg, "");
1974 VG_(message)(Vg_UserMsg,
1975 "My PID = %d, parent PID = %d. Prog and args are:",
1976 VG_(getpid)(), VG_(getppid)() );
1977 for (i = 0; i < VG_(client_argc); i++)
1978 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1979 }
1980
sewardjde4a1d02002-03-22 01:27:54 +00001981 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00001982 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00001983 if (VG_(clo_log_to) != VgLogTo_Fd)
1984 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00001985 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00001986 VG_(message)(Vg_UserMsg, "Command line");
1987 for (i = 0; i < VG_(client_argc); i++)
1988 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1989
sewardjde4a1d02002-03-22 01:27:54 +00001990 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00001991 for (i = 1; i < vg_argc; i++) {
1992 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00001993 }
nethercotea70f7352004-04-18 12:08:46 +00001994
1995 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
1996 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
1997 if (fd < 0) {
1998 VG_(message)(Vg_UserMsg, " can't open /proc/version");
1999 } else {
2000 #define BUF_LEN 256
2001 Char version_buf[BUF_LEN];
2002 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2003 vg_assert(n <= 256);
2004 if (n > 0) {
2005 version_buf[n-1] = '\0';
2006 VG_(message)(Vg_UserMsg, " %s", version_buf);
2007 } else {
2008 VG_(message)(Vg_UserMsg, " (empty?)");
2009 }
2010 VG_(close)(fd);
2011 #undef BUF_LEN
2012 }
sewardjde4a1d02002-03-22 01:27:54 +00002013 }
2014
fitzhardinge98abfc72003-12-16 02:05:15 +00002015 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn25e49d8e72002-09-23 09:36:25 +00002016 (VG_(needs).core_errors || VG_(needs).skin_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002017 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002018 needs one, load the default */
2019 static const Char default_supp[] = "default.supp";
2020 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2021 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2022 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2023 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2024 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002025 }
sewardj4cf05692002-10-27 20:28:29 +00002026
njn6a230532003-07-21 10:38:23 +00002027 if (VG_(clo_gen_suppressions) &&
2028 !VG_(needs).core_errors && !VG_(needs).skin_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002029 VG_(message)(Vg_UserMsg,
2030 "Can't use --gen-suppressions=yes with this tool,");
2031 VG_(message)(Vg_UserMsg,
2032 "as it doesn't generate errors.");
2033 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002034 }
sewardjde4a1d02002-03-22 01:27:54 +00002035}
2036
nethercotef6a1d502004-08-09 12:21:57 +00002037// Build the string for VALGRINDCLO.
2038Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2039{
2040 /* If we're tracing the children, then we need to start it
2041 with our starter+arguments, which are copied into VALGRINDCLO,
2042 except the --exec= option is changed if present.
2043 */
2044 Int i;
2045 Char *exec;
2046 Char *cp;
2047 Char *optvar;
2048 Int optlen, execlen;
2049
2050 // All these allocated blocks are not free - because we're either
2051 // going to exec, or panic when we fail.
2052
2053 // Create --exec= option: "--exec=<exename>"
2054 exec = VG_(arena_malloc)(VG_AR_CORE,
2055 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2056 vg_assert(NULL != exec);
2057 VG_(sprintf)(exec, "--exec=%s", exename);
2058
2059 // Allocate space for optvar (may overestimate by counting --exec twice,
2060 // no matter)
2061 optlen = 1;
2062 for (i = 0; i < vg_argc; i++)
2063 optlen += VG_(strlen)(vg_argv[i]) + 1;
2064 optlen += VG_(strlen)(exec)+1;
2065 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2066
2067 // Copy all valgrind args except the old --exec (if present)
2068 // VG_CLO_SEP is the separator.
2069 cp = optvar;
2070 for (i = 1; i < vg_argc; i++) {
2071 Char *arg = vg_argv[i];
2072
2073 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2074 // don't copy existing --exec= arg
2075 } else if (VG_(strcmp)(arg, "--") == 0) {
2076 // stop at "--"
2077 break;
2078 } else {
2079 // copy non "--exec" arg
2080 Int len = VG_(strlen)(arg);
2081 VG_(memcpy)(cp, arg, len);
2082 cp += len;
2083 *cp++ = VG_CLO_SEP;
2084 }
2085 }
2086 // Add the new --exec= option
2087 execlen = VG_(strlen)(exec);
2088 VG_(memcpy)(cp, exec, execlen);
2089 cp += execlen;
2090 *cp++ = VG_CLO_SEP;
2091
2092 *cp = '\0';
2093
2094 return optvar;
2095}
2096
2097// Build "/proc/self/fd/<execfd>".
2098Char* VG_(build_child_exename)( void )
2099{
2100 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2101 vg_assert(NULL != exename);
2102 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2103 return exename;
2104}
2105
sewardjde4a1d02002-03-22 01:27:54 +00002106
nethercote71980f02004-01-24 18:18:54 +00002107/*====================================================================*/
2108/*=== File descriptor setup ===*/
2109/*====================================================================*/
2110
2111static void setup_file_descriptors(void)
2112{
2113 struct vki_rlimit rl;
2114
2115 /* Get the current file descriptor limits. */
2116 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2117 rl.rlim_cur = 1024;
2118 rl.rlim_max = 1024;
2119 }
2120
2121 /* Work out where to move the soft limit to. */
2122 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2123 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2124 } else {
2125 rl.rlim_cur = rl.rlim_max;
2126 }
2127
2128 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002129 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2130 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002131
2132 /* Update the soft limit. */
2133 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2134
nethercotef6a1d502004-08-09 12:21:57 +00002135 if (vgexecfd != -1)
2136 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002137 if (VG_(clexecfd) != -1)
2138 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2139}
2140
2141
2142/*====================================================================*/
nethercote1d447092004-02-01 17:29:59 +00002143/*=== baseBlock: definition + setup ===*/
nethercote71980f02004-01-24 18:18:54 +00002144/*====================================================================*/
2145
nethercote71980f02004-01-24 18:18:54 +00002146Int VGOFF_(helper_undefined_instruction) = INVALID_OFFSET;
2147
2148/* MAX_NONCOMPACT_HELPERS can be increased easily. If MAX_COMPACT_HELPERS is
2149 * increased too much, they won't really be compact any more... */
2150#define MAX_COMPACT_HELPERS 8
2151#define MAX_NONCOMPACT_HELPERS 50
2152
nethercote81f9a6f2004-08-03 15:45:46 +00002153/* For storing tool-specific helpers, determined at runtime. The addr
2154 * and offset arrays together form a (addr, offset) map that allows a
2155 * helper's baseBlock offset to be computed from its address. It's done
2156 * like this so CCALLs can use the function address rather than having to
2157 * muck around with offsets. */
2158static UInt VG_(n_compact_helpers) = 0;
2159static UInt VG_(n_noncompact_helpers) = 0;
2160static Addr VG_(compact_helper_addrs) [MAX_COMPACT_HELPERS];
2161static Int VG_(compact_helper_offsets)[MAX_COMPACT_HELPERS];
2162static Addr VG_(noncompact_helper_addrs) [MAX_NONCOMPACT_HELPERS];
2163static Int VG_(noncompact_helper_offsets)[MAX_NONCOMPACT_HELPERS];
nethercote71980f02004-01-24 18:18:54 +00002164
2165/* This is the actual defn of baseblock. */
2166UInt VG_(baseBlock)[VG_BASEBLOCK_WORDS];
2167
nethercote71980f02004-01-24 18:18:54 +00002168/* Words. */
2169static Int baB_off = 0;
2170
2171
nethercote71980f02004-01-24 18:18:54 +00002172/* Returns the offset, in words. */
nethercote2e05c332004-09-06 16:43:37 +00002173Int VG_(alloc_BaB) ( Int words )
sewardjde4a1d02002-03-22 01:27:54 +00002174{
nethercote71980f02004-01-24 18:18:54 +00002175 Int off = baB_off;
2176 baB_off += words;
2177 if (baB_off >= VG_BASEBLOCK_WORDS)
nethercote2e05c332004-09-06 16:43:37 +00002178 VG_(core_panic)( "VG_(alloc_BaB): baseBlock is too small");
sewardjde4a1d02002-03-22 01:27:54 +00002179
nethercote71980f02004-01-24 18:18:54 +00002180 return off;
sewardjde4a1d02002-03-22 01:27:54 +00002181}
2182
nethercote71980f02004-01-24 18:18:54 +00002183/* Align offset, in *bytes* */
nethercote2e05c332004-09-06 16:43:37 +00002184void VG_(align_BaB) ( UInt align )
njn25e49d8e72002-09-23 09:36:25 +00002185{
nethercote71980f02004-01-24 18:18:54 +00002186 vg_assert(2 == align || 4 == align || 8 == align || 16 == align);
2187 baB_off += (align-1);
2188 baB_off &= ~(align-1);
njn25e49d8e72002-09-23 09:36:25 +00002189}
2190
nethercote71980f02004-01-24 18:18:54 +00002191/* Allocate 1 word in baseBlock and set it to the given value. */
nethercote2e05c332004-09-06 16:43:37 +00002192Int VG_(alloc_BaB_1_set) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00002193{
nethercote2e05c332004-09-06 16:43:37 +00002194 Int off = VG_(alloc_BaB)(1);
nethercote71980f02004-01-24 18:18:54 +00002195 VG_(baseBlock)[off] = (UInt)a;
2196 return off;
njn25e49d8e72002-09-23 09:36:25 +00002197}
2198
nethercote71980f02004-01-24 18:18:54 +00002199/* Registers a function in compact_helper_addrs; compact_helper_offsets is
2200 filled in later. */
2201void VG_(register_compact_helper)(Addr a)
sewardjde4a1d02002-03-22 01:27:54 +00002202{
nethercote71980f02004-01-24 18:18:54 +00002203 if (MAX_COMPACT_HELPERS <= VG_(n_compact_helpers)) {
2204 VG_(printf)("Can only register %d compact helpers\n",
2205 MAX_COMPACT_HELPERS);
2206 VG_(core_panic)("Too many compact helpers registered");
2207 }
2208 VG_(compact_helper_addrs)[VG_(n_compact_helpers)] = a;
2209 VG_(n_compact_helpers)++;
2210}
2211
2212/* Registers a function in noncompact_helper_addrs; noncompact_helper_offsets
2213 * is filled in later.
2214 */
2215void VG_(register_noncompact_helper)(Addr a)
2216{
2217 if (MAX_NONCOMPACT_HELPERS <= VG_(n_noncompact_helpers)) {
2218 VG_(printf)("Can only register %d non-compact helpers\n",
2219 MAX_NONCOMPACT_HELPERS);
2220 VG_(printf)("Try increasing MAX_NON_COMPACT_HELPERS\n");
2221 VG_(core_panic)("Too many non-compact helpers registered");
2222 }
2223 VG_(noncompact_helper_addrs)[VG_(n_noncompact_helpers)] = a;
2224 VG_(n_noncompact_helpers)++;
2225}
2226
nethercote996901a2004-08-03 13:29:09 +00002227/* Allocate offsets in baseBlock for the tool helpers */
nethercote71980f02004-01-24 18:18:54 +00002228static
2229void assign_helpers_in_baseBlock(UInt n, Int offsets[], Addr addrs[])
2230{
2231 UInt i;
2232 for (i = 0; i < n; i++)
nethercote2e05c332004-09-06 16:43:37 +00002233 offsets[i] = VG_(alloc_BaB_1_set)( addrs[i] );
nethercote71980f02004-01-24 18:18:54 +00002234}
2235
2236Bool VG_(need_to_handle_esp_assignment)(void)
2237{
2238 return ( VG_(defined_new_mem_stack_4)() ||
2239 VG_(defined_die_mem_stack_4)() ||
2240 VG_(defined_new_mem_stack_8)() ||
2241 VG_(defined_die_mem_stack_8)() ||
2242 VG_(defined_new_mem_stack_12)() ||
2243 VG_(defined_die_mem_stack_12)() ||
2244 VG_(defined_new_mem_stack_16)() ||
2245 VG_(defined_die_mem_stack_16)() ||
2246 VG_(defined_new_mem_stack_32)() ||
2247 VG_(defined_die_mem_stack_32)() ||
2248 VG_(defined_new_mem_stack)() ||
2249 VG_(defined_die_mem_stack)()
2250 );
2251}
2252
nethercote2e05c332004-09-06 16:43:37 +00002253// The low/high split is for x86, so that the more common helpers can be
2254// in the first 128 bytes of the start, which allows the use of a more
2255// compact addressing mode.
nethercote71980f02004-01-24 18:18:54 +00002256static void init_baseBlock ( Addr client_eip, Addr esp_at_startup )
2257{
nethercote2e05c332004-09-06 16:43:37 +00002258 VGA_(init_low_baseBlock)(client_eip, esp_at_startup);
nethercote71980f02004-01-24 18:18:54 +00002259
nethercote71980f02004-01-24 18:18:54 +00002260 /* Allocate slots for compact helpers */
2261 assign_helpers_in_baseBlock(VG_(n_compact_helpers),
2262 VG_(compact_helper_offsets),
2263 VG_(compact_helper_addrs));
2264
nethercote2e05c332004-09-06 16:43:37 +00002265 VGA_(init_high_baseBlock)(client_eip, esp_at_startup);
fitzhardingef0046f22003-12-18 02:39:22 +00002266
nethercote71980f02004-01-24 18:18:54 +00002267#define REG(kind, size) \
2268 if (VG_(defined_##kind##_mem_stack##size)()) \
2269 VG_(register_noncompact_helper)( \
2270 (Addr) VG_(tool_interface).track_##kind##_mem_stack##size );
2271 REG(new, _8);
2272 REG(new, _12);
2273 REG(new, _16);
2274 REG(new, _32);
2275 REG(new, );
2276 REG(die, _8);
2277 REG(die, _12);
2278 REG(die, _16);
2279 REG(die, _32);
2280 REG(die, );
2281#undef REG
fitzhardingef0046f22003-12-18 02:39:22 +00002282
nethercote71980f02004-01-24 18:18:54 +00002283 if (VG_(need_to_handle_esp_assignment)())
2284 VG_(register_noncompact_helper)((Addr) VG_(unknown_esp_update));
fitzhardingeb791a192003-12-18 07:22:44 +00002285
nethercote2e05c332004-09-06 16:43:37 +00002286 VGOFF_(helper_undefined_instruction)
2287 = VG_(alloc_BaB_1_set)( (Addr) & VG_(helper_undefined_instruction));
sewardjde4a1d02002-03-22 01:27:54 +00002288
nethercote71980f02004-01-24 18:18:54 +00002289 /* Allocate slots for noncompact helpers */
2290 assign_helpers_in_baseBlock(VG_(n_noncompact_helpers),
2291 VG_(noncompact_helper_offsets),
2292 VG_(noncompact_helper_addrs));
2293}
sewardjde4a1d02002-03-22 01:27:54 +00002294
nethercote81f9a6f2004-08-03 15:45:46 +00002295// Finds the baseBlock offset of a tool-specified helper.
2296// Searches through compacts first, then non-compacts.
2297Int VG_(helper_offset)(Addr a)
2298{
2299 UInt i;
2300 Char buf[100];
2301
2302 for (i = 0; i < VG_(n_compact_helpers); i++)
2303 if (VG_(compact_helper_addrs)[i] == a)
2304 return VG_(compact_helper_offsets)[i];
2305 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2306 if (VG_(noncompact_helper_addrs)[i] == a)
2307 return VG_(noncompact_helper_offsets)[i];
2308
2309 /* Shouldn't get here */
2310 VG_(get_fnname) ( a, buf, 100 );
2311
2312 VG_(printf)(
2313 "\nCouldn't find offset of helper from its address (%p: %s).\n"
2314 "A helper function probably used hasn't been registered?\n\n", a, buf);
2315
2316 VG_(printf)(" compact helpers: ");
2317 for (i = 0; i < VG_(n_compact_helpers); i++)
2318 VG_(printf)("%p ", VG_(compact_helper_addrs)[i]);
2319
2320 VG_(printf)("\n non-compact helpers: ");
2321 for (i = 0; i < VG_(n_noncompact_helpers); i++)
2322 VG_(printf)("%p ", VG_(noncompact_helper_addrs)[i]);
2323
2324 VG_(printf)("\n");
2325 VG_(skin_panic)("Unfound helper");
2326}
2327
sewardj5f07b662002-04-23 16:52:51 +00002328
nethercote71980f02004-01-24 18:18:54 +00002329/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002330/*=== Initialise program data/text, etc. ===*/
2331/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002332
nethercote71980f02004-01-24 18:18:54 +00002333static void build_valgrind_map_callback
2334 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2335 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002336{
nethercote71980f02004-01-24 18:18:54 +00002337 UInt prot = 0;
2338 UInt flags = SF_MMAP|SF_NOSYMS;
2339 Bool is_stack_segment;
2340
2341 is_stack_segment =
2342 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2343
2344 /* Only record valgrind mappings for now, without loading any
2345 symbols. This is so we know where the free space is before we
2346 start allocating more memory (note: heap is OK, it's just mmap
2347 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002348 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002349 flags |= SF_VALGRIND;
2350 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2351 }
sewardjde4a1d02002-03-22 01:27:54 +00002352}
2353
nethercote71980f02004-01-24 18:18:54 +00002354// Global var used to pass local data to callback
2355Addr esp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002356
nethercote71980f02004-01-24 18:18:54 +00002357static void build_segment_map_callback
2358 ( Addr start, UInt size, Char rr, Char ww, Char xx,
2359 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002360{
nethercote71980f02004-01-24 18:18:54 +00002361 UInt prot = 0;
2362 UInt flags;
2363 Bool is_stack_segment;
2364 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002365
nethercote71980f02004-01-24 18:18:54 +00002366 is_stack_segment
2367 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002368
nethercote71980f02004-01-24 18:18:54 +00002369 if (rr == 'r') prot |= VKI_PROT_READ;
2370 if (ww == 'w') prot |= VKI_PROT_WRITE;
2371 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002372
nethercote71980f02004-01-24 18:18:54 +00002373 if (is_stack_segment)
2374 flags = SF_STACK | SF_GROWDOWN;
2375 else
2376 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002377
nethercote71980f02004-01-24 18:18:54 +00002378 if (filename != NULL)
2379 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002380
nethercote820bd8c2004-09-07 23:04:49 +00002381 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002382 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002383
nethercote71980f02004-01-24 18:18:54 +00002384 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002385
nethercote71980f02004-01-24 18:18:54 +00002386 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2387 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002388
nethercote71980f02004-01-24 18:18:54 +00002389 /* If this is the stack segment mark all below %esp as noaccess. */
2390 r_esp = esp_at_startup___global_arg;
2391 vg_assert(0 != r_esp);
2392 if (is_stack_segment) {
2393 if (0)
2394 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2395 start,r_esp);
2396 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002397 }
sewardjde4a1d02002-03-22 01:27:54 +00002398}
2399
2400
nethercote71980f02004-01-24 18:18:54 +00002401/*====================================================================*/
2402/*=== Sanity check machinery (permanently engaged) ===*/
2403/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002404
2405/* A fast sanity check -- suitable for calling circa once per
2406 millisecond. */
2407
nethercote885dd912004-08-03 23:14:00 +00002408void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002409{
njn37cea302002-09-30 11:24:00 +00002410 VGP_PUSHCC(VgpCoreCheapSanity);
2411
nethercote27fec902004-06-16 21:26:32 +00002412 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002413
2414 /* --- First do all the tests that we can do quickly. ---*/
2415
nethercote297effd2004-08-02 15:07:57 +00002416 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002417
njn25e49d8e72002-09-23 09:36:25 +00002418 /* Check stuff pertaining to the memory check system. */
2419
2420 /* Check that nobody has spuriously claimed that the first or
2421 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002422 if (VG_(needs).sanity_checks) {
2423 VGP_PUSHCC(VgpSkinCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002424 vg_assert(SK_(cheap_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002425 VGP_POPCC(VgpSkinCheapSanity);
2426 }
njn25e49d8e72002-09-23 09:36:25 +00002427
2428 /* --- Now some more expensive checks. ---*/
2429
2430 /* Once every 25 times, check some more expensive stuff. */
2431 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002432 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002433 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002434
njn37cea302002-09-30 11:24:00 +00002435 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002436 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002437
nethercote885dd912004-08-03 23:14:00 +00002438 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002439
njn25e49d8e72002-09-23 09:36:25 +00002440# if 0
2441 { void zzzmemscan(void); zzzmemscan(); }
2442# endif
2443
nethercote297effd2004-08-02 15:07:57 +00002444 if ((sanity_fast_count % 250) == 0)
nethercote92e7b7f2004-08-07 17:52:25 +00002445 VG_(sanity_check_tt_tc)();
njn25e49d8e72002-09-23 09:36:25 +00002446
2447 if (VG_(needs).sanity_checks) {
njn37cea302002-09-30 11:24:00 +00002448 VGP_PUSHCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002449 vg_assert(SK_(expensive_sanity_check)());
njn37cea302002-09-30 11:24:00 +00002450 VGP_POPCC(VgpSkinExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002451 }
2452 /*
nethercote297effd2004-08-02 15:07:57 +00002453 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002454 */
njn37cea302002-09-30 11:24:00 +00002455 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002456 }
2457
nethercote27fec902004-06-16 21:26:32 +00002458 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002459 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002460 /* Check sanity of the low-level memory manager. Note that bugs
2461 in the client's code can cause this to fail, so we don't do
2462 this check unless specially asked for. And because it's
2463 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002464 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002465 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002466 }
njn37cea302002-09-30 11:24:00 +00002467 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002468}
nethercote71980f02004-01-24 18:18:54 +00002469
2470
2471/*====================================================================*/
2472/*=== main() ===*/
2473/*====================================================================*/
2474
nethercotec314eba2004-07-15 12:59:41 +00002475/*
2476 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002477 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002478 loads the client executable (and the dynamic linker, if necessary)
2479 into the client part, and calls into Valgrind proper.
2480
2481 The code is careful not to allow spurious mappings to appear in the
2482 wrong parts of the address space. In particular, to make sure
2483 dlopen puts things in the right place, it will pad out the forbidden
2484 chunks of address space so that dlopen is forced to put things where
2485 we want them.
2486
2487 The memory map it creates is:
2488
2489 CLIENT_BASE +-------------------------+
2490 | client address space |
2491 : :
2492 : :
2493 | client stack |
2494 client_end +-------------------------+
2495 | redzone |
2496 shadow_base +-------------------------+
2497 | |
nethercote996901a2004-08-03 13:29:09 +00002498 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002499 | (may be 0 sized) |
2500 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002501 valgrind_base +-------------------------+
2502 | kickstart executable |
2503 | valgrind heap vvvvvvvvv| (barely used)
2504 - -
2505 | valgrind .so files |
2506 | and mappings |
2507 - -
2508 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002509 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002510 : kernel :
2511
2512 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2513 VG_(mmap)(), we need to build the segment skip-list, so we know where
2514 we can put things. However, building that structure requires
2515 allocating memory. So we need to a bootstrapping process. It's done
2516 by making VG_(arena_malloc)() have a special static superblock that's
2517 used for the first 1MB's worth of allocations. This is enough to
2518 build the segment skip-list.
2519*/
2520
nethercote31779c72004-07-30 21:50:15 +00002521static int prmap(char *start, char *end, const char *perm, off_t off,
2522 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002523 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2524 start, end, perm, maj, min, ino);
2525 return True;
2526}
2527
nethercote71980f02004-01-24 18:18:54 +00002528int main(int argc, char **argv)
2529{
2530 char **cl_argv;
2531 const char *tool = NULL;
2532 const char *exec = NULL;
2533 char *preload; /* tool-specific LD_PRELOAD .so */
2534 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002535 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002536 struct exeinfo info;
2537 ToolInfo *toolinfo = NULL;
2538 void *tool_dlhandle;
2539 Addr client_eip;
2540 Addr esp_at_startup; /* client's %esp at the point we gained control. */
2541 UInt * client_auxv;
2542 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002543 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002544 Int fatal_sigNo = -1;
fitzhardingeb50068f2004-02-24 23:42:55 +00002545 vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002546 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002547 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2548
nethercote71980f02004-01-24 18:18:54 +00002549
2550 //============================================================
2551 // Nb: startup is complex. Prerequisites are shown at every step.
2552 //
2553 // *** Be very careful when messing with the order ***
2554 //============================================================
2555
nethercotef4928da2004-06-15 10:54:40 +00002556 //============================================================
2557 // Command line argument handling order:
2558 // * If --help/--help-debug are present, show usage message
2559 // (if --tool is also present, that includes the tool-specific usage)
2560 // * Then, if --tool is missing, abort with error msg
2561 // * Then, if client is missing, abort with error msg
2562 // * Then, if any cmdline args are bad, abort with error msg
2563 //============================================================
2564
fitzhardingeb50068f2004-02-24 23:42:55 +00002565 // Get the current process datasize rlimit, and set it to zero.
2566 // This prevents any internal uses of brk() from having any effect.
2567 // We remember the old value so we can restore it on exec, so that
2568 // child processes will have a reasonable brk value.
2569 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2570 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2571 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002572
2573 // Get the current process stack rlimit.
2574 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2575
nethercote71980f02004-01-24 18:18:54 +00002576 //--------------------------------------------------------------
2577 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002578 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002579 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002580 {
2581 void* init_sp = argv - 1;
2582 padfile = scan_auxv(init_sp);
2583 }
nethercote71980f02004-01-24 18:18:54 +00002584
2585 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002586 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002587 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002588 }
2589
2590 //--------------------------------------------------------------
2591 // Look for alternative libdir
2592 // p: n/a
2593 //--------------------------------------------------------------
2594 { char *cp = getenv(VALGRINDLIB);
2595 if (cp != NULL)
2596 VG_(libdir) = cp;
2597 }
2598
2599 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002600 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2601 // Pre-process the command line.
2602 // p: n/a
2603 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002604 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002605 pre_process_cmd_line_options(&need_help, &tool, &exec);
2606
2607 //==============================================================
2608 // Nb: once a tool is specified, the tool.so must be loaded even if
2609 // they specified --help or didn't specify a client program.
2610 //==============================================================
2611
2612 //--------------------------------------------------------------
2613 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002614 // p: set-libdir [for VG_(libdir)]
2615 // p: pre_process_cmd_line_options() [for 'tool']
2616 //--------------------------------------------------------------
2617 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2618
2619 //==============================================================
2620 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002621 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002622 //==============================================================
2623
2624 //--------------------------------------------------------------
2625 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002626 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002627 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002628 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002629
2630 //--------------------------------------------------------------
2631 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002632 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2633 // p: layout_remaining_space [so there's space]
2634 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002635 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002636
2637 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002638 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002639 // p: layout_remaining_space() [everything must be mapped in before now]
2640 // p: load_client() [ditto]
2641 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002642 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2643 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002644
2645 //--------------------------------------------------------------
2646 // Set up client's environment
2647 // p: set-libdir [for VG_(libdir)]
2648 // p: load_tool() [for 'preload']
2649 //--------------------------------------------------------------
2650 env = fix_environment(environ, preload);
2651
2652 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002653 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002654 // p: load_client() [for 'info']
2655 // p: fix_environment() [for 'env']
2656 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002657 {
2658 void* init_sp = argv - 1;
2659 esp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2660 &client_auxv);
2661 }
nethercote71980f02004-01-24 18:18:54 +00002662
2663 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002664 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
2665 (void*)client_eip, (void*)esp_at_startup, vg_argc,
2666 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002667
2668 //==============================================================
2669 // Finished setting up operating environment. Now initialise
2670 // Valgrind. (This is where the old VG_(main)() started.)
2671 //==============================================================
2672
2673 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002674 // atfork
2675 // p: n/a
2676 //--------------------------------------------------------------
2677 VG_(atfork)(NULL, NULL, newpid);
2678 newpid(VG_INVALID_THREADID);
2679
2680 //--------------------------------------------------------------
2681 // setup file descriptors
2682 // p: n/a
2683 //--------------------------------------------------------------
2684 setup_file_descriptors();
2685
2686 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002687 // Read /proc/self/maps into a buffer
2688 // p: all memory layout, environment setup [so memory maps are right]
2689 //--------------------------------------------------------------
2690 VG_(read_procselfmaps)();
2691
2692 //--------------------------------------------------------------
2693 // Build segment map (Valgrind segments only)
2694 // p: read proc/self/maps
2695 // p: sk_pre_clo_init() [to setup new_mem_startup tracker]
2696 //--------------------------------------------------------------
2697 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2698
2699 //==============================================================
2700 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2701 //==============================================================
2702
2703 //--------------------------------------------------------------
2704 // Init tool: pre_clo_init, process cmd line, post_clo_init
2705 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2706 // p: load_tool() [for 'tool']
2707 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2708 // p: parse_procselfmaps [so VG segments are setup so tool can
2709 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002710 //--------------------------------------------------------------
2711 (*toolinfo->sk_pre_clo_init)();
2712 VG_(tool_init_dlsym)(tool_dlhandle);
2713 VG_(sanity_check_needs)();
2714
nethercotef4928da2004-06-15 10:54:40 +00002715 // If --tool and --help/--help-debug was given, now give the core+tool
2716 // help message
nethercotef4928da2004-06-15 10:54:40 +00002717 if (need_help) {
2718 usage(/*--help-debug?*/2 == need_help);
2719 }
nethercotec314eba2004-07-15 12:59:41 +00002720 process_cmd_line_options(client_auxv, tool);
2721
2722 SK_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002723
2724 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002725 // Build segment map (all segments)
2726 // p: setup_client_stack() [for 'esp_at_startup']
2727 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002728 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002729 esp_at_startup___global_arg = esp_at_startup;
2730 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
2731 esp_at_startup___global_arg = 0;
2732
2733 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002734 // Protect client trampoline page (which is also sysinfo stuff)
2735 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002736 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002737 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2738 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
2739
2740 //==============================================================
2741 // Can use VG_(map)() after segments set up
2742 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002743
2744 //--------------------------------------------------------------
2745 // Allow GDB attach
2746 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2747 //--------------------------------------------------------------
2748 /* Hook to delay things long enough so we can get the pid and
2749 attach GDB in another shell. */
2750 if (VG_(clo_wait_for_gdb)) {
2751 VG_(printf)("pid=%d\n", VG_(getpid)());
2752 /* do "jump *$eip" to skip this in gdb */
2753 VG_(do_syscall)(__NR_pause);
2754 }
2755
2756 //--------------------------------------------------------------
nethercote1d447092004-02-01 17:29:59 +00002757 // Set up baseBlock
nethercote71980f02004-01-24 18:18:54 +00002758 // p: {pre,post}_clo_init() [for tool helper registration]
2759 // load_client() [for 'client_eip']
2760 // setup_client_stack() [for 'esp_at_startup']
2761 //--------------------------------------------------------------
2762 init_baseBlock(client_eip, esp_at_startup);
2763
2764 //--------------------------------------------------------------
2765 // Search for file descriptors that are inherited from our parent
2766 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2767 //--------------------------------------------------------------
2768 if (VG_(clo_track_fds))
2769 VG_(init_preopened_fds)();
2770
2771 //--------------------------------------------------------------
2772 // Initialise the scheduler
2773 // p: init_baseBlock() [baseBlock regs copied into VG_(threads)[1]]
2774 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2775 //--------------------------------------------------------------
2776 VG_(scheduler_init)();
2777
2778 //--------------------------------------------------------------
2779 // Set up the ProxyLWP machinery
2780 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002781 //--------------------------------------------------------------
2782 VG_(proxy_init)();
2783
2784 //--------------------------------------------------------------
2785 // Initialise the signal handling subsystem
2786 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2787 // p: VG_(proxy_init)() [else breaks...]
2788 //--------------------------------------------------------------
2789 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2790 VG_(sigstartup_actions)();
2791
2792 //--------------------------------------------------------------
2793 // Perhaps we're profiling Valgrind?
2794 // p: process_cmd_line_options() [for VG_(clo_profile)]
2795 // p: others?
2796 //
2797 // XXX: this seems to be broken? It always says the tool wasn't built
2798 // for profiling; vg_profile.c's functions don't seem to be overriding
2799 // vg_dummy_profile.c's?
2800 //
2801 // XXX: want this as early as possible. Looking for --profile
2802 // in pre_process_cmd_line_options() could get it earlier.
2803 //--------------------------------------------------------------
2804 if (VG_(clo_profile))
2805 VGP_(init_profiling)();
2806
2807 VGP_PUSHCC(VgpStartup);
2808
2809 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002810 // Read suppression file
2811 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2812 //--------------------------------------------------------------
2813 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2814 VG_(load_suppressions)();
2815
2816 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002817 // Initialise translation table and translation cache
2818 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2819 // aren't identified as part of the client, which would waste
2820 // > 20M of virtual address space.]
2821 //--------------------------------------------------------------
2822 VG_(init_tt_tc)();
2823
2824 //--------------------------------------------------------------
2825 // Read debug info to find glibc entry points to intercept
2826 // p: parse_procselfmaps? [XXX for debug info?]
2827 // p: init_tt_tc? [XXX ???]
2828 //--------------------------------------------------------------
2829 VG_(setup_code_redirect_table)();
2830
2831 //--------------------------------------------------------------
2832 // Verbosity message
2833 // p: end_rdtsc_calibration [so startup message is printed first]
2834 //--------------------------------------------------------------
2835 if (VG_(clo_verbosity) == 1)
2836 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2837 if (VG_(clo_verbosity) > 0)
2838 VG_(message)(Vg_UserMsg, "");
2839
2840 //--------------------------------------------------------------
2841 // Setup pointercheck
2842 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2843 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002844 if (VG_(clo_pointercheck))
2845 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002846
nethercote71980f02004-01-24 18:18:54 +00002847 //--------------------------------------------------------------
2848 // Run!
2849 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002850 VGP_POPCC(VgpStartup);
2851 VGP_PUSHCC(VgpSched);
2852
nethercote238a3c32004-08-09 13:13:31 +00002853 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002854
nethercote238a3c32004-08-09 13:13:31 +00002855 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002856
2857
2858 //--------------------------------------------------------------
2859 // Finalisation: cleanup, messages, etc. Order no so important, only
2860 // affects what order the messages come.
2861 //--------------------------------------------------------------
2862 if (VG_(clo_verbosity) > 0)
2863 VG_(message)(Vg_UserMsg, "");
2864
2865 if (src == VgSrc_Deadlock) {
2866 VG_(message)(Vg_UserMsg,
2867 "Warning: pthread scheduler exited due to deadlock");
2868 }
2869
2870 /* Print out file descriptor summary and stats. */
2871 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002872 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002873
2874 if (VG_(needs).core_errors || VG_(needs).skin_errors)
2875 VG_(show_all_errors)();
2876
nethercote47dd12c2004-06-22 14:18:42 +00002877 SK_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002878
nethercote885dd912004-08-03 23:14:00 +00002879 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002880
2881 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002882 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002883
nethercote71980f02004-01-24 18:18:54 +00002884 if (VG_(clo_profile))
2885 VGP_(done_profiling)();
2886
nethercote71980f02004-01-24 18:18:54 +00002887 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2888 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002889 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2890 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002891 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2892
2893 //--------------------------------------------------------------
2894 // Exit, according to the scheduler's return code
2895 //--------------------------------------------------------------
2896 switch (src) {
2897 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002898 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002899 VG_(proxy_shutdown)();
2900
2901 /* The thread's %EBX at the time it did __NR_exit() will hold
2902 the arg to __NR_exit(), so we just do __NR_exit() with
2903 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002904 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002905 /* NOT ALIVE HERE! */
2906 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2907 break; /* what the hell :) */
2908
2909 case VgSrc_Deadlock:
2910 /* Just exit now. No point in continuing. */
2911 VG_(proxy_shutdown)();
2912 VG_(exit)(0);
2913 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2914 break;
2915
nethercote71980f02004-01-24 18:18:54 +00002916 case VgSrc_FatalSig:
2917 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002918 vg_assert(fatal_sigNo != -1);
2919 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002920 VG_(core_panic)("main(): signal was supposed to be fatal");
2921 break;
2922
2923 default:
2924 VG_(core_panic)("main(): unexpected scheduler return code");
2925 }
2926
2927 abort();
2928}
2929
2930
sewardjde4a1d02002-03-22 01:27:54 +00002931/*--------------------------------------------------------------------*/
2932/*--- end vg_main.c ---*/
2933/*--------------------------------------------------------------------*/