blob: 3e17a5a81efde80f833e54bac934d7fd5bffd8c0 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
nethercote71980f02004-01-24 18:18:54 +000035
36#include <dirent.h>
37#include <dlfcn.h>
38#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000039#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000040#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000041#include <string.h>
42#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/wait.h>
46#include <unistd.h>
47
thughes74b8de22004-04-22 18:12:31 +000048#ifndef AT_DCACHEBSIZE
49#define AT_DCACHEBSIZE 19
50#endif /* AT_DCACHEBSIZE */
51
52#ifndef AT_ICACHEBSIZE
53#define AT_ICACHEBSIZE 20
54#endif /* AT_ICACHEBSIZE */
55
56#ifndef AT_UCACHEBSIZE
57#define AT_UCACHEBSIZE 21
58#endif /* AT_UCACHEBSIZE */
59
nethercote71980f02004-01-24 18:18:54 +000060#ifndef AT_SYSINFO
61#define AT_SYSINFO 32
62#endif /* AT_SYSINFO */
63
64#ifndef AT_SYSINFO_EHDR
65#define AT_SYSINFO_EHDR 33
66#endif /* AT_SYSINFO_EHDR */
67
68#ifndef AT_SECURE
69#define AT_SECURE 23 /* secure mode boolean */
70#endif /* AT_SECURE */
71
nethercote71980f02004-01-24 18:18:54 +000072/* redzone gap between client address space and shadow */
73#define REDZONE_SIZE (1 * 1024*1024)
74
75/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000076#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000077
nethercotee2097312004-06-27 12:29:56 +000078/* Proportion of client space for its heap (rest is for mmaps + stack) */
79#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000080
81/*====================================================================*/
82/*=== Global entities not referenced from generated code ===*/
83/*====================================================================*/
84
sewardjde4a1d02002-03-22 01:27:54 +000085/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000086 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000087 ------------------------------------------------------------------ */
88
nethercote71980f02004-01-24 18:18:54 +000089/* Client address space, lowest to highest (see top of ume.c) */
90Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000091Addr VG_(client_end);
92Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000093Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000094Addr VG_(clstk_base);
95Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000096
97Addr VG_(brk_base); /* start of brk */
98Addr VG_(brk_limit); /* current brk */
99
nethercote996901a2004-08-03 13:29:09 +0000100Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000104
nethercote820bd8c2004-09-07 23:04:49 +0000105// Note that VG_(valgrind_last) names the last byte of the section, whereas
106// the VG_(*_end) vars name the byte one past the end of the section.
107Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108
nethercote73b526f2004-10-31 18:48:21 +0000109struct vki_rlimit VG_(client_rlimit_data);
110struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000111
nethercote71980f02004-01-24 18:18:54 +0000112/* This is set early to indicate whether this CPU has the
113 SSE/fxsave/fxrestor features. */
114Bool VG_(have_ssestate);
115
fitzhardinge98abfc72003-12-16 02:05:15 +0000116/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000117static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000118
119/* client executable */
120Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000121
122/* Path to library directory */
123const Char *VG_(libdir) = VG_LIBDIR;
124
125/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000126static Int vg_argc;
127static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000128
jsgf855d93d2003-10-13 22:26:55 +0000129/* PID of the main thread */
130Int VG_(main_pid);
131
132/* PGRP of process */
133Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000134
thughesad1c9562004-06-26 11:27:52 +0000135/* Application-visible file descriptor limits */
136Int VG_(fd_soft_limit) = -1;
137Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000138
nethercote4ad74312004-10-26 09:59:49 +0000139/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000140 envp[] as extracted from the client's stack at startup-time. */
141Int VG_(client_argc);
142Char** VG_(client_argv);
143Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000144
njn16de5572004-11-27 14:27:21 +0000145// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
146UInt VG_(instr_ptr_offset);
147
sewardjde4a1d02002-03-22 01:27:54 +0000148/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000149 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000150 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000151
nethercote71980f02004-01-24 18:18:54 +0000152/* Counts downwards in VG_(run_innerloop). */
153UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000154
155/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000156ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000157
nethercote71980f02004-01-24 18:18:54 +0000158/* Tell the logging mechanism whether we are logging to a file
159 descriptor or a socket descriptor. */
160Bool VG_(logging_to_filedes) = True;
161
sewardj73cf3bc2002-11-03 03:20:15 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/*====================================================================*/
164/*=== Counters, for profiling purposes only ===*/
165/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000166
sewardjde4a1d02002-03-22 01:27:54 +0000167/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000168static UInt sanity_fast_count = 0;
169static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000170
nethercote3a42fb82004-08-03 18:08:50 +0000171static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000172{
nethercote3a42fb82004-08-03 18:08:50 +0000173 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000174 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000175 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000176 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000177
nethercote3a42fb82004-08-03 18:08:50 +0000178 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000179 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000180
nethercote71980f02004-01-24 18:18:54 +0000181 VG_(message)(Vg_DebugMsg,
182 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000183 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000184
nethercote3a42fb82004-08-03 18:08:50 +0000185 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000186 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000187 VG_(message)(Vg_DebugMsg, "");
188 VG_(message)(Vg_DebugMsg,
189 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000190 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000191 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000192 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000193 VG_(message)(Vg_DebugMsg,
194 "------ Valgrind's ExeContext management stats follow ------" );
195 VG_(print_ExeContext_stats)();
196 }
nethercote71980f02004-01-24 18:18:54 +0000197}
198
199
200/*====================================================================*/
201/*=== Miscellaneous global functions ===*/
202/*====================================================================*/
203
nethercotecf97ffb2004-09-09 13:40:31 +0000204static Int ptrace_setregs(Int pid, ThreadId tid)
205{
sewardj2a99cf62004-11-24 10:44:19 +0000206 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000207}
208
nethercote04d0fbc2004-01-26 16:48:06 +0000209/* Start debugger and get it to attach to this process. Called if the
210 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000211 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000212 meaningfully get the debugger to continue the program, though; to
213 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000214void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000215{
216 Int pid;
217
218 if ((pid = fork()) == 0) {
219 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000220 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000221
222 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000223 Int status;
224 Int res;
225
nethercote71980f02004-01-24 18:18:54 +0000226 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
227 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000228 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000229 kill(pid, SIGSTOP) == 0 &&
230 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000231 Char pidbuf[15];
232 Char file[30];
233 Char buf[100];
234 Char *bufptr;
235 Char *cmdptr;
236
237 VG_(sprintf)(pidbuf, "%d", pid);
238 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
239
240 bufptr = buf;
241 cmdptr = VG_(clo_db_command);
242
243 while (*cmdptr) {
244 switch (*cmdptr) {
245 case '%':
246 switch (*++cmdptr) {
247 case 'f':
248 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
249 bufptr += VG_(strlen)(file);
250 cmdptr++;
251 break;
252 case 'p':
253 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
254 bufptr += VG_(strlen)(pidbuf);
255 cmdptr++;
256 break;
257 default:
258 *bufptr++ = *cmdptr++;
259 break;
260 }
261 break;
262 default:
263 *bufptr++ = *cmdptr++;
264 break;
265 }
266 }
267
268 *bufptr++ = '\0';
269
270 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000271 res = VG_(system)(buf);
272 if (res == 0) {
273 VG_(message)(Vg_UserMsg, "");
274 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000275 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000276 } else {
277 VG_(message)(Vg_UserMsg, "Apparently failed!");
278 VG_(message)(Vg_UserMsg, "");
279 }
280 }
281
nethercote73b526f2004-10-31 18:48:21 +0000282 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000283 VG_(waitpid)(pid, &status, 0);
284 }
285}
286
287
288/* Print some helpful-ish text about unimplemented things, and give
289 up. */
290void VG_(unimplemented) ( Char* msg )
291{
292 VG_(message)(Vg_UserMsg, "");
293 VG_(message)(Vg_UserMsg,
294 "Valgrind detected that your program requires");
295 VG_(message)(Vg_UserMsg,
296 "the following unimplemented functionality:");
297 VG_(message)(Vg_UserMsg, " %s", msg);
298 VG_(message)(Vg_UserMsg,
299 "This may be because the functionality is hard to implement,");
300 VG_(message)(Vg_UserMsg,
301 "or because no reasonable program would behave this way,");
302 VG_(message)(Vg_UserMsg,
303 "or because nobody has yet needed it. In any case, let us know at");
304 VG_(message)(Vg_UserMsg,
305 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
306 VG_(message)(Vg_UserMsg,
307 "");
308 VG_(message)(Vg_UserMsg,
309 "Valgrind has to exit now. Sorry. Bye!");
310 VG_(message)(Vg_UserMsg,
311 "");
312 VG_(pp_sched_status)();
313 VG_(exit)(1);
314}
315
sewardj2a99cf62004-11-24 10:44:19 +0000316/* Get the simulated stack pointer */
317Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000318{
njncf45fd42004-11-24 16:30:22 +0000319 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000320}
321
322/* Initialize the PID and PGRP of scheduler LWP; this is also called
323 in any new children after fork. */
324static void newpid(ThreadId unused)
325{
326 /* PID of scheduler LWP */
327 VG_(main_pid) = VG_(getpid)();
328 VG_(main_pgrp) = VG_(getpgrp)();
329}
330
331/*====================================================================*/
332/*=== Check we were launched by stage 1 ===*/
333/*====================================================================*/
334
335/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000336int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000337{
nethercoteebf1d862004-11-01 18:22:05 +0000338 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000339 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000340
341 for (; auxv->a_type != AT_NULL; auxv++)
342 switch(auxv->a_type) {
343 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000344 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000345 found |= 1;
346 break;
347
348 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000349 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000350 found |= 2;
351 break;
nethercote7f390022004-10-25 17:18:24 +0000352
353 case AT_PHDR:
354 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
355 break;
nethercote71980f02004-01-24 18:18:54 +0000356 }
357
nethercote361a14e2004-07-26 11:11:56 +0000358 if ( found != (1|2) ) {
359 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000360 exit(127);
361 }
nethercote31779c72004-07-30 21:50:15 +0000362 vg_assert(padfile >= 0);
363 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000364}
365
366
367/*====================================================================*/
368/*=== Address space determination ===*/
369/*====================================================================*/
370
nethercote7f390022004-10-25 17:18:24 +0000371extern char _start[];
372
nethercote31779c72004-07-30 21:50:15 +0000373static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000374{
nethercotea3c3cf22004-11-01 18:38:00 +0000375 Int ires;
376 void* vres;
377 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000378
nethercote7f390022004-10-25 17:18:24 +0000379 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
380 // this is a workable approximation
381 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000382 VG_(valgrind_base) = PGROUNDDN(&_start);
383 }
384
nethercote820bd8c2004-09-07 23:04:49 +0000385 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000386
nethercote31779c72004-07-30 21:50:15 +0000387 // This gives the client the largest possible address space while
388 // taking into account the tool's shadow needs.
389 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000390 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000391 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000392 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000393 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000394 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000395 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000396
nethercote31779c72004-07-30 21:50:15 +0000397 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000398 VG_(shadow_end) = VG_(valgrind_base);
399 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000400
nethercotee2097312004-06-27 12:29:56 +0000401#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
402
nethercote71980f02004-01-24 18:18:54 +0000403 if (0)
nethercotee2097312004-06-27 12:29:56 +0000404 VG_(printf)(
405 "client_base %8x (%dMB)\n"
406 "client_mapbase %8x (%dMB)\n"
407 "client_end %8x (%dMB)\n"
408 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000409 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000410 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000411 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000412 VG_(client_base), SEGSIZE(client_base, client_mapbase),
413 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
414 VG_(client_end), SEGSIZE(client_end, shadow_base),
415 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000416 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000417 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
418 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000419 );
420
421#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000422
423 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000424 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000425 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000426 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000427
428 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000429 ires = munmap((void*)VG_(client_base), client_size);
430 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000431
432 // Map shadow memory.
433 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000434 if (shadow_size != 0) {
435 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000436 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000437 if ((void*)-1 == vres) {
438 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000439 "valgrind: Could not allocate address space (%p bytes)\n"
440 "valgrind: for shadow memory\n"
441 "valgrind: Possible causes:\n"
442 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
443 "valgrind: needs at least 1.5GB swap space.\n"
444 "valgrind: - Or, your virtual memory size may be limited (check\n"
445 "valgrind: with 'ulimit -v').\n"
446 "valgrind: - Or, your system may use a kernel that provides only a\n"
447 "valgrind: too-small (eg. 2GB) user address space.\n"
448 , (void*)shadow_size
449 );
nethercoted4722622004-08-30 19:36:42 +0000450 exit(1);
451 }
nethercotee567e702004-07-10 17:49:17 +0000452 }
nethercote71980f02004-01-24 18:18:54 +0000453}
454
455/*====================================================================*/
456/*=== Command line setup ===*/
457/*====================================================================*/
458
459/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
460static char* get_file_clo(char* dir)
461{
462# define FLEN 512
463 Int fd, n;
464 struct stat s1;
465 char* f_clo = NULL;
466 char filename[FLEN];
467
468 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
469 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
470 if ( fd > 0 ) {
471 if ( 0 == fstat(fd, &s1) ) {
472 f_clo = malloc(s1.st_size+1);
473 vg_assert(f_clo);
474 n = read(fd, f_clo, s1.st_size);
475 if (n == -1) n = 0;
476 f_clo[n] = '\0';
477 }
478 close(fd);
479 }
480 return f_clo;
481# undef FLEN
482}
483
nethercotee2097312004-06-27 12:29:56 +0000484#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
485
nethercote71980f02004-01-24 18:18:54 +0000486static Int count_args(char* s)
487{
488 Int n = 0;
489 if (s) {
490 char* cp = s;
491 while (True) {
492 // We have alternating sequences: blanks, non-blanks, blanks...
493 // count the non-blanks sequences.
494 while ( ISSPACE(*cp) ) cp++;
495 if ( !*cp ) break;
496 n++;
497 while ( !ISSPACE(*cp) && *cp ) cp++;
498 }
499 }
500 return n;
501}
502
503/* add args out of environment, skipping multiple spaces and -- args */
504static char** copy_args( char* s, char** to )
505{
506 if (s) {
507 char* cp = s;
508 while (True) {
509 // We have alternating sequences: blanks, non-blanks, blanks...
510 // copy the non-blanks sequences, and add terminating '\0'
511 while ( ISSPACE(*cp) ) cp++;
512 if ( !*cp ) break;
513 *to++ = cp;
514 while ( !ISSPACE(*cp) && *cp ) cp++;
515 if ( *cp ) *cp++ = '\0'; // terminate if necessary
516 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
517 }
518 }
519 return to;
520}
521
nethercotee2097312004-06-27 12:29:56 +0000522#undef ISSPACE
523
nethercote71980f02004-01-24 18:18:54 +0000524// Augment command line with arguments from environment and .valgrindrc
525// files.
526static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
527{
nethercotef6a1d502004-08-09 12:21:57 +0000528 int vg_argc0 = *vg_argc_inout;
529 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000530
531 char* env_clo = getenv(VALGRINDOPTS);
532 char* f1_clo = get_file_clo( getenv("HOME") );
533 char* f2_clo = get_file_clo(".");
534
535 /* copy any extra args from file or environment, if present */
536 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
537 /* ' ' separated extra options */
538 char **from;
539 char **to;
thughescaca0022004-09-13 10:20:34 +0000540 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
541
542 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
543
nethercote71980f02004-01-24 18:18:54 +0000544 env_arg_count = count_args(env_clo);
545 f1_arg_count = count_args(f1_clo);
546 f2_arg_count = count_args(f2_clo);
547
548 if (0)
549 printf("extra-argc=%d %d %d\n",
550 env_arg_count, f1_arg_count, f2_arg_count);
551
552 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000553 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000554 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000555 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000556 vg_assert(vg_argv0);
557 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000558
559 /* copy argv[0] */
560 *to++ = *from++;
561
562 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
563 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
564 * to override less local ones. */
565 to = copy_args(f1_clo, to);
566 to = copy_args(env_clo, to);
567 to = copy_args(f2_clo, to);
568
569 /* copy original arguments, stopping at command or -- */
570 while (*from) {
571 if (**from != '-')
572 break;
573 if (VG_STREQ(*from, "--")) {
574 from++; /* skip -- */
575 break;
576 }
577 *to++ = *from++;
578 }
579
580 /* add -- */
581 *to++ = "--";
582
nethercotef6a1d502004-08-09 12:21:57 +0000583 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000584
585 /* copy rest of original command line, then NULL */
586 while (*from) *to++ = *from++;
587 *to = NULL;
588 }
589
nethercotef6a1d502004-08-09 12:21:57 +0000590 *vg_argc_inout = vg_argc0;
591 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000592}
593
nethercotef6a1d502004-08-09 12:21:57 +0000594#define VG_CLO_SEP '\01'
595
nethercote71980f02004-01-24 18:18:54 +0000596static void get_command_line( int argc, char** argv,
597 Int* vg_argc_out, Char*** vg_argv_out,
598 char*** cl_argv_out )
599{
nethercotef6a1d502004-08-09 12:21:57 +0000600 int vg_argc0;
601 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000602 char** cl_argv;
603 char* env_clo = getenv(VALGRINDCLO);
604
605 if (env_clo != NULL && *env_clo != '\0') {
606 char *cp;
607 char **cpp;
608
nethercotef6a1d502004-08-09 12:21:57 +0000609 /* OK, VALGRINDCLO is set, which means we must be a child of another
610 Valgrind process using --trace-children, so we're getting all our
611 arguments from VALGRINDCLO, and the entire command line belongs to
612 the client (including argv[0]) */
613 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000614 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000615 if (*cp == VG_CLO_SEP)
616 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000617
nethercotef6a1d502004-08-09 12:21:57 +0000618 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
619 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000620
nethercotef6a1d502004-08-09 12:21:57 +0000621 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000622
623 *cpp++ = "valgrind"; /* nominal argv[0] */
624 *cpp++ = env_clo;
625
nethercotef6a1d502004-08-09 12:21:57 +0000626 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000627 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000628 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000629 *cp++ = '\0'; /* chop it up in place */
630 *cpp++ = cp;
631 }
632 }
633 *cpp = NULL;
634 cl_argv = argv;
635
636 } else {
637 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000638 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000639
nethercotef6a1d502004-08-09 12:21:57 +0000640 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
641 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000642 break;
nethercotef6a1d502004-08-09 12:21:57 +0000643 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
644 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000645 break;
646 }
647 }
nethercotef6a1d502004-08-09 12:21:57 +0000648 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000649
650 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000651 Note we don't do this if getting args from VALGRINDCLO, as
652 those extra args will already be present in VALGRINDCLO. */
653 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000654 }
655
656 if (0) {
657 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000658 for (i = 0; i < vg_argc0; i++)
659 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000660 }
661
nethercotef6a1d502004-08-09 12:21:57 +0000662 *vg_argc_out = vg_argc0;
663 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000664 *cl_argv_out = cl_argv;
665}
666
667
668/*====================================================================*/
669/*=== Environment and stack setup ===*/
670/*====================================================================*/
671
672/* Scan a colon-separated list, and call a function on each element.
673 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000674 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000675 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000676
677 This routine will return True if (*func) returns True and False if
678 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000679*/
thughes4ad52d02004-06-27 17:37:21 +0000680static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000681{
682 char *cp, *entry;
683 int end;
684
685 if (colsep == NULL ||
686 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000687 return False;
nethercote71980f02004-01-24 18:18:54 +0000688
689 entry = cp = colsep;
690
691 do {
692 end = (*cp == '\0');
693
694 if (*cp == ':' || *cp == '\0') {
695 char save = *cp;
696
697 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000698 if ((*func)(entry)) {
699 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000700 return True;
thughes21942d92004-07-12 09:35:37 +0000701 }
nethercote71980f02004-01-24 18:18:54 +0000702 *cp = save;
703 entry = cp+1;
704 }
705 cp++;
706 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000707
708 return False;
709}
710
711static Bool contains(const char *p) {
712 if (VG_STREQ(p, VG_(libdir))) {
713 return True;
714 }
715 return False;
nethercote71980f02004-01-24 18:18:54 +0000716}
717
718/* Prepare the client's environment. This is basically a copy of our
719 environment, except:
720 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
721 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
722
723 If any of these is missing, then it is added.
724
725 Yummy. String hacking in C.
726
727 If this needs to handle any more variables it should be hacked
728 into something table driven.
729 */
730static char **fix_environment(char **origenv, const char *preload)
731{
732 static const char inject_so[] = "vg_inject.so";
733 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
734 static const char ld_preload[] = "LD_PRELOAD=";
735 static const char valgrind_clo[] = VALGRINDCLO "=";
736 static const int ld_library_path_len = sizeof(ld_library_path)-1;
737 static const int ld_preload_len = sizeof(ld_preload)-1;
738 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
739 int ld_preload_done = 0;
740 int ld_library_path_done = 0;
741 char *inject_path;
742 int inject_path_len;
743 int vgliblen = strlen(VG_(libdir));
744 char **cpp;
745 char **ret;
746 int envc;
747 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
748
749 /* Find the vg_inject.so; also make room for the tool preload
750 library */
751 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
752 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000753 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000754
755 if (preload)
756 snprintf(inject_path, inject_path_len, "%s/%s:%s",
757 VG_(libdir), inject_so, preload);
758 else
759 snprintf(inject_path, inject_path_len, "%s/%s",
760 VG_(libdir), inject_so);
761
762 /* Count the original size of the env */
763 envc = 0; /* trailing NULL */
764 for (cpp = origenv; cpp && *cpp; cpp++)
765 envc++;
766
767 /* Allocate a new space */
768 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000769 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000770
771 /* copy it over */
772 for (cpp = ret; *origenv; )
773 *cpp++ = *origenv++;
774 *cpp = NULL;
775
776 vg_assert(envc == (cpp - ret));
777
778 /* Walk over the new environment, mashing as we go */
779 for (cpp = ret; cpp && *cpp; cpp++) {
780 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000781 /* If the LD_LIBRARY_PATH already contains libdir, then don't
782 bother adding it again, even if it isn't the first (it
783 seems that the Java runtime will keep reexecing itself
784 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000785 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000786 int len = strlen(*cpp) + vgliblen*2 + 16;
787 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000788 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000789
790 snprintf(cp, len, "%s%s:%s",
791 ld_library_path, VG_(libdir),
792 (*cpp)+ld_library_path_len);
793
794 *cpp = cp;
795 }
796
797 ld_library_path_done = 1;
798 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
799 int len = strlen(*cpp) + inject_path_len;
800 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000801 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000802
803 snprintf(cp, len, "%s%s:%s",
804 ld_preload, inject_path, (*cpp)+ld_preload_len);
805
806 *cpp = cp;
807
808 ld_preload_done = 1;
809 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
810 *cpp = "";
811 }
812 }
813
814 /* Add the missing bits */
815
816 if (!ld_library_path_done) {
817 int len = ld_library_path_len + vgliblen*2 + 16;
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", ld_library_path, VG_(libdir));
822
823 ret[envc++] = cp;
824 }
825
826 if (!ld_preload_done) {
827 int len = ld_preload_len + inject_path_len;
828 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000829 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000830
831 snprintf(cp, len, "%s%s",
832 ld_preload, inject_path);
833
834 ret[envc++] = cp;
835 }
836
837 ret[envc] = NULL;
838
839 return ret;
840}
841
842extern char **environ; /* our environment */
843//#include <error.h>
844
845/* Add a string onto the string table, and return its address */
846static char *copy_str(char **tab, const char *str)
847{
848 char *cp = *tab;
849 char *orig = cp;
850
851 while(*str)
852 *cp++ = *str++;
853 *cp++ = '\0';
854
855 if (0)
nethercote545fe672004-11-01 16:52:43 +0000856 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000857
858 *tab = cp;
859
860 return orig;
861}
862
863/*
864 This sets up the client's initial stack, containing the args,
865 environment and aux vector.
866
867 The format of the stack is:
868
869 higher address +-----------------+
870 | Trampoline code |
871 +-----------------+
872 | |
873 : string table :
874 | |
875 +-----------------+
876 | AT_NULL |
877 - -
878 | auxv |
879 +-----------------+
880 | NULL |
881 - -
882 | envp |
883 +-----------------+
884 | NULL |
885 - -
886 | argv |
887 +-----------------+
888 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000889 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000890 | undefined |
891 : :
892 */
nethercotec25c4492004-10-18 11:52:17 +0000893static Addr setup_client_stack(void* init_sp,
894 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000895 const struct exeinfo *info,
896 UInt** client_auxv)
897{
nethercotee567e702004-07-10 17:49:17 +0000898 void* res;
nethercote71980f02004-01-24 18:18:54 +0000899 char **cpp;
900 char *strtab; /* string table */
901 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000902 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000903 struct ume_auxv *auxv;
904 const struct ume_auxv *orig_auxv;
905 const struct ume_auxv *cauxv;
906 unsigned stringsize; /* total size of strings in bytes */
907 unsigned auxsize; /* total size of auxv in bytes */
908 int argc; /* total argc */
909 int envc; /* total number of env vars */
910 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000911 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000912
913 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000914 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000915
916 /* ==================== compute sizes ==================== */
917
918 /* first of all, work out how big the client stack will be */
919 stringsize = 0;
920
921 /* paste on the extra args if the loader needs them (ie, the #!
922 interpreter and its argument) */
923 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000924 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000925 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000926 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000927 }
nethercoted6a56872004-07-26 15:32:47 +0000928 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000929 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000930 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000931 }
932
933 /* now scan the args we're given... */
934 for (cpp = orig_argv; *cpp; cpp++) {
935 argc++;
936 stringsize += strlen(*cpp) + 1;
937 }
938
939 /* ...and the environment */
940 envc = 0;
941 for (cpp = orig_envp; cpp && *cpp; cpp++) {
942 envc++;
943 stringsize += strlen(*cpp) + 1;
944 }
945
946 /* now, how big is the auxv? */
947 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
948 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
949 if (cauxv->a_type == AT_PLATFORM)
950 stringsize += strlen(cauxv->u.a_ptr) + 1;
951 auxsize += sizeof(*cauxv);
952 }
953
954 /* OK, now we know how big the client stack is */
955 stacksize =
956 sizeof(int) + /* argc */
957 sizeof(char **)*argc + /* argv */
958 sizeof(char **) + /* terminal NULL */
959 sizeof(char **)*envc + /* envp */
960 sizeof(char **) + /* terminal NULL */
961 auxsize + /* auxv */
962 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000963 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000964
nethercotef84f6952004-07-15 14:58:33 +0000965 // decide where stack goes!
966 VG_(clstk_end) = VG_(client_end);
967
nethercote73b526f2004-10-31 18:48:21 +0000968 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000969
nethercote71980f02004-01-24 18:18:54 +0000970 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000971 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000972 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
973
nethercote71980f02004-01-24 18:18:54 +0000974 /* base of the string table (aligned) */
975 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
976
977 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000978
nethercote5ee67ca2004-06-22 14:00:09 +0000979 if (0)
980 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000981 "clstk_base %p\n"
982 "clstk_end %p\n",
983 stringsize, auxsize, stacksize,
984 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000985
986
nethercote71980f02004-01-24 18:18:54 +0000987 /* ==================== allocate space ==================== */
988
989 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000990 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000991 PROT_READ | PROT_WRITE | PROT_EXEC,
992 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
993 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000994
995 /* ==================== copy client stack ==================== */
996
nethercotea3c3cf22004-11-01 18:38:00 +0000997 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000998
999 /* --- argc --- */
1000 *ptr++ = argc; /* client argc */
1001
1002 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001003 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001004 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001005 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001006 }
nethercoted6a56872004-07-26 15:32:47 +00001007 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001008 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001009 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001010 }
1011 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001012 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001013 }
1014 *ptr++ = 0;
1015
1016 /* --- envp --- */
1017 VG_(client_envp) = (Char **)ptr;
1018 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001019 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001020 *ptr++ = 0;
1021
1022 /* --- auxv --- */
1023 auxv = (struct ume_auxv *)ptr;
1024 *client_auxv = (UInt *)auxv;
1025
1026 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1027 /* copy the entry... */
1028 *auxv = *orig_auxv;
1029
1030 /* ...and fix up the copy */
1031 switch(auxv->a_type) {
1032 case AT_PHDR:
1033 if (info->phdr == 0)
1034 auxv->a_type = AT_IGNORE;
1035 else
1036 auxv->u.a_val = info->phdr;
1037 break;
1038
1039 case AT_PHNUM:
1040 if (info->phdr == 0)
1041 auxv->a_type = AT_IGNORE;
1042 else
1043 auxv->u.a_val = info->phnum;
1044 break;
1045
1046 case AT_BASE:
1047 if (info->interp_base == 0)
1048 auxv->a_type = AT_IGNORE;
1049 else
1050 auxv->u.a_val = info->interp_base;
1051 break;
1052
1053 case AT_PLATFORM: /* points to a platform description string */
1054 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1055 break;
1056
1057 case AT_ENTRY:
1058 auxv->u.a_val = info->entry;
1059 break;
1060
1061 case AT_IGNORE:
1062 case AT_EXECFD:
1063 case AT_PHENT:
1064 case AT_PAGESZ:
1065 case AT_FLAGS:
1066 case AT_NOTELF:
1067 case AT_UID:
1068 case AT_EUID:
1069 case AT_GID:
1070 case AT_EGID:
1071 case AT_CLKTCK:
1072 case AT_HWCAP:
1073 case AT_FPUCW:
1074 case AT_DCACHEBSIZE:
1075 case AT_ICACHEBSIZE:
1076 case AT_UCACHEBSIZE:
1077 /* All these are pointerless, so we don't need to do anything
1078 about them. */
1079 break;
1080
1081 case AT_SECURE:
1082 /* If this is 1, then it means that this program is running
1083 suid, and therefore the dynamic linker should be careful
1084 about LD_PRELOAD, etc. However, since stage1 (the thing
1085 the kernel actually execve's) should never be SUID, and we
1086 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1087 set AT_SECURE to 0. */
1088 auxv->u.a_val = 0;
1089 break;
1090
1091 case AT_SYSINFO:
1092 /* Leave this unmolested for now, but we'll update it later
1093 when we set up the client trampoline code page */
1094 break;
1095
1096 case AT_SYSINFO_EHDR:
1097 /* Trash this, because we don't reproduce it */
1098 auxv->a_type = AT_IGNORE;
1099 break;
1100
1101 default:
1102 /* stomp out anything we don't know about */
1103 if (0)
nethercote545fe672004-11-01 16:52:43 +00001104 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001105 auxv->a_type = AT_IGNORE;
1106 break;
1107
1108 }
1109 }
1110 *auxv = *orig_auxv;
1111 vg_assert(auxv->a_type == AT_NULL);
1112
njnc6168192004-11-29 13:54:10 +00001113// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1114// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
njnca0518d2004-11-26 19:34:36 +00001115#ifdef __x86__
nethercotef84f6952004-07-15 14:58:33 +00001116 /* --- trampoline page --- */
1117 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1118 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001119#endif
nethercotef84f6952004-07-15 14:58:33 +00001120
nethercote71980f02004-01-24 18:18:54 +00001121 vg_assert((strtab-stringbase) == stringsize);
1122
nethercote5ee67ca2004-06-22 14:00:09 +00001123 /* We know the initial ESP is pointing at argc/argv */
1124 VG_(client_argc) = *(Int*)cl_esp;
1125 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1126
nethercote71980f02004-01-24 18:18:54 +00001127 return cl_esp;
1128}
1129
1130/*====================================================================*/
1131/*=== Find executable ===*/
1132/*====================================================================*/
1133
thughes4ad52d02004-06-27 17:37:21 +00001134static const char* executable_name;
1135
1136static Bool match_executable(const char *entry) {
1137 char buf[strlen(entry) + strlen(executable_name) + 2];
1138
1139 /* empty PATH element means . */
1140 if (*entry == '\0')
1141 entry = ".";
1142
1143 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1144
1145 if (access(buf, R_OK|X_OK) == 0) {
1146 executable_name = strdup(buf);
1147 vg_assert(NULL != executable_name);
1148 return True;
1149 }
1150 return False;
1151}
1152
nethercote71980f02004-01-24 18:18:54 +00001153static const char* find_executable(const char* exec)
1154{
1155 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001156 executable_name = exec;
1157 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001158 /* no '/' - we need to search the path */
1159 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001160 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001161 }
thughes4ad52d02004-06-27 17:37:21 +00001162 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001163}
1164
1165
1166/*====================================================================*/
1167/*=== Loading tools ===*/
1168/*====================================================================*/
1169
1170static void list_tools(void)
1171{
1172 DIR *dir = opendir(VG_(libdir));
1173 struct dirent *de;
1174 int first = 1;
1175
1176 if (dir == NULL) {
1177 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001178 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001179 return;
1180 }
1181
nethercotef4928da2004-06-15 10:54:40 +00001182 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001183 int len = strlen(de->d_name);
1184
njn063c5402004-11-22 16:58:05 +00001185 /* look for vgtool_TOOL.so names */
1186 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1187 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001188 VG_STREQ(de->d_name + len - 3, ".so")) {
1189 if (first) {
1190 fprintf(stderr, "Available tools:\n");
1191 first = 0;
1192 }
1193 de->d_name[len-3] = '\0';
1194 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001195 }
1196 }
1197
1198 closedir(dir);
1199
1200 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001201 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1202 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001203}
1204
1205
1206/* Find and load a tool, and check it looks ok. Also looks to see if there's
1207 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1208static void load_tool( const char *toolname, void** handle_out,
1209 ToolInfo** toolinfo_out, char **preloadpath_out )
1210{
1211 Bool ok;
1212 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1213 char buf[len];
1214 void* handle;
1215 ToolInfo* toolinfo;
1216 char* preloadpath = NULL;
1217 Int* vg_malloc_redzonep;
1218
1219 // XXX: allowing full paths for --tool option -- does it make sense?
1220 // Doesn't allow for vgpreload_<tool>.so.
1221
1222 if (strchr(toolname, '/') != 0) {
1223 /* toolname contains '/', and so must be a pathname */
1224 handle = dlopen(toolname, RTLD_NOW);
1225 } else {
1226 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001227 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001228 handle = dlopen(buf, RTLD_NOW);
1229
1230 if (handle != NULL) {
1231 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1232 if (access(buf, R_OK) == 0) {
1233 preloadpath = strdup(buf);
1234 vg_assert(NULL != preloadpath);
1235 }
1236 }
1237 }
1238
1239 ok = (NULL != handle);
1240 if (!ok) {
1241 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1242 goto bad_load;
1243 }
1244
njn26f02512004-11-22 18:33:15 +00001245 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001246 ok = (NULL != toolinfo);
1247 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001248 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001249 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1250 goto bad_load;
1251 }
1252
1253 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1254 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001255 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001256 if (!ok) {
1257 fprintf(stderr, "Error:\n"
1258 " Tool and core interface versions do not match.\n"
1259 " Interface version used by core is: %d.%d (size %d)\n"
1260 " Interface version used by tool is: %d.%d (size %d)\n"
1261 " The major version numbers must match.\n",
1262 VG_CORE_INTERFACE_MAJOR_VERSION,
1263 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001264 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001265 toolinfo->interface_major_version,
1266 toolinfo->interface_minor_version,
1267 toolinfo->sizeof_ToolInfo);
1268 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1269 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001270 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001271 else
nethercote996901a2004-08-03 13:29:09 +00001272 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001273 goto bad_load;
1274 }
1275
1276 // Set redzone size for V's allocator
1277 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1278 if ( NULL != vg_malloc_redzonep ) {
1279 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1280 }
1281
1282 vg_assert(NULL != handle && NULL != toolinfo);
1283 *handle_out = handle;
1284 *toolinfo_out = toolinfo;
1285 *preloadpath_out = preloadpath;
1286 return;
1287
1288
1289 bad_load:
1290 if (handle != NULL)
1291 dlclose(handle);
1292
nethercotef4928da2004-06-15 10:54:40 +00001293 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001294 list_tools();
1295 exit(127);
1296}
1297
nethercotef4928da2004-06-15 10:54:40 +00001298
1299/*====================================================================*/
1300/*=== Command line errors ===*/
1301/*====================================================================*/
1302
1303static void abort_msg ( void )
1304{
nethercotef8548672004-06-21 12:42:35 +00001305 VG_(clo_log_to) = VgLogTo_Fd;
1306 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001307}
1308
1309void VG_(bad_option) ( Char* opt )
1310{
1311 abort_msg();
1312 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1313 VG_(printf)("valgrind: Use --help for more information.\n");
1314 VG_(exit)(1);
1315}
1316
1317static void missing_tool_option ( void )
1318{
1319 abort_msg();
1320 VG_(printf)("valgrind: Missing --tool option\n");
1321 list_tools();
1322 VG_(printf)("valgrind: Use --help for more information.\n");
1323 VG_(exit)(1);
1324}
1325
1326static void missing_prog ( void )
1327{
1328 abort_msg();
1329 VG_(printf)("valgrind: no program specified\n");
1330 VG_(printf)("valgrind: Use --help for more information.\n");
1331 VG_(exit)(1);
1332}
1333
1334static void config_error ( Char* msg )
1335{
1336 abort_msg();
1337 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1338 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1339 VG_(exit)(1);
1340}
1341
1342
nethercote71980f02004-01-24 18:18:54 +00001343/*====================================================================*/
1344/*=== Loading the client ===*/
1345/*====================================================================*/
1346
nethercotef4928da2004-06-15 10:54:40 +00001347static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001348 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1349{
1350 // If they didn't specify an executable with --exec, and didn't specify
1351 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001352 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001353 if (cl_argv[0] == NULL ||
1354 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1355 {
nethercotef4928da2004-06-15 10:54:40 +00001356 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001357 }
1358 }
1359
1360 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001361 info->exe_base = VG_(client_base);
1362 info->exe_end = VG_(client_end);
1363 info->argv = cl_argv;
1364
nethercotef4928da2004-06-15 10:54:40 +00001365 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001366 VG_(clexecfd) = -1;
nethercoteea147e72004-07-26 15:43:57 +00001367 // Set the minimal number of entries in 'info' to continue.
nethercoted6a56872004-07-26 15:32:47 +00001368 info->interp_name = NULL;
1369 info->interp_args = NULL;
nethercote71980f02004-01-24 18:18:54 +00001370 } else {
1371 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001372 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001373 ret = do_exec(exec, info);
1374 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001375 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1376 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001377 exit(127);
1378 }
1379 }
1380
1381 /* Copy necessary bits of 'info' that were filled in */
1382 *client_eip = info->init_eip;
1383 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1384}
1385
nethercote969ecf12004-10-13 17:29:01 +00001386/*====================================================================*/
1387/*=== Address space unpadding ===*/
1388/*====================================================================*/
1389
1390typedef struct {
1391 char* killpad_start;
1392 char* killpad_end;
1393 struct stat* killpad_padstat;
1394} killpad_extra;
1395
1396static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1397 int maj, int min, int ino, void* ex)
1398{
1399 killpad_extra* extra = ex;
1400 void *b, *e;
1401 int res;
1402
1403 vg_assert(NULL != extra->killpad_padstat);
1404
1405 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1406 extra->killpad_padstat->st_ino != ino)
1407 return 1;
1408
1409 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1410 return 1;
1411
1412 if (segstart <= extra->killpad_start)
1413 b = extra->killpad_start;
1414 else
1415 b = segstart;
1416
1417 if (segend >= extra->killpad_end)
1418 e = extra->killpad_end;
1419 else
1420 e = segend;
1421
1422 res = munmap(b, (char *)e-(char *)b);
1423 vg_assert(0 == res);
1424
1425 return 1;
1426}
1427
1428// Remove padding of 'padfile' from a range of address space.
1429void as_unpad(void *start, void *end, int padfile)
1430{
1431 static struct stat padstat;
1432 killpad_extra extra;
1433 int res;
1434
1435 vg_assert(padfile > 0);
1436
1437 res = fstat(padfile, &padstat);
1438 vg_assert(0 == res);
1439 extra.killpad_padstat = &padstat;
1440 extra.killpad_start = start;
1441 extra.killpad_end = end;
1442 foreach_map(killpad, &extra);
1443}
1444
1445void as_closepadfile(int padfile)
1446{
1447 int res = close(padfile);
1448 vg_assert(0 == res);
1449}
1450
nethercote71980f02004-01-24 18:18:54 +00001451
1452/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001453/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001454/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001455
njn25e49d8e72002-09-23 09:36:25 +00001456/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001457VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001458Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001459Bool VG_(clo_db_attach) = False;
1460Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001461Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001462Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001463Int VG_(clo_verbosity) = 1;
1464Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001465Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001466
nethercotef1e5e152004-09-01 23:58:16 +00001467/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001468 fd is initially stdout, for --help, but gets moved to stderr by default
1469 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001470VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001471Int VG_(clo_log_fd) = 1;
1472Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001473
thughes6233a382004-08-21 11:10:44 +00001474Bool VG_(clo_time_stamp) = False;
1475
sewardj6024b212003-07-13 10:54:33 +00001476Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001477Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001478Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001479Bool VG_(clo_profile) = False;
sewardj8e4d7dc2004-11-28 18:07:41 +00001480Bool VG_(clo_bbprofile) = False;
njn25e49d8e72002-09-23 09:36:25 +00001481UChar VG_(clo_trace_codegen) = 0; // 00000000b
1482Bool VG_(clo_trace_syscalls) = False;
1483Bool VG_(clo_trace_signals) = False;
1484Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001485Bool VG_(clo_trace_sched) = False;
1486Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001487Int VG_(clo_dump_error) = 0;
1488Int VG_(clo_backtrace_size) = 4;
1489Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001490Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001491Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001492Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001493Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001494Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001495
jsgf855d93d2003-10-13 22:26:55 +00001496static Bool VG_(clo_wait_for_gdb) = False;
1497
1498/* If we're doing signal routing, poll for signals every 50mS by
1499 default. */
1500Int VG_(clo_signal_polltime) = 50;
1501
1502/* These flags reduce thread wakeup latency on syscall completion and
1503 signal delivery, respectively. The downside is possible unfairness. */
1504Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1505Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1506
sewardjde4a1d02002-03-22 01:27:54 +00001507
nethercote6c999f22004-01-31 22:55:15 +00001508void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001509{
njn25e49d8e72002-09-23 09:36:25 +00001510 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001511"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001512"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001513" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001514" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001515" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001516" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001518" -q --quiet run silently; only print error msgs\n"
1519" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001520" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001521" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001522" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001523"\n"
1524" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001525" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1526" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1527" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1528" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1529" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001530" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001531"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001532" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001533" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1534" --log-file=<file> log messages to <file>.pid<pid>\n"
1535" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001536" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1537" --num-callers=<number> show <num> callers in stack traces [4]\n"
1538" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1539" --show-below-main=no|yes continue stack traces below main() [no]\n"
1540" --suppressions=<filename> suppress errors described in <filename>\n"
1541" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001542" --db-attach=no|yes start debugger when errors detected? [no]\n"
1543" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1544" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001545"\n";
njn7cf0bd32002-06-08 13:36:03 +00001546
njn25e49d8e72002-09-23 09:36:25 +00001547 Char* usage2 =
1548"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001549" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001550" --sanity-level=<number> level of sanity checking to do [1]\n"
1551" --single-step=no|yes translate each instr separately? [no]\n"
1552" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001553" --profile=no|yes profile? (tool must be built for it) [no]\n"
sewardj8e4d7dc2004-11-28 18:07:41 +00001554" --bbprofile=no|yes profile bbs?\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001555" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001556" --trace-codegen=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
njn25e49d8e72002-09-23 09:36:25 +00001557" --trace-syscalls=no|yes show all system calls? [no]\n"
1558" --trace-signals=no|yes show signal handling details? [no]\n"
1559" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001560" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001561" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001562" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001563"\n"
sewardj8b635a42004-11-22 19:01:47 +00001564" --vex-iropt-verbosity 0 .. 9 [0]\n"
1565" --vex-iropt-level 0 .. 2 [2]\n"
1566" --vex-iropt-precise-memory-exns [no]\n"
1567" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1568" --vex-guest-max-insns 1 .. 100 [50]\n"
1569" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1570"\n"
sewardj2a99cf62004-11-24 10:44:19 +00001571" --trace-codegen values (omit the middle space):\n"
1572" 1000 0000 show conversion into IR\n"
1573" 0100 0000 show after initial opt\n"
1574" 0010 0000 show after instrumentation\n"
1575" 0001 0000 show after second opt\n"
1576" 0000 1000 show after tree building\n"
1577" 0000 0100 show selecting insns\n"
1578" 0000 0010 show after reg-alloc\n"
1579" 0000 0001 show final assembly\n"
1580"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001581" debugging options for Valgrind tools that report errors\n"
1582" --dump-error=<number> show translation for basic block associated\n"
1583" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001584"\n";
njn3e884182003-04-15 13:03:23 +00001585
1586 Char* usage3 =
1587"\n"
nethercote71980f02004-01-24 18:18:54 +00001588" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001589"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001590" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001591" and licensed under the GNU General Public License, version 2.\n"
1592" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001593"\n"
nethercote137bc552003-11-14 17:47:54 +00001594" Tools are copyright and licensed by their authors. See each\n"
1595" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001596"\n";
njn7cf0bd32002-06-08 13:36:03 +00001597
fitzhardinge98abfc72003-12-16 02:05:15 +00001598 VG_(printf)(usage1);
1599 if (VG_(details).name) {
1600 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001601 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001602 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 else
1604 VG_(printf)(" (none)\n");
1605 }
nethercote6c999f22004-01-31 22:55:15 +00001606 if (debug_help) {
1607 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001608
nethercote6c999f22004-01-31 22:55:15 +00001609 if (VG_(details).name) {
1610 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1611
1612 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001613 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001614 else
1615 VG_(printf)(" (none)\n");
1616 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 }
nethercote421281e2003-11-20 16:20:55 +00001618 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001619 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001620}
sewardjde4a1d02002-03-22 01:27:54 +00001621
nethercote71980f02004-01-24 18:18:54 +00001622static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001623 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001624{
nethercote71980f02004-01-24 18:18:54 +00001625 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001626
sewardj8b635a42004-11-22 19:01:47 +00001627 LibVEX_default_VexControl(& VG_(clo_vex_control));
1628
nethercote71980f02004-01-24 18:18:54 +00001629 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001630 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001631
nethercotef6a1d502004-08-09 12:21:57 +00001632 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001633 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001634 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001635
nethercotef6a1d502004-08-09 12:21:57 +00001636 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1637 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001638 *need_help = 1;
1639
nethercotef6a1d502004-08-09 12:21:57 +00001640 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001641 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001642
nethercotef6c99d72004-11-09 14:35:43 +00001643 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001644 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001645
nethercotef6a1d502004-08-09 12:21:57 +00001646 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1647 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001648 }
1649 }
1650
nethercotef4928da2004-06-15 10:54:40 +00001651 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001652 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001653 if (0 == *need_help) {
1654 // neither --tool nor --help/--help-debug specified
1655 missing_tool_option();
1656 } else {
1657 // Give help message, without any tool-specific help
1658 usage(/*help-debug?*/2 == *need_help);
1659 }
nethercote71980f02004-01-24 18:18:54 +00001660 }
1661}
1662
nethercote5ee67ca2004-06-22 14:00:09 +00001663static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001664{
nethercotef8548672004-06-21 12:42:35 +00001665 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001666 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001667
nethercotee1730692003-11-20 10:38:07 +00001668 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001669 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001670
sewardj19d81412002-06-03 01:10:40 +00001671 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001672 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001673 config_error("Please use absolute paths in "
1674 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001675
njnc6168192004-11-29 13:54:10 +00001676// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001677#ifdef __x86__
1678 {
1679 Int *auxp;
1680 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1681 switch(auxp[0]) {
1682 case AT_SYSINFO:
1683 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1684 break;
1685 }
1686 }
1687 }
1688#endif
sewardjde4a1d02002-03-22 01:27:54 +00001689
nethercotef6a1d502004-08-09 12:21:57 +00001690 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001691
nethercotef6a1d502004-08-09 12:21:57 +00001692 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001693 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001694
thughes3bfd5a02004-07-18 08:05:44 +00001695 /* Look for a colon in the switch name */
1696 while (*colon && *colon != ':' && *colon != '=')
1697 colon++;
nethercote71980f02004-01-24 18:18:54 +00001698
1699 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001700 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001701 if (VG_CLO_STREQN(2, arg, "--") &&
1702 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1703 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1704 {
1705 // prefix matches, convert "--toolname:foo" to "--foo"
1706 if (0)
1707 VG_(printf)("tool-specific arg: %s\n", arg);
1708 arg += toolname_len + 1;
1709 arg[0] = '-';
1710 arg[1] = '-';
1711
1712 } else {
1713 // prefix doesn't match, skip to next arg
1714 continue;
1715 }
1716 }
1717
fitzhardinge98abfc72003-12-16 02:05:15 +00001718 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001719 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001720 continue;
nethercote71980f02004-01-24 18:18:54 +00001721 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001722 continue;
1723
nethercote71980f02004-01-24 18:18:54 +00001724 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001725 continue;
nethercote27fec902004-06-16 21:26:32 +00001726
nethercote71980f02004-01-24 18:18:54 +00001727 else if (VG_CLO_STREQ(arg, "-v") ||
1728 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001729 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001730
nethercote71980f02004-01-24 18:18:54 +00001731 else if (VG_CLO_STREQ(arg, "-q") ||
1732 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001733 VG_(clo_verbosity)--;
1734
nethercote27fec902004-06-16 21:26:32 +00001735 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001736 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1737 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1738 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1739 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1740 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1741 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
nethercote27fec902004-06-16 21:26:32 +00001742 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1743 else VG_BOOL_CLO("--profile", VG_(clo_profile))
sewardj8e4d7dc2004-11-28 18:07:41 +00001744 else VG_BOOL_CLO("--bbprofile", VG_(clo_bbprofile))
nethercote27fec902004-06-16 21:26:32 +00001745 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1746 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001747 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001748 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1749 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1750 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1751 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1752 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1753 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1754 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001755
nethercote27fec902004-06-16 21:26:32 +00001756 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1757 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001758
nethercote27fec902004-06-16 21:26:32 +00001759 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1760 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1761 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001762 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001763 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1764 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001765
sewardj8b635a42004-11-22 19:01:47 +00001766 else VG_BNUM_CLO("--vex-iropt-verbosity",
1767 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1768 else VG_BNUM_CLO("--vex-iropt-level",
1769 VG_(clo_vex_control).iropt_level, 0, 2)
1770 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1771 VG_(clo_vex_control).iropt_precise_memory_exns)
1772 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1773 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1774 else VG_BNUM_CLO("--vex-guest-max-insns",
1775 VG_(clo_vex_control).guest_max_insns, 1, 100)
1776 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1777 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1778
nethercotef8548672004-06-21 12:42:35 +00001779 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001780 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001781 VG_(clo_log_to) = VgLogTo_Fd;
1782 VG_(clo_log_name) = NULL;
1783 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1784 }
1785 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1786 VG_(clo_log_to) = VgLogTo_Fd;
1787 VG_(clo_log_name) = NULL;
1788 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001789 }
1790
nethercotef8548672004-06-21 12:42:35 +00001791 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001792 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001793 VG_(clo_log_to) = VgLogTo_File;
1794 VG_(clo_log_name) = &arg[10];
1795 }
1796 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1797 VG_(clo_log_to) = VgLogTo_File;
1798 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001799 }
sewardjde4a1d02002-03-22 01:27:54 +00001800
nethercotef8548672004-06-21 12:42:35 +00001801 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001802 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001803 VG_(clo_log_to) = VgLogTo_Socket;
1804 VG_(clo_log_name) = &arg[12];
1805 }
1806 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1807 VG_(clo_log_to) = VgLogTo_Socket;
1808 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001809 }
1810
nethercote71980f02004-01-24 18:18:54 +00001811 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001812 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001813 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001814 VG_(message)(Vg_UserMsg,
1815 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001816 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001817 }
nethercote71980f02004-01-24 18:18:54 +00001818 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001819 VG_(clo_n_suppressions)++;
1820 }
sewardjde4a1d02002-03-22 01:27:54 +00001821
njn25e49d8e72002-09-23 09:36:25 +00001822 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001823 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001824 Int j;
nethercote71980f02004-01-24 18:18:54 +00001825 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001826
sewardj2a99cf62004-11-24 10:44:19 +00001827 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001828 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +00001829 "--trace-codegen argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001830 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001831 }
sewardj8b635a42004-11-22 19:01:47 +00001832 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001833 if ('0' == opt[j]) { /* do nothing */ }
sewardj8b635a42004-11-22 19:01:47 +00001834 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001835 else {
1836 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1837 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001838 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001839 }
1840 }
1841 }
sewardjde4a1d02002-03-22 01:27:54 +00001842
nethercote71980f02004-01-24 18:18:54 +00001843 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001844 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001845 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001846 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001847 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001848 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001849
nethercote71980f02004-01-24 18:18:54 +00001850 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001851 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001852 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001853 }
sewardjde4a1d02002-03-22 01:27:54 +00001854 }
1855
nethercote27fec902004-06-16 21:26:32 +00001856 // Check various option values
1857
njnf9ebf672003-05-12 21:41:30 +00001858 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001859 VG_(clo_verbosity) = 0;
1860
nethercote04d0fbc2004-01-26 16:48:06 +00001861 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001862 VG_(message)(Vg_UserMsg, "");
1863 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001864 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001865 VG_(message)(Vg_UserMsg,
1866 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001867 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001868 }
1869
nethercotef8548672004-06-21 12:42:35 +00001870 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001871 should be connected to whatever sink has been selected, and we
1872 indiscriminately chuck stuff into it without worrying what the
1873 nature of it is. Oh the wonder of Unix streams. */
1874
nethercotee1730692003-11-20 10:38:07 +00001875 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001876 the terminal any problems to do with processing command line
1877 opts. */
nethercotef8548672004-06-21 12:42:35 +00001878 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001879 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001880
1881 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001882
sewardj4cf05692002-10-27 20:28:29 +00001883 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001884 vg_assert(VG_(clo_log_name) == NULL);
1885 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001886 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001887
sewardj4cf05692002-10-27 20:28:29 +00001888 case VgLogTo_File: {
1889 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001890 Int seq = 0;
1891 Int pid = VG_(getpid)();
1892
nethercotef8548672004-06-21 12:42:35 +00001893 vg_assert(VG_(clo_log_name) != NULL);
1894 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001895
nethercote71980f02004-01-24 18:18:54 +00001896 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001897 if (seq == 0)
1898 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001899 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001900 else
1901 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001902 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001903 seq++;
1904
nethercotef8548672004-06-21 12:42:35 +00001905 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001906 = VG_(open)(logfilename,
1907 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1908 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001909 if (eventually_log_fd >= 0) {
1910 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001911 break;
1912 } else {
nethercotef8548672004-06-21 12:42:35 +00001913 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001914 VG_(message)(Vg_UserMsg,
1915 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001916 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001917 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001918 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001919 break;
1920 }
1921 }
1922 }
sewardj4cf05692002-10-27 20:28:29 +00001923 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001924 }
1925
1926 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001927 vg_assert(VG_(clo_log_name) != NULL);
1928 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1929 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1930 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001931 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001932 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001933 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001934 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001935 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001936 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001937 }
nethercotef8548672004-06-21 12:42:35 +00001938 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001939 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001940 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001941 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001942 VG_(message)(Vg_UserMsg,
1943 "Log messages will sent to stderr instead." );
1944 VG_(message)(Vg_UserMsg,
1945 "" );
1946 /* We don't change anything here. */
1947 } else {
nethercotef8548672004-06-21 12:42:35 +00001948 vg_assert(eventually_log_fd > 0);
1949 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001950 VG_(logging_to_filedes) = False;
1951 }
sewardj73cf3bc2002-11-03 03:20:15 +00001952 break;
1953 }
1954
sewardj4cf05692002-10-27 20:28:29 +00001955 }
1956
nethercotef8548672004-06-21 12:42:35 +00001957 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001958 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001959 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001960 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1961 else {
nethercotef8548672004-06-21 12:42:35 +00001962 VG_(clo_log_fd) = eventually_log_fd;
1963 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001964 }
1965
sewardj4cf05692002-10-27 20:28:29 +00001966 /* Ok, the logging sink is running now. Print a suitable preamble.
1967 If logging to file or a socket, write details of parent PID and
1968 command line args, to help people trying to interpret the
1969 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001970
sewardj83adf412002-05-01 01:25:45 +00001971 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001972 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001973 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001974 VG_(details).name,
1975 NULL == VG_(details).version ? "" : "-",
1976 NULL == VG_(details).version
1977 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001978 VG_(details).description,
1979 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001980 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001981
njnd04b7c62002-10-03 14:05:52 +00001982 /* Core details */
1983 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001984 "Using valgrind-%s, a program supervision framework for %s.",
1985 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001986 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001987 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001988 }
1989
nethercotec1e395d2003-11-10 13:26:49 +00001990 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001991 VG_(message)(Vg_UserMsg, "");
1992 VG_(message)(Vg_UserMsg,
1993 "My PID = %d, parent PID = %d. Prog and args are:",
1994 VG_(getpid)(), VG_(getppid)() );
1995 for (i = 0; i < VG_(client_argc); i++)
1996 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
1997 }
1998
sewardjde4a1d02002-03-22 01:27:54 +00001999 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002000 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002001 if (VG_(clo_log_to) != VgLogTo_Fd)
2002 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002003 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002004 VG_(message)(Vg_UserMsg, "Command line");
2005 for (i = 0; i < VG_(client_argc); i++)
2006 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2007
sewardjde4a1d02002-03-22 01:27:54 +00002008 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002009 for (i = 1; i < vg_argc; i++) {
2010 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002011 }
nethercotea70f7352004-04-18 12:08:46 +00002012
2013 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2014 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2015 if (fd < 0) {
2016 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2017 } else {
2018 #define BUF_LEN 256
2019 Char version_buf[BUF_LEN];
2020 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2021 vg_assert(n <= 256);
2022 if (n > 0) {
2023 version_buf[n-1] = '\0';
2024 VG_(message)(Vg_UserMsg, " %s", version_buf);
2025 } else {
2026 VG_(message)(Vg_UserMsg, " (empty?)");
2027 }
2028 VG_(close)(fd);
2029 #undef BUF_LEN
2030 }
sewardjde4a1d02002-03-22 01:27:54 +00002031 }
2032
fitzhardinge98abfc72003-12-16 02:05:15 +00002033 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002034 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002035 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002036 needs one, load the default */
2037 static const Char default_supp[] = "default.supp";
2038 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2039 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2040 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2041 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2042 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002043 }
sewardj4cf05692002-10-27 20:28:29 +00002044
njn6a230532003-07-21 10:38:23 +00002045 if (VG_(clo_gen_suppressions) &&
njn95ec8702004-11-22 16:46:13 +00002046 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002047 VG_(message)(Vg_UserMsg,
2048 "Can't use --gen-suppressions=yes with this tool,");
2049 VG_(message)(Vg_UserMsg,
2050 "as it doesn't generate errors.");
2051 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002052 }
sewardjde4a1d02002-03-22 01:27:54 +00002053}
2054
nethercotef6a1d502004-08-09 12:21:57 +00002055// Build the string for VALGRINDCLO.
2056Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2057{
2058 /* If we're tracing the children, then we need to start it
2059 with our starter+arguments, which are copied into VALGRINDCLO,
2060 except the --exec= option is changed if present.
2061 */
2062 Int i;
2063 Char *exec;
2064 Char *cp;
2065 Char *optvar;
2066 Int optlen, execlen;
2067
2068 // All these allocated blocks are not free - because we're either
2069 // going to exec, or panic when we fail.
2070
2071 // Create --exec= option: "--exec=<exename>"
2072 exec = VG_(arena_malloc)(VG_AR_CORE,
2073 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2074 vg_assert(NULL != exec);
2075 VG_(sprintf)(exec, "--exec=%s", exename);
2076
2077 // Allocate space for optvar (may overestimate by counting --exec twice,
2078 // no matter)
2079 optlen = 1;
2080 for (i = 0; i < vg_argc; i++)
2081 optlen += VG_(strlen)(vg_argv[i]) + 1;
2082 optlen += VG_(strlen)(exec)+1;
2083 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2084
2085 // Copy all valgrind args except the old --exec (if present)
2086 // VG_CLO_SEP is the separator.
2087 cp = optvar;
2088 for (i = 1; i < vg_argc; i++) {
2089 Char *arg = vg_argv[i];
2090
2091 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2092 // don't copy existing --exec= arg
2093 } else if (VG_(strcmp)(arg, "--") == 0) {
2094 // stop at "--"
2095 break;
2096 } else {
2097 // copy non "--exec" arg
2098 Int len = VG_(strlen)(arg);
2099 VG_(memcpy)(cp, arg, len);
2100 cp += len;
2101 *cp++ = VG_CLO_SEP;
2102 }
2103 }
2104 // Add the new --exec= option
2105 execlen = VG_(strlen)(exec);
2106 VG_(memcpy)(cp, exec, execlen);
2107 cp += execlen;
2108 *cp++ = VG_CLO_SEP;
2109
2110 *cp = '\0';
2111
2112 return optvar;
2113}
2114
2115// Build "/proc/self/fd/<execfd>".
2116Char* VG_(build_child_exename)( void )
2117{
2118 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2119 vg_assert(NULL != exename);
2120 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2121 return exename;
2122}
2123
sewardjde4a1d02002-03-22 01:27:54 +00002124
nethercote71980f02004-01-24 18:18:54 +00002125/*====================================================================*/
2126/*=== File descriptor setup ===*/
2127/*====================================================================*/
2128
2129static void setup_file_descriptors(void)
2130{
2131 struct vki_rlimit rl;
2132
2133 /* Get the current file descriptor limits. */
2134 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2135 rl.rlim_cur = 1024;
2136 rl.rlim_max = 1024;
2137 }
2138
2139 /* Work out where to move the soft limit to. */
2140 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2141 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2142 } else {
2143 rl.rlim_cur = rl.rlim_max;
2144 }
2145
2146 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002147 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2148 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002149
2150 /* Update the soft limit. */
2151 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2152
nethercotef6a1d502004-08-09 12:21:57 +00002153 if (vgexecfd != -1)
2154 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002155 if (VG_(clexecfd) != -1)
2156 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2157}
2158
nethercote71980f02004-01-24 18:18:54 +00002159/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002160/*=== Initialise program data/text, etc. ===*/
2161/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002162
nethercote71980f02004-01-24 18:18:54 +00002163static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002164 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002165 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002166{
nethercote71980f02004-01-24 18:18:54 +00002167 UInt prot = 0;
2168 UInt flags = SF_MMAP|SF_NOSYMS;
2169 Bool is_stack_segment;
2170
2171 is_stack_segment =
2172 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2173
2174 /* Only record valgrind mappings for now, without loading any
2175 symbols. This is so we know where the free space is before we
2176 start allocating more memory (note: heap is OK, it's just mmap
2177 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002178 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002179 flags |= SF_VALGRIND;
2180 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2181 }
sewardjde4a1d02002-03-22 01:27:54 +00002182}
2183
nethercote71980f02004-01-24 18:18:54 +00002184// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002185Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002186
nethercote71980f02004-01-24 18:18:54 +00002187static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002188 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002189 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002190{
nethercote71980f02004-01-24 18:18:54 +00002191 UInt prot = 0;
2192 UInt flags;
2193 Bool is_stack_segment;
2194 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002195
nethercote71980f02004-01-24 18:18:54 +00002196 is_stack_segment
2197 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002198
nethercote71980f02004-01-24 18:18:54 +00002199 if (rr == 'r') prot |= VKI_PROT_READ;
2200 if (ww == 'w') prot |= VKI_PROT_WRITE;
2201 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002202
nethercote71980f02004-01-24 18:18:54 +00002203 if (is_stack_segment)
2204 flags = SF_STACK | SF_GROWDOWN;
2205 else
2206 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002207
nethercote71980f02004-01-24 18:18:54 +00002208 if (filename != NULL)
2209 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002210
nethercote820bd8c2004-09-07 23:04:49 +00002211 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002212 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002213
nethercote71980f02004-01-24 18:18:54 +00002214 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
nethercote71980f02004-01-24 18:18:54 +00002216 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2217 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002218
nethercote71980f02004-01-24 18:18:54 +00002219 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002220 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002221 vg_assert(0 != r_esp);
2222 if (is_stack_segment) {
2223 if (0)
2224 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2225 start,r_esp);
2226 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002227 }
sewardjde4a1d02002-03-22 01:27:54 +00002228}
2229
2230
nethercote71980f02004-01-24 18:18:54 +00002231/*====================================================================*/
2232/*=== Sanity check machinery (permanently engaged) ===*/
2233/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002234
2235/* A fast sanity check -- suitable for calling circa once per
2236 millisecond. */
2237
nethercote885dd912004-08-03 23:14:00 +00002238void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002239{
njn37cea302002-09-30 11:24:00 +00002240 VGP_PUSHCC(VgpCoreCheapSanity);
2241
nethercote27fec902004-06-16 21:26:32 +00002242 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002243
2244 /* --- First do all the tests that we can do quickly. ---*/
2245
nethercote297effd2004-08-02 15:07:57 +00002246 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002247
njn25e49d8e72002-09-23 09:36:25 +00002248 /* Check stuff pertaining to the memory check system. */
2249
2250 /* Check that nobody has spuriously claimed that the first or
2251 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002252 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002253 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002254 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002255 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002256 }
njn25e49d8e72002-09-23 09:36:25 +00002257
2258 /* --- Now some more expensive checks. ---*/
2259
2260 /* Once every 25 times, check some more expensive stuff. */
2261 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002262 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002263 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002264
njn37cea302002-09-30 11:24:00 +00002265 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002266 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002267
nethercote885dd912004-08-03 23:14:00 +00002268 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002269
njn25e49d8e72002-09-23 09:36:25 +00002270# if 0
2271 { void zzzmemscan(void); zzzmemscan(); }
2272# endif
2273
nethercote297effd2004-08-02 15:07:57 +00002274 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002275 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002276
2277 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002278 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002279 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002280 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002281 }
2282 /*
nethercote297effd2004-08-02 15:07:57 +00002283 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002284 */
njn37cea302002-09-30 11:24:00 +00002285 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002286 }
2287
nethercote27fec902004-06-16 21:26:32 +00002288 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002289 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002290 /* Check sanity of the low-level memory manager. Note that bugs
2291 in the client's code can cause this to fail, so we don't do
2292 this check unless specially asked for. And because it's
2293 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002294 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002295 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002296 }
njn37cea302002-09-30 11:24:00 +00002297 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002298}
nethercote71980f02004-01-24 18:18:54 +00002299
2300
2301/*====================================================================*/
2302/*=== main() ===*/
2303/*====================================================================*/
2304
nethercotec314eba2004-07-15 12:59:41 +00002305/*
2306 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002307 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002308 loads the client executable (and the dynamic linker, if necessary)
2309 into the client part, and calls into Valgrind proper.
2310
2311 The code is careful not to allow spurious mappings to appear in the
2312 wrong parts of the address space. In particular, to make sure
2313 dlopen puts things in the right place, it will pad out the forbidden
2314 chunks of address space so that dlopen is forced to put things where
2315 we want them.
2316
2317 The memory map it creates is:
2318
2319 CLIENT_BASE +-------------------------+
2320 | client address space |
2321 : :
2322 : :
2323 | client stack |
2324 client_end +-------------------------+
2325 | redzone |
2326 shadow_base +-------------------------+
2327 | |
nethercote996901a2004-08-03 13:29:09 +00002328 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002329 | (may be 0 sized) |
2330 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002331 valgrind_base +-------------------------+
2332 | kickstart executable |
2333 | valgrind heap vvvvvvvvv| (barely used)
2334 - -
2335 | valgrind .so files |
2336 | and mappings |
2337 - -
2338 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002339 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002340 : kernel :
2341
2342 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2343 VG_(mmap)(), we need to build the segment skip-list, so we know where
2344 we can put things. However, building that structure requires
2345 allocating memory. So we need to a bootstrapping process. It's done
2346 by making VG_(arena_malloc)() have a special static superblock that's
2347 used for the first 1MB's worth of allocations. This is enough to
2348 build the segment skip-list.
2349*/
2350
nethercote31779c72004-07-30 21:50:15 +00002351static int prmap(char *start, char *end, const char *perm, off_t off,
2352 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002353 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2354 start, end, perm, maj, min, ino);
2355 return True;
2356}
2357
nethercote71980f02004-01-24 18:18:54 +00002358int main(int argc, char **argv)
2359{
2360 char **cl_argv;
2361 const char *tool = NULL;
2362 const char *exec = NULL;
2363 char *preload; /* tool-specific LD_PRELOAD .so */
2364 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002365 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002366 struct exeinfo info;
2367 ToolInfo *toolinfo = NULL;
2368 void *tool_dlhandle;
2369 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002370 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002371 UInt * client_auxv;
2372 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002373 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002374 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002375 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002376 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002377 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2378
nethercote71980f02004-01-24 18:18:54 +00002379
2380 //============================================================
2381 // Nb: startup is complex. Prerequisites are shown at every step.
2382 //
2383 // *** Be very careful when messing with the order ***
2384 //============================================================
2385
nethercotef4928da2004-06-15 10:54:40 +00002386 //============================================================
2387 // Command line argument handling order:
2388 // * If --help/--help-debug are present, show usage message
2389 // (if --tool is also present, that includes the tool-specific usage)
2390 // * Then, if --tool is missing, abort with error msg
2391 // * Then, if client is missing, abort with error msg
2392 // * Then, if any cmdline args are bad, abort with error msg
2393 //============================================================
2394
fitzhardingeb50068f2004-02-24 23:42:55 +00002395 // Get the current process datasize rlimit, and set it to zero.
2396 // This prevents any internal uses of brk() from having any effect.
2397 // We remember the old value so we can restore it on exec, so that
2398 // child processes will have a reasonable brk value.
2399 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2400 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2401 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002402
2403 // Get the current process stack rlimit.
2404 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2405
nethercote71980f02004-01-24 18:18:54 +00002406 //--------------------------------------------------------------
2407 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002408 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002409 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002410 {
2411 void* init_sp = argv - 1;
2412 padfile = scan_auxv(init_sp);
2413 }
nethercote71980f02004-01-24 18:18:54 +00002414
2415 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002416 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002417 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002418 }
2419
2420 //--------------------------------------------------------------
2421 // Look for alternative libdir
2422 // p: n/a
2423 //--------------------------------------------------------------
2424 { char *cp = getenv(VALGRINDLIB);
2425 if (cp != NULL)
2426 VG_(libdir) = cp;
2427 }
2428
2429 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002430 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2431 // Pre-process the command line.
2432 // p: n/a
2433 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002434 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002435 pre_process_cmd_line_options(&need_help, &tool, &exec);
2436
2437 //==============================================================
2438 // Nb: once a tool is specified, the tool.so must be loaded even if
2439 // they specified --help or didn't specify a client program.
2440 //==============================================================
2441
2442 //--------------------------------------------------------------
2443 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002444 // p: set-libdir [for VG_(libdir)]
2445 // p: pre_process_cmd_line_options() [for 'tool']
2446 //--------------------------------------------------------------
2447 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2448
2449 //==============================================================
2450 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002451 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002452 //==============================================================
2453
2454 //--------------------------------------------------------------
2455 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002456 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002457 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002458 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002459
2460 //--------------------------------------------------------------
2461 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002462 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2463 // p: layout_remaining_space [so there's space]
2464 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002465 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002466
2467 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002468 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002469 // p: layout_remaining_space() [everything must be mapped in before now]
2470 // p: load_client() [ditto]
2471 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002472 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2473 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002474
2475 //--------------------------------------------------------------
2476 // Set up client's environment
2477 // p: set-libdir [for VG_(libdir)]
2478 // p: load_tool() [for 'preload']
2479 //--------------------------------------------------------------
2480 env = fix_environment(environ, preload);
2481
2482 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002483 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002484 // p: load_client() [for 'info']
2485 // p: fix_environment() [for 'env']
2486 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002487 {
2488 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002489 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2490 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002491 }
nethercote71980f02004-01-24 18:18:54 +00002492
2493 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002494 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002495 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002496 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002497
2498 //==============================================================
2499 // Finished setting up operating environment. Now initialise
2500 // Valgrind. (This is where the old VG_(main)() started.)
2501 //==============================================================
2502
2503 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002504 // atfork
2505 // p: n/a
2506 //--------------------------------------------------------------
2507 VG_(atfork)(NULL, NULL, newpid);
2508 newpid(VG_INVALID_THREADID);
2509
2510 //--------------------------------------------------------------
2511 // setup file descriptors
2512 // p: n/a
2513 //--------------------------------------------------------------
2514 setup_file_descriptors();
2515
2516 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002517 // Read /proc/self/maps into a buffer
2518 // p: all memory layout, environment setup [so memory maps are right]
2519 //--------------------------------------------------------------
2520 VG_(read_procselfmaps)();
2521
2522 //--------------------------------------------------------------
2523 // Build segment map (Valgrind segments only)
2524 // p: read proc/self/maps
njnd2252832004-11-26 10:53:33 +00002525 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002526 //--------------------------------------------------------------
2527 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2528
2529 //==============================================================
2530 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2531 //==============================================================
2532
2533 //--------------------------------------------------------------
2534 // Init tool: pre_clo_init, process cmd line, post_clo_init
2535 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2536 // p: load_tool() [for 'tool']
2537 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2538 // p: parse_procselfmaps [so VG segments are setup so tool can
2539 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002540 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002541 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002542 VG_(tool_init_dlsym)(tool_dlhandle);
2543 VG_(sanity_check_needs)();
2544
nethercotef4928da2004-06-15 10:54:40 +00002545 // If --tool and --help/--help-debug was given, now give the core+tool
2546 // help message
nethercotef4928da2004-06-15 10:54:40 +00002547 if (need_help) {
2548 usage(/*--help-debug?*/2 == need_help);
2549 }
nethercotec314eba2004-07-15 12:59:41 +00002550 process_cmd_line_options(client_auxv, tool);
2551
njn26f02512004-11-22 18:33:15 +00002552 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002553
2554 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002555 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002556 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002557 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002558 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002559 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002560 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002561 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002562
njnca0518d2004-11-26 19:34:36 +00002563#ifdef __i386__
nethercotec314eba2004-07-15 12:59:41 +00002564 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002565 // Protect client trampoline page (which is also sysinfo stuff)
2566 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002567 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002568 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2569 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002570#endif
nethercotec314eba2004-07-15 12:59:41 +00002571
2572 //==============================================================
2573 // Can use VG_(map)() after segments set up
2574 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002575
2576 //--------------------------------------------------------------
2577 // Allow GDB attach
2578 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2579 //--------------------------------------------------------------
2580 /* Hook to delay things long enough so we can get the pid and
2581 attach GDB in another shell. */
2582 if (VG_(clo_wait_for_gdb)) {
2583 VG_(printf)("pid=%d\n", VG_(getpid)());
2584 /* do "jump *$eip" to skip this in gdb */
2585 VG_(do_syscall)(__NR_pause);
2586 }
2587
2588 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002589 // Search for file descriptors that are inherited from our parent
2590 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2591 //--------------------------------------------------------------
2592 if (VG_(clo_track_fds))
2593 VG_(init_preopened_fds)();
2594
2595 //--------------------------------------------------------------
2596 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002597 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2598 //--------------------------------------------------------------
2599 VG_(scheduler_init)();
2600
2601 //--------------------------------------------------------------
sewardj2a99cf62004-11-24 10:44:19 +00002602 // Set up state of thread 1
2603 // p: {pre,post}_clo_init() [for tool helper registration]
2604 // load_client() [for 'client_eip']
2605 // setup_client_stack() [for 'sp_at_startup']
2606 // setup_scheduler() [for the rest of state 1 stuff]
2607 //--------------------------------------------------------------
2608 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njn16de5572004-11-27 14:27:21 +00002609 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002610
2611 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002612 // Set up the ProxyLWP machinery
2613 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002614 //--------------------------------------------------------------
2615 VG_(proxy_init)();
2616
2617 //--------------------------------------------------------------
2618 // Initialise the signal handling subsystem
2619 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2620 // p: VG_(proxy_init)() [else breaks...]
2621 //--------------------------------------------------------------
2622 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2623 VG_(sigstartup_actions)();
2624
2625 //--------------------------------------------------------------
2626 // Perhaps we're profiling Valgrind?
2627 // p: process_cmd_line_options() [for VG_(clo_profile)]
2628 // p: others?
2629 //
2630 // XXX: this seems to be broken? It always says the tool wasn't built
2631 // for profiling; vg_profile.c's functions don't seem to be overriding
2632 // vg_dummy_profile.c's?
2633 //
2634 // XXX: want this as early as possible. Looking for --profile
2635 // in pre_process_cmd_line_options() could get it earlier.
2636 //--------------------------------------------------------------
2637 if (VG_(clo_profile))
2638 VGP_(init_profiling)();
2639
2640 VGP_PUSHCC(VgpStartup);
2641
2642 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002643 // Read suppression file
2644 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2645 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002646 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002647 VG_(load_suppressions)();
2648
2649 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002650 // Initialise translation table and translation cache
2651 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2652 // aren't identified as part of the client, which would waste
2653 // > 20M of virtual address space.]
2654 //--------------------------------------------------------------
2655 VG_(init_tt_tc)();
2656
2657 //--------------------------------------------------------------
2658 // Read debug info to find glibc entry points to intercept
2659 // p: parse_procselfmaps? [XXX for debug info?]
2660 // p: init_tt_tc? [XXX ???]
2661 //--------------------------------------------------------------
2662 VG_(setup_code_redirect_table)();
2663
2664 //--------------------------------------------------------------
2665 // Verbosity message
2666 // p: end_rdtsc_calibration [so startup message is printed first]
2667 //--------------------------------------------------------------
2668 if (VG_(clo_verbosity) == 1)
2669 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2670 if (VG_(clo_verbosity) > 0)
2671 VG_(message)(Vg_UserMsg, "");
2672
2673 //--------------------------------------------------------------
2674 // Setup pointercheck
2675 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2676 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002677 if (VG_(clo_pointercheck))
2678 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002679
nethercote71980f02004-01-24 18:18:54 +00002680 //--------------------------------------------------------------
2681 // Run!
2682 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002683 VGP_POPCC(VgpStartup);
2684 VGP_PUSHCC(VgpSched);
2685
nethercote238a3c32004-08-09 13:13:31 +00002686 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002687
nethercote238a3c32004-08-09 13:13:31 +00002688 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002689
2690
2691 //--------------------------------------------------------------
2692 // Finalisation: cleanup, messages, etc. Order no so important, only
2693 // affects what order the messages come.
2694 //--------------------------------------------------------------
2695 if (VG_(clo_verbosity) > 0)
2696 VG_(message)(Vg_UserMsg, "");
2697
2698 if (src == VgSrc_Deadlock) {
2699 VG_(message)(Vg_UserMsg,
2700 "Warning: pthread scheduler exited due to deadlock");
2701 }
2702
2703 /* Print out file descriptor summary and stats. */
2704 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002705 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002706
njn95ec8702004-11-22 16:46:13 +00002707 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002708 VG_(show_all_errors)();
2709
njn26f02512004-11-22 18:33:15 +00002710 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002711
nethercote885dd912004-08-03 23:14:00 +00002712 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002713
2714 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002715 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002716
nethercote71980f02004-01-24 18:18:54 +00002717 if (VG_(clo_profile))
2718 VGP_(done_profiling)();
2719
nethercote71980f02004-01-24 18:18:54 +00002720 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2721 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002722 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2723 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002724 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2725
sewardj8b635a42004-11-22 19:01:47 +00002726 /* Print Vex storage stats */
njn383ae5e2004-11-23 17:10:15 +00002727 LibVEX_ClearTemporary( False/*show stats*/ );
sewardj8b635a42004-11-22 19:01:47 +00002728
nethercote71980f02004-01-24 18:18:54 +00002729 //--------------------------------------------------------------
2730 // Exit, according to the scheduler's return code
2731 //--------------------------------------------------------------
2732 switch (src) {
2733 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002734 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002735 VG_(proxy_shutdown)();
2736
2737 /* The thread's %EBX at the time it did __NR_exit() will hold
2738 the arg to __NR_exit(), so we just do __NR_exit() with
2739 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002740 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002741 /* NOT ALIVE HERE! */
2742 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2743 break; /* what the hell :) */
2744
2745 case VgSrc_Deadlock:
2746 /* Just exit now. No point in continuing. */
2747 VG_(proxy_shutdown)();
2748 VG_(exit)(0);
2749 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2750 break;
2751
nethercote71980f02004-01-24 18:18:54 +00002752 case VgSrc_FatalSig:
2753 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002754 vg_assert(fatal_sigNo != -1);
2755 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002756 VG_(core_panic)("main(): signal was supposed to be fatal");
2757 break;
2758
2759 default:
2760 VG_(core_panic)("main(): unexpected scheduler return code");
2761 }
2762
2763 abort();
2764}
2765
2766
sewardjde4a1d02002-03-22 01:27:54 +00002767/*--------------------------------------------------------------------*/
2768/*--- end vg_main.c ---*/
2769/*--------------------------------------------------------------------*/