blob: ad8247cb3d87d45a2debf0d68947c8a6dcd341a2 [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
njnea4b28c2004-11-30 16:04:58 +0000322/* Debugging thing .. can be called from assembly with OYNK macro. */
323void VG_(oynk) ( Int n )
324{
325 OINK(n);
326}
327
nethercote71980f02004-01-24 18:18:54 +0000328/* Initialize the PID and PGRP of scheduler LWP; this is also called
329 in any new children after fork. */
330static void newpid(ThreadId unused)
331{
332 /* PID of scheduler LWP */
333 VG_(main_pid) = VG_(getpid)();
334 VG_(main_pgrp) = VG_(getpgrp)();
335}
336
337/*====================================================================*/
338/*=== Check we were launched by stage 1 ===*/
339/*====================================================================*/
340
341/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000342int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000343{
nethercoteebf1d862004-11-01 18:22:05 +0000344 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000345 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000346
347 for (; auxv->a_type != AT_NULL; auxv++)
348 switch(auxv->a_type) {
349 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000350 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000351 found |= 1;
352 break;
353
354 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000355 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000356 found |= 2;
357 break;
nethercote7f390022004-10-25 17:18:24 +0000358
359 case AT_PHDR:
360 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
361 break;
nethercote71980f02004-01-24 18:18:54 +0000362 }
363
nethercote361a14e2004-07-26 11:11:56 +0000364 if ( found != (1|2) ) {
365 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000366 exit(127);
367 }
nethercote31779c72004-07-30 21:50:15 +0000368 vg_assert(padfile >= 0);
369 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000370}
371
372
373/*====================================================================*/
374/*=== Address space determination ===*/
375/*====================================================================*/
376
nethercote7f390022004-10-25 17:18:24 +0000377extern char _start[];
378
nethercote31779c72004-07-30 21:50:15 +0000379static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000380{
nethercotea3c3cf22004-11-01 18:38:00 +0000381 Int ires;
382 void* vres;
383 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000384
nethercote7f390022004-10-25 17:18:24 +0000385 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
386 // this is a workable approximation
387 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000388 VG_(valgrind_base) = PGROUNDDN(&_start);
389 }
390
nethercote820bd8c2004-09-07 23:04:49 +0000391 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000392
nethercote31779c72004-07-30 21:50:15 +0000393 // This gives the client the largest possible address space while
394 // taking into account the tool's shadow needs.
395 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000396 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000397 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000398 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000399 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000400 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000401 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000402
nethercote31779c72004-07-30 21:50:15 +0000403 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000404 VG_(shadow_end) = VG_(valgrind_base);
405 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000406
nethercotee2097312004-06-27 12:29:56 +0000407#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
408
nethercote71980f02004-01-24 18:18:54 +0000409 if (0)
nethercotee2097312004-06-27 12:29:56 +0000410 VG_(printf)(
411 "client_base %8x (%dMB)\n"
412 "client_mapbase %8x (%dMB)\n"
413 "client_end %8x (%dMB)\n"
414 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000415 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000416 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000417 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000418 VG_(client_base), SEGSIZE(client_base, client_mapbase),
419 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
420 VG_(client_end), SEGSIZE(client_end, shadow_base),
421 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000422 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000423 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
424 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000425 );
426
427#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000428
429 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000430 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000431 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000432 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000433
434 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000435 ires = munmap((void*)VG_(client_base), client_size);
436 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000437
438 // Map shadow memory.
439 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000440 if (shadow_size != 0) {
441 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000442 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000443 if ((void*)-1 == vres) {
444 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000445 "valgrind: Could not allocate address space (%p bytes)\n"
446 "valgrind: for shadow memory\n"
447 "valgrind: Possible causes:\n"
448 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
449 "valgrind: needs at least 1.5GB swap space.\n"
450 "valgrind: - Or, your virtual memory size may be limited (check\n"
451 "valgrind: with 'ulimit -v').\n"
452 "valgrind: - Or, your system may use a kernel that provides only a\n"
453 "valgrind: too-small (eg. 2GB) user address space.\n"
454 , (void*)shadow_size
455 );
nethercoted4722622004-08-30 19:36:42 +0000456 exit(1);
457 }
nethercotee567e702004-07-10 17:49:17 +0000458 }
nethercote71980f02004-01-24 18:18:54 +0000459}
460
461/*====================================================================*/
462/*=== Command line setup ===*/
463/*====================================================================*/
464
465/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
466static char* get_file_clo(char* dir)
467{
468# define FLEN 512
469 Int fd, n;
470 struct stat s1;
471 char* f_clo = NULL;
472 char filename[FLEN];
473
474 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
475 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
476 if ( fd > 0 ) {
477 if ( 0 == fstat(fd, &s1) ) {
478 f_clo = malloc(s1.st_size+1);
479 vg_assert(f_clo);
480 n = read(fd, f_clo, s1.st_size);
481 if (n == -1) n = 0;
482 f_clo[n] = '\0';
483 }
484 close(fd);
485 }
486 return f_clo;
487# undef FLEN
488}
489
nethercotee2097312004-06-27 12:29:56 +0000490#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
491
nethercote71980f02004-01-24 18:18:54 +0000492static Int count_args(char* s)
493{
494 Int n = 0;
495 if (s) {
496 char* cp = s;
497 while (True) {
498 // We have alternating sequences: blanks, non-blanks, blanks...
499 // count the non-blanks sequences.
500 while ( ISSPACE(*cp) ) cp++;
501 if ( !*cp ) break;
502 n++;
503 while ( !ISSPACE(*cp) && *cp ) cp++;
504 }
505 }
506 return n;
507}
508
509/* add args out of environment, skipping multiple spaces and -- args */
510static char** copy_args( char* s, char** to )
511{
512 if (s) {
513 char* cp = s;
514 while (True) {
515 // We have alternating sequences: blanks, non-blanks, blanks...
516 // copy the non-blanks sequences, and add terminating '\0'
517 while ( ISSPACE(*cp) ) cp++;
518 if ( !*cp ) break;
519 *to++ = cp;
520 while ( !ISSPACE(*cp) && *cp ) cp++;
521 if ( *cp ) *cp++ = '\0'; // terminate if necessary
522 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
523 }
524 }
525 return to;
526}
527
nethercotee2097312004-06-27 12:29:56 +0000528#undef ISSPACE
529
nethercote71980f02004-01-24 18:18:54 +0000530// Augment command line with arguments from environment and .valgrindrc
531// files.
532static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
533{
nethercotef6a1d502004-08-09 12:21:57 +0000534 int vg_argc0 = *vg_argc_inout;
535 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000536
537 char* env_clo = getenv(VALGRINDOPTS);
538 char* f1_clo = get_file_clo( getenv("HOME") );
539 char* f2_clo = get_file_clo(".");
540
541 /* copy any extra args from file or environment, if present */
542 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
543 /* ' ' separated extra options */
544 char **from;
545 char **to;
thughescaca0022004-09-13 10:20:34 +0000546 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
547
548 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
549
nethercote71980f02004-01-24 18:18:54 +0000550 env_arg_count = count_args(env_clo);
551 f1_arg_count = count_args(f1_clo);
552 f2_arg_count = count_args(f2_clo);
553
554 if (0)
555 printf("extra-argc=%d %d %d\n",
556 env_arg_count, f1_arg_count, f2_arg_count);
557
558 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000559 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000560 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000561 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000562 vg_assert(vg_argv0);
563 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000564
565 /* copy argv[0] */
566 *to++ = *from++;
567
568 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
569 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
570 * to override less local ones. */
571 to = copy_args(f1_clo, to);
572 to = copy_args(env_clo, to);
573 to = copy_args(f2_clo, to);
574
575 /* copy original arguments, stopping at command or -- */
576 while (*from) {
577 if (**from != '-')
578 break;
579 if (VG_STREQ(*from, "--")) {
580 from++; /* skip -- */
581 break;
582 }
583 *to++ = *from++;
584 }
585
586 /* add -- */
587 *to++ = "--";
588
nethercotef6a1d502004-08-09 12:21:57 +0000589 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000590
591 /* copy rest of original command line, then NULL */
592 while (*from) *to++ = *from++;
593 *to = NULL;
594 }
595
nethercotef6a1d502004-08-09 12:21:57 +0000596 *vg_argc_inout = vg_argc0;
597 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000598}
599
nethercotef6a1d502004-08-09 12:21:57 +0000600#define VG_CLO_SEP '\01'
601
nethercote71980f02004-01-24 18:18:54 +0000602static void get_command_line( int argc, char** argv,
603 Int* vg_argc_out, Char*** vg_argv_out,
604 char*** cl_argv_out )
605{
nethercotef6a1d502004-08-09 12:21:57 +0000606 int vg_argc0;
607 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000608 char** cl_argv;
609 char* env_clo = getenv(VALGRINDCLO);
610
611 if (env_clo != NULL && *env_clo != '\0') {
612 char *cp;
613 char **cpp;
614
nethercotef6a1d502004-08-09 12:21:57 +0000615 /* OK, VALGRINDCLO is set, which means we must be a child of another
616 Valgrind process using --trace-children, so we're getting all our
617 arguments from VALGRINDCLO, and the entire command line belongs to
618 the client (including argv[0]) */
619 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000620 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000621 if (*cp == VG_CLO_SEP)
622 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000623
nethercotef6a1d502004-08-09 12:21:57 +0000624 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
625 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000626
nethercotef6a1d502004-08-09 12:21:57 +0000627 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000628
629 *cpp++ = "valgrind"; /* nominal argv[0] */
630 *cpp++ = env_clo;
631
nethercotef6a1d502004-08-09 12:21:57 +0000632 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000633 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000634 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000635 *cp++ = '\0'; /* chop it up in place */
636 *cpp++ = cp;
637 }
638 }
639 *cpp = NULL;
640 cl_argv = argv;
641
642 } else {
643 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000644 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000645
nethercotef6a1d502004-08-09 12:21:57 +0000646 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
647 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000648 break;
nethercotef6a1d502004-08-09 12:21:57 +0000649 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
650 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000651 break;
652 }
653 }
nethercotef6a1d502004-08-09 12:21:57 +0000654 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000655
656 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000657 Note we don't do this if getting args from VALGRINDCLO, as
658 those extra args will already be present in VALGRINDCLO. */
659 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000660 }
661
662 if (0) {
663 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000664 for (i = 0; i < vg_argc0; i++)
665 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000666 }
667
nethercotef6a1d502004-08-09 12:21:57 +0000668 *vg_argc_out = vg_argc0;
669 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000670 *cl_argv_out = cl_argv;
671}
672
673
674/*====================================================================*/
675/*=== Environment and stack setup ===*/
676/*====================================================================*/
677
678/* Scan a colon-separated list, and call a function on each element.
679 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000680 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000681 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000682
683 This routine will return True if (*func) returns True and False if
684 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000685*/
thughes4ad52d02004-06-27 17:37:21 +0000686static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000687{
688 char *cp, *entry;
689 int end;
690
691 if (colsep == NULL ||
692 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000693 return False;
nethercote71980f02004-01-24 18:18:54 +0000694
695 entry = cp = colsep;
696
697 do {
698 end = (*cp == '\0');
699
700 if (*cp == ':' || *cp == '\0') {
701 char save = *cp;
702
703 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000704 if ((*func)(entry)) {
705 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000706 return True;
thughes21942d92004-07-12 09:35:37 +0000707 }
nethercote71980f02004-01-24 18:18:54 +0000708 *cp = save;
709 entry = cp+1;
710 }
711 cp++;
712 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000713
714 return False;
715}
716
717static Bool contains(const char *p) {
718 if (VG_STREQ(p, VG_(libdir))) {
719 return True;
720 }
721 return False;
nethercote71980f02004-01-24 18:18:54 +0000722}
723
724/* Prepare the client's environment. This is basically a copy of our
725 environment, except:
726 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
727 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
728
729 If any of these is missing, then it is added.
730
731 Yummy. String hacking in C.
732
733 If this needs to handle any more variables it should be hacked
734 into something table driven.
735 */
736static char **fix_environment(char **origenv, const char *preload)
737{
738 static const char inject_so[] = "vg_inject.so";
739 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
740 static const char ld_preload[] = "LD_PRELOAD=";
741 static const char valgrind_clo[] = VALGRINDCLO "=";
742 static const int ld_library_path_len = sizeof(ld_library_path)-1;
743 static const int ld_preload_len = sizeof(ld_preload)-1;
744 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
745 int ld_preload_done = 0;
746 int ld_library_path_done = 0;
747 char *inject_path;
748 int inject_path_len;
749 int vgliblen = strlen(VG_(libdir));
750 char **cpp;
751 char **ret;
752 int envc;
753 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
754
755 /* Find the vg_inject.so; also make room for the tool preload
756 library */
757 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
758 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000759 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000760
761 if (preload)
762 snprintf(inject_path, inject_path_len, "%s/%s:%s",
763 VG_(libdir), inject_so, preload);
764 else
765 snprintf(inject_path, inject_path_len, "%s/%s",
766 VG_(libdir), inject_so);
767
768 /* Count the original size of the env */
769 envc = 0; /* trailing NULL */
770 for (cpp = origenv; cpp && *cpp; cpp++)
771 envc++;
772
773 /* Allocate a new space */
774 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000775 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000776
777 /* copy it over */
778 for (cpp = ret; *origenv; )
779 *cpp++ = *origenv++;
780 *cpp = NULL;
781
782 vg_assert(envc == (cpp - ret));
783
784 /* Walk over the new environment, mashing as we go */
785 for (cpp = ret; cpp && *cpp; cpp++) {
786 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000787 /* If the LD_LIBRARY_PATH already contains libdir, then don't
788 bother adding it again, even if it isn't the first (it
789 seems that the Java runtime will keep reexecing itself
790 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000791 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000792 int len = strlen(*cpp) + vgliblen*2 + 16;
793 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000794 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000795
796 snprintf(cp, len, "%s%s:%s",
797 ld_library_path, VG_(libdir),
798 (*cpp)+ld_library_path_len);
799
800 *cpp = cp;
801 }
802
803 ld_library_path_done = 1;
804 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
805 int len = strlen(*cpp) + inject_path_len;
806 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000807 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000808
809 snprintf(cp, len, "%s%s:%s",
810 ld_preload, inject_path, (*cpp)+ld_preload_len);
811
812 *cpp = cp;
813
814 ld_preload_done = 1;
815 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
816 *cpp = "";
817 }
818 }
819
820 /* Add the missing bits */
821
822 if (!ld_library_path_done) {
823 int len = ld_library_path_len + vgliblen*2 + 16;
824 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000825 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000826
827 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
828
829 ret[envc++] = cp;
830 }
831
832 if (!ld_preload_done) {
833 int len = ld_preload_len + inject_path_len;
834 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000835 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000836
837 snprintf(cp, len, "%s%s",
838 ld_preload, inject_path);
839
840 ret[envc++] = cp;
841 }
842
843 ret[envc] = NULL;
844
845 return ret;
846}
847
848extern char **environ; /* our environment */
849//#include <error.h>
850
851/* Add a string onto the string table, and return its address */
852static char *copy_str(char **tab, const char *str)
853{
854 char *cp = *tab;
855 char *orig = cp;
856
857 while(*str)
858 *cp++ = *str++;
859 *cp++ = '\0';
860
861 if (0)
nethercote545fe672004-11-01 16:52:43 +0000862 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000863
864 *tab = cp;
865
866 return orig;
867}
868
869/*
870 This sets up the client's initial stack, containing the args,
871 environment and aux vector.
872
873 The format of the stack is:
874
875 higher address +-----------------+
876 | Trampoline code |
877 +-----------------+
878 | |
879 : string table :
880 | |
881 +-----------------+
882 | AT_NULL |
883 - -
884 | auxv |
885 +-----------------+
886 | NULL |
887 - -
888 | envp |
889 +-----------------+
890 | NULL |
891 - -
892 | argv |
893 +-----------------+
894 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000895 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000896 | undefined |
897 : :
898 */
nethercotec25c4492004-10-18 11:52:17 +0000899static Addr setup_client_stack(void* init_sp,
900 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000901 const struct exeinfo *info,
902 UInt** client_auxv)
903{
nethercotee567e702004-07-10 17:49:17 +0000904 void* res;
nethercote71980f02004-01-24 18:18:54 +0000905 char **cpp;
906 char *strtab; /* string table */
907 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000908 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000909 struct ume_auxv *auxv;
910 const struct ume_auxv *orig_auxv;
911 const struct ume_auxv *cauxv;
912 unsigned stringsize; /* total size of strings in bytes */
913 unsigned auxsize; /* total size of auxv in bytes */
914 int argc; /* total argc */
915 int envc; /* total number of env vars */
916 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000917 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000918
919 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000920 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000921
922 /* ==================== compute sizes ==================== */
923
924 /* first of all, work out how big the client stack will be */
925 stringsize = 0;
926
927 /* paste on the extra args if the loader needs them (ie, the #!
928 interpreter and its argument) */
929 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000930 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000931 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000932 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000933 }
nethercoted6a56872004-07-26 15:32:47 +0000934 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000935 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000936 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000937 }
938
939 /* now scan the args we're given... */
940 for (cpp = orig_argv; *cpp; cpp++) {
941 argc++;
942 stringsize += strlen(*cpp) + 1;
943 }
944
945 /* ...and the environment */
946 envc = 0;
947 for (cpp = orig_envp; cpp && *cpp; cpp++) {
948 envc++;
949 stringsize += strlen(*cpp) + 1;
950 }
951
952 /* now, how big is the auxv? */
953 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
954 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
955 if (cauxv->a_type == AT_PLATFORM)
956 stringsize += strlen(cauxv->u.a_ptr) + 1;
957 auxsize += sizeof(*cauxv);
958 }
959
960 /* OK, now we know how big the client stack is */
961 stacksize =
962 sizeof(int) + /* argc */
963 sizeof(char **)*argc + /* argv */
964 sizeof(char **) + /* terminal NULL */
965 sizeof(char **)*envc + /* envp */
966 sizeof(char **) + /* terminal NULL */
967 auxsize + /* auxv */
968 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000969 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000970
nethercotef84f6952004-07-15 14:58:33 +0000971 // decide where stack goes!
972 VG_(clstk_end) = VG_(client_end);
973
nethercote73b526f2004-10-31 18:48:21 +0000974 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000975
nethercote71980f02004-01-24 18:18:54 +0000976 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000977 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000978 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
979
nethercote71980f02004-01-24 18:18:54 +0000980 /* base of the string table (aligned) */
981 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
982
983 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000984
nethercote5ee67ca2004-06-22 14:00:09 +0000985 if (0)
986 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000987 "clstk_base %p\n"
988 "clstk_end %p\n",
989 stringsize, auxsize, stacksize,
990 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000991
992
nethercote71980f02004-01-24 18:18:54 +0000993 /* ==================== allocate space ==================== */
994
995 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000996 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000997 PROT_READ | PROT_WRITE | PROT_EXEC,
998 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
999 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001000
1001 /* ==================== copy client stack ==================== */
1002
nethercotea3c3cf22004-11-01 18:38:00 +00001003 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +00001004
1005 /* --- argc --- */
1006 *ptr++ = argc; /* client argc */
1007
1008 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001009 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001010 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001011 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001012 }
nethercoted6a56872004-07-26 15:32:47 +00001013 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001014 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001015 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001016 }
1017 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001018 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001019 }
1020 *ptr++ = 0;
1021
1022 /* --- envp --- */
1023 VG_(client_envp) = (Char **)ptr;
1024 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001025 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001026 *ptr++ = 0;
1027
1028 /* --- auxv --- */
1029 auxv = (struct ume_auxv *)ptr;
1030 *client_auxv = (UInt *)auxv;
1031
1032 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1033 /* copy the entry... */
1034 *auxv = *orig_auxv;
1035
1036 /* ...and fix up the copy */
1037 switch(auxv->a_type) {
1038 case AT_PHDR:
1039 if (info->phdr == 0)
1040 auxv->a_type = AT_IGNORE;
1041 else
1042 auxv->u.a_val = info->phdr;
1043 break;
1044
1045 case AT_PHNUM:
1046 if (info->phdr == 0)
1047 auxv->a_type = AT_IGNORE;
1048 else
1049 auxv->u.a_val = info->phnum;
1050 break;
1051
1052 case AT_BASE:
1053 if (info->interp_base == 0)
1054 auxv->a_type = AT_IGNORE;
1055 else
1056 auxv->u.a_val = info->interp_base;
1057 break;
1058
1059 case AT_PLATFORM: /* points to a platform description string */
1060 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1061 break;
1062
1063 case AT_ENTRY:
1064 auxv->u.a_val = info->entry;
1065 break;
1066
1067 case AT_IGNORE:
1068 case AT_EXECFD:
1069 case AT_PHENT:
1070 case AT_PAGESZ:
1071 case AT_FLAGS:
1072 case AT_NOTELF:
1073 case AT_UID:
1074 case AT_EUID:
1075 case AT_GID:
1076 case AT_EGID:
1077 case AT_CLKTCK:
1078 case AT_HWCAP:
1079 case AT_FPUCW:
1080 case AT_DCACHEBSIZE:
1081 case AT_ICACHEBSIZE:
1082 case AT_UCACHEBSIZE:
1083 /* All these are pointerless, so we don't need to do anything
1084 about them. */
1085 break;
1086
1087 case AT_SECURE:
1088 /* If this is 1, then it means that this program is running
1089 suid, and therefore the dynamic linker should be careful
1090 about LD_PRELOAD, etc. However, since stage1 (the thing
1091 the kernel actually execve's) should never be SUID, and we
1092 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1093 set AT_SECURE to 0. */
1094 auxv->u.a_val = 0;
1095 break;
1096
1097 case AT_SYSINFO:
1098 /* Leave this unmolested for now, but we'll update it later
1099 when we set up the client trampoline code page */
1100 break;
1101
1102 case AT_SYSINFO_EHDR:
1103 /* Trash this, because we don't reproduce it */
1104 auxv->a_type = AT_IGNORE;
1105 break;
1106
1107 default:
1108 /* stomp out anything we don't know about */
1109 if (0)
nethercote545fe672004-11-01 16:52:43 +00001110 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001111 auxv->a_type = AT_IGNORE;
1112 break;
1113
1114 }
1115 }
1116 *auxv = *orig_auxv;
1117 vg_assert(auxv->a_type == AT_NULL);
1118
njnc6168192004-11-29 13:54:10 +00001119// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1120// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
njnca0518d2004-11-26 19:34:36 +00001121#ifdef __x86__
nethercotef84f6952004-07-15 14:58:33 +00001122 /* --- trampoline page --- */
1123 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1124 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001125#endif
nethercotef84f6952004-07-15 14:58:33 +00001126
nethercote71980f02004-01-24 18:18:54 +00001127 vg_assert((strtab-stringbase) == stringsize);
1128
nethercote5ee67ca2004-06-22 14:00:09 +00001129 /* We know the initial ESP is pointing at argc/argv */
1130 VG_(client_argc) = *(Int*)cl_esp;
1131 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1132
nethercote71980f02004-01-24 18:18:54 +00001133 return cl_esp;
1134}
1135
1136/*====================================================================*/
1137/*=== Find executable ===*/
1138/*====================================================================*/
1139
thughes4ad52d02004-06-27 17:37:21 +00001140static const char* executable_name;
1141
1142static Bool match_executable(const char *entry) {
1143 char buf[strlen(entry) + strlen(executable_name) + 2];
1144
1145 /* empty PATH element means . */
1146 if (*entry == '\0')
1147 entry = ".";
1148
1149 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1150
1151 if (access(buf, R_OK|X_OK) == 0) {
1152 executable_name = strdup(buf);
1153 vg_assert(NULL != executable_name);
1154 return True;
1155 }
1156 return False;
1157}
1158
nethercote71980f02004-01-24 18:18:54 +00001159static const char* find_executable(const char* exec)
1160{
1161 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001162 executable_name = exec;
1163 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001164 /* no '/' - we need to search the path */
1165 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001166 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001167 }
thughes4ad52d02004-06-27 17:37:21 +00001168 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001169}
1170
1171
1172/*====================================================================*/
1173/*=== Loading tools ===*/
1174/*====================================================================*/
1175
1176static void list_tools(void)
1177{
1178 DIR *dir = opendir(VG_(libdir));
1179 struct dirent *de;
1180 int first = 1;
1181
1182 if (dir == NULL) {
1183 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001184 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001185 return;
1186 }
1187
nethercotef4928da2004-06-15 10:54:40 +00001188 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001189 int len = strlen(de->d_name);
1190
njn063c5402004-11-22 16:58:05 +00001191 /* look for vgtool_TOOL.so names */
1192 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1193 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001194 VG_STREQ(de->d_name + len - 3, ".so")) {
1195 if (first) {
1196 fprintf(stderr, "Available tools:\n");
1197 first = 0;
1198 }
1199 de->d_name[len-3] = '\0';
1200 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001201 }
1202 }
1203
1204 closedir(dir);
1205
1206 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001207 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1208 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001209}
1210
1211
1212/* Find and load a tool, and check it looks ok. Also looks to see if there's
1213 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1214static void load_tool( const char *toolname, void** handle_out,
1215 ToolInfo** toolinfo_out, char **preloadpath_out )
1216{
1217 Bool ok;
1218 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1219 char buf[len];
1220 void* handle;
1221 ToolInfo* toolinfo;
1222 char* preloadpath = NULL;
1223 Int* vg_malloc_redzonep;
1224
1225 // XXX: allowing full paths for --tool option -- does it make sense?
1226 // Doesn't allow for vgpreload_<tool>.so.
1227
1228 if (strchr(toolname, '/') != 0) {
1229 /* toolname contains '/', and so must be a pathname */
1230 handle = dlopen(toolname, RTLD_NOW);
1231 } else {
1232 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001233 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001234 handle = dlopen(buf, RTLD_NOW);
1235
1236 if (handle != NULL) {
1237 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1238 if (access(buf, R_OK) == 0) {
1239 preloadpath = strdup(buf);
1240 vg_assert(NULL != preloadpath);
1241 }
1242 }
1243 }
1244
1245 ok = (NULL != handle);
1246 if (!ok) {
1247 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1248 goto bad_load;
1249 }
1250
njn26f02512004-11-22 18:33:15 +00001251 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001252 ok = (NULL != toolinfo);
1253 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001254 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001255 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1256 goto bad_load;
1257 }
1258
1259 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1260 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001261 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001262 if (!ok) {
1263 fprintf(stderr, "Error:\n"
1264 " Tool and core interface versions do not match.\n"
1265 " Interface version used by core is: %d.%d (size %d)\n"
1266 " Interface version used by tool is: %d.%d (size %d)\n"
1267 " The major version numbers must match.\n",
1268 VG_CORE_INTERFACE_MAJOR_VERSION,
1269 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001270 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001271 toolinfo->interface_major_version,
1272 toolinfo->interface_minor_version,
1273 toolinfo->sizeof_ToolInfo);
1274 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1275 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001276 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001277 else
nethercote996901a2004-08-03 13:29:09 +00001278 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001279 goto bad_load;
1280 }
1281
1282 // Set redzone size for V's allocator
1283 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1284 if ( NULL != vg_malloc_redzonep ) {
1285 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1286 }
1287
1288 vg_assert(NULL != handle && NULL != toolinfo);
1289 *handle_out = handle;
1290 *toolinfo_out = toolinfo;
1291 *preloadpath_out = preloadpath;
1292 return;
1293
1294
1295 bad_load:
1296 if (handle != NULL)
1297 dlclose(handle);
1298
nethercotef4928da2004-06-15 10:54:40 +00001299 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001300 list_tools();
1301 exit(127);
1302}
1303
nethercotef4928da2004-06-15 10:54:40 +00001304
1305/*====================================================================*/
1306/*=== Command line errors ===*/
1307/*====================================================================*/
1308
1309static void abort_msg ( void )
1310{
nethercotef8548672004-06-21 12:42:35 +00001311 VG_(clo_log_to) = VgLogTo_Fd;
1312 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001313}
1314
1315void VG_(bad_option) ( Char* opt )
1316{
1317 abort_msg();
1318 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1319 VG_(printf)("valgrind: Use --help for more information.\n");
1320 VG_(exit)(1);
1321}
1322
1323static void missing_tool_option ( void )
1324{
1325 abort_msg();
1326 VG_(printf)("valgrind: Missing --tool option\n");
1327 list_tools();
1328 VG_(printf)("valgrind: Use --help for more information.\n");
1329 VG_(exit)(1);
1330}
1331
1332static void missing_prog ( void )
1333{
1334 abort_msg();
1335 VG_(printf)("valgrind: no program specified\n");
1336 VG_(printf)("valgrind: Use --help for more information.\n");
1337 VG_(exit)(1);
1338}
1339
1340static void config_error ( Char* msg )
1341{
1342 abort_msg();
1343 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1344 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1345 VG_(exit)(1);
1346}
1347
1348
nethercote71980f02004-01-24 18:18:54 +00001349/*====================================================================*/
1350/*=== Loading the client ===*/
1351/*====================================================================*/
1352
nethercotef4928da2004-06-15 10:54:40 +00001353static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001354 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1355{
1356 // If they didn't specify an executable with --exec, and didn't specify
1357 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001358 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001359 if (cl_argv[0] == NULL ||
1360 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1361 {
nethercotef4928da2004-06-15 10:54:40 +00001362 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001363 }
1364 }
1365
1366 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001367 info->exe_base = VG_(client_base);
1368 info->exe_end = VG_(client_end);
1369 info->argv = cl_argv;
1370
nethercotef4928da2004-06-15 10:54:40 +00001371 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001372 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001373 // Totally zero 'info' before continuing.
1374 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001375 } else {
1376 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001377 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001378 ret = do_exec(exec, info);
1379 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001380 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1381 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001382 exit(127);
1383 }
1384 }
1385
1386 /* Copy necessary bits of 'info' that were filled in */
1387 *client_eip = info->init_eip;
1388 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1389}
1390
nethercote969ecf12004-10-13 17:29:01 +00001391/*====================================================================*/
1392/*=== Address space unpadding ===*/
1393/*====================================================================*/
1394
1395typedef struct {
1396 char* killpad_start;
1397 char* killpad_end;
1398 struct stat* killpad_padstat;
1399} killpad_extra;
1400
1401static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1402 int maj, int min, int ino, void* ex)
1403{
1404 killpad_extra* extra = ex;
1405 void *b, *e;
1406 int res;
1407
1408 vg_assert(NULL != extra->killpad_padstat);
1409
1410 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1411 extra->killpad_padstat->st_ino != ino)
1412 return 1;
1413
1414 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1415 return 1;
1416
1417 if (segstart <= extra->killpad_start)
1418 b = extra->killpad_start;
1419 else
1420 b = segstart;
1421
1422 if (segend >= extra->killpad_end)
1423 e = extra->killpad_end;
1424 else
1425 e = segend;
1426
1427 res = munmap(b, (char *)e-(char *)b);
1428 vg_assert(0 == res);
1429
1430 return 1;
1431}
1432
1433// Remove padding of 'padfile' from a range of address space.
1434void as_unpad(void *start, void *end, int padfile)
1435{
1436 static struct stat padstat;
1437 killpad_extra extra;
1438 int res;
1439
1440 vg_assert(padfile > 0);
1441
1442 res = fstat(padfile, &padstat);
1443 vg_assert(0 == res);
1444 extra.killpad_padstat = &padstat;
1445 extra.killpad_start = start;
1446 extra.killpad_end = end;
1447 foreach_map(killpad, &extra);
1448}
1449
1450void as_closepadfile(int padfile)
1451{
1452 int res = close(padfile);
1453 vg_assert(0 == res);
1454}
1455
nethercote71980f02004-01-24 18:18:54 +00001456
1457/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001458/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001459/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001460
njn25e49d8e72002-09-23 09:36:25 +00001461/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001462VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001463Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001464Bool VG_(clo_db_attach) = False;
1465Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001466Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001467Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001468Int VG_(clo_verbosity) = 1;
1469Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001470Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001471
nethercotef1e5e152004-09-01 23:58:16 +00001472/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001473 fd is initially stdout, for --help, but gets moved to stderr by default
1474 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001475VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001476Int VG_(clo_log_fd) = 1;
1477Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001478
thughes6233a382004-08-21 11:10:44 +00001479Bool VG_(clo_time_stamp) = False;
1480
sewardj6024b212003-07-13 10:54:33 +00001481Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001482Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001483Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001484Bool VG_(clo_profile) = False;
sewardj8e4d7dc2004-11-28 18:07:41 +00001485Bool VG_(clo_bbprofile) = False;
njn25e49d8e72002-09-23 09:36:25 +00001486UChar VG_(clo_trace_codegen) = 0; // 00000000b
1487Bool VG_(clo_trace_syscalls) = False;
1488Bool VG_(clo_trace_signals) = False;
1489Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001490Bool VG_(clo_trace_sched) = False;
1491Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001492Int VG_(clo_dump_error) = 0;
1493Int VG_(clo_backtrace_size) = 4;
1494Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001495Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001496Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001497Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001498Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001499Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001500
jsgf855d93d2003-10-13 22:26:55 +00001501static Bool VG_(clo_wait_for_gdb) = False;
1502
1503/* If we're doing signal routing, poll for signals every 50mS by
1504 default. */
1505Int VG_(clo_signal_polltime) = 50;
1506
1507/* These flags reduce thread wakeup latency on syscall completion and
1508 signal delivery, respectively. The downside is possible unfairness. */
1509Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1510Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1511
sewardjde4a1d02002-03-22 01:27:54 +00001512
nethercote6c999f22004-01-31 22:55:15 +00001513void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001514{
njn25e49d8e72002-09-23 09:36:25 +00001515 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001516"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001517"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001518" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001519" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001520" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001521" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001522" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001523" -q --quiet run silently; only print error msgs\n"
1524" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001525" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001526" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001527" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001528"\n"
1529" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001530" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1531" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1532" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1533" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1534" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001535" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001536"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001538" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1539" --log-file=<file> log messages to <file>.pid<pid>\n"
1540" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001541" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1542" --num-callers=<number> show <num> callers in stack traces [4]\n"
1543" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1544" --show-below-main=no|yes continue stack traces below main() [no]\n"
1545" --suppressions=<filename> suppress errors described in <filename>\n"
1546" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001547" --db-attach=no|yes start debugger when errors detected? [no]\n"
1548" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1549" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001550"\n";
njn7cf0bd32002-06-08 13:36:03 +00001551
njn25e49d8e72002-09-23 09:36:25 +00001552 Char* usage2 =
1553"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001554" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001555" --sanity-level=<number> level of sanity checking to do [1]\n"
1556" --single-step=no|yes translate each instr separately? [no]\n"
1557" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001558" --profile=no|yes profile? (tool must be built for it) [no]\n"
njnc767b432004-11-29 16:08:22 +00001559" --bbprofile=no|yes profile bbs? [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001560" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001561" --trace-codegen=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
njn25e49d8e72002-09-23 09:36:25 +00001562" --trace-syscalls=no|yes show all system calls? [no]\n"
1563" --trace-signals=no|yes show signal handling details? [no]\n"
1564" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001565" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001566" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001567" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001568"\n"
sewardj8b635a42004-11-22 19:01:47 +00001569" --vex-iropt-verbosity 0 .. 9 [0]\n"
1570" --vex-iropt-level 0 .. 2 [2]\n"
1571" --vex-iropt-precise-memory-exns [no]\n"
1572" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1573" --vex-guest-max-insns 1 .. 100 [50]\n"
1574" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1575"\n"
sewardj2a99cf62004-11-24 10:44:19 +00001576" --trace-codegen values (omit the middle space):\n"
1577" 1000 0000 show conversion into IR\n"
1578" 0100 0000 show after initial opt\n"
1579" 0010 0000 show after instrumentation\n"
1580" 0001 0000 show after second opt\n"
1581" 0000 1000 show after tree building\n"
1582" 0000 0100 show selecting insns\n"
1583" 0000 0010 show after reg-alloc\n"
1584" 0000 0001 show final assembly\n"
1585"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001586" debugging options for Valgrind tools that report errors\n"
1587" --dump-error=<number> show translation for basic block associated\n"
1588" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001589"\n";
njn3e884182003-04-15 13:03:23 +00001590
1591 Char* usage3 =
1592"\n"
nethercote71980f02004-01-24 18:18:54 +00001593" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001594"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001595" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001596" and licensed under the GNU General Public License, version 2.\n"
1597" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001598"\n"
nethercote137bc552003-11-14 17:47:54 +00001599" Tools are copyright and licensed by their authors. See each\n"
1600" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001601"\n";
njn7cf0bd32002-06-08 13:36:03 +00001602
fitzhardinge98abfc72003-12-16 02:05:15 +00001603 VG_(printf)(usage1);
1604 if (VG_(details).name) {
1605 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001607 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001608 else
1609 VG_(printf)(" (none)\n");
1610 }
nethercote6c999f22004-01-31 22:55:15 +00001611 if (debug_help) {
1612 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001613
nethercote6c999f22004-01-31 22:55:15 +00001614 if (VG_(details).name) {
1615 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1616
1617 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001618 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001619 else
1620 VG_(printf)(" (none)\n");
1621 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001622 }
nethercote421281e2003-11-20 16:20:55 +00001623 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001624 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001625}
sewardjde4a1d02002-03-22 01:27:54 +00001626
nethercote71980f02004-01-24 18:18:54 +00001627static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001628 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001629{
nethercote71980f02004-01-24 18:18:54 +00001630 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001631
sewardj8b635a42004-11-22 19:01:47 +00001632 LibVEX_default_VexControl(& VG_(clo_vex_control));
1633
nethercote71980f02004-01-24 18:18:54 +00001634 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001638 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001639 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001640
nethercotef6a1d502004-08-09 12:21:57 +00001641 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1642 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001643 *need_help = 1;
1644
nethercotef6a1d502004-08-09 12:21:57 +00001645 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001646 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001647
nethercotef6c99d72004-11-09 14:35:43 +00001648 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001649 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001650
nethercotef6a1d502004-08-09 12:21:57 +00001651 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1652 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001653 }
1654 }
1655
nethercotef4928da2004-06-15 10:54:40 +00001656 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001657 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001658 if (0 == *need_help) {
1659 // neither --tool nor --help/--help-debug specified
1660 missing_tool_option();
1661 } else {
1662 // Give help message, without any tool-specific help
1663 usage(/*help-debug?*/2 == *need_help);
1664 }
nethercote71980f02004-01-24 18:18:54 +00001665 }
1666}
1667
nethercote5ee67ca2004-06-22 14:00:09 +00001668static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001669{
nethercotef8548672004-06-21 12:42:35 +00001670 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001671 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001672
nethercotee1730692003-11-20 10:38:07 +00001673 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001674 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001675
sewardj19d81412002-06-03 01:10:40 +00001676 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001677 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001678 config_error("Please use absolute paths in "
1679 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001680
njnc6168192004-11-29 13:54:10 +00001681// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001682#ifdef __x86__
1683 {
1684 Int *auxp;
1685 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1686 switch(auxp[0]) {
1687 case AT_SYSINFO:
1688 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1689 break;
1690 }
1691 }
1692 }
1693#endif
sewardjde4a1d02002-03-22 01:27:54 +00001694
nethercotef6a1d502004-08-09 12:21:57 +00001695 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001696
nethercotef6a1d502004-08-09 12:21:57 +00001697 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001698 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001699
thughes3bfd5a02004-07-18 08:05:44 +00001700 /* Look for a colon in the switch name */
1701 while (*colon && *colon != ':' && *colon != '=')
1702 colon++;
nethercote71980f02004-01-24 18:18:54 +00001703
1704 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001705 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001706 if (VG_CLO_STREQN(2, arg, "--") &&
1707 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1708 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1709 {
1710 // prefix matches, convert "--toolname:foo" to "--foo"
1711 if (0)
1712 VG_(printf)("tool-specific arg: %s\n", arg);
1713 arg += toolname_len + 1;
1714 arg[0] = '-';
1715 arg[1] = '-';
1716
1717 } else {
1718 // prefix doesn't match, skip to next arg
1719 continue;
1720 }
1721 }
1722
fitzhardinge98abfc72003-12-16 02:05:15 +00001723 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001724 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001725 continue;
nethercote71980f02004-01-24 18:18:54 +00001726 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001727 continue;
1728
nethercote71980f02004-01-24 18:18:54 +00001729 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001730 continue;
nethercote27fec902004-06-16 21:26:32 +00001731
nethercote71980f02004-01-24 18:18:54 +00001732 else if (VG_CLO_STREQ(arg, "-v") ||
1733 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001734 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001735
nethercote71980f02004-01-24 18:18:54 +00001736 else if (VG_CLO_STREQ(arg, "-q") ||
1737 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001738 VG_(clo_verbosity)--;
1739
nethercote27fec902004-06-16 21:26:32 +00001740 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001741 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1742 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1743 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1744 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1745 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1746 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
nethercote27fec902004-06-16 21:26:32 +00001747 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1748 else VG_BOOL_CLO("--profile", VG_(clo_profile))
sewardj8e4d7dc2004-11-28 18:07:41 +00001749 else VG_BOOL_CLO("--bbprofile", VG_(clo_bbprofile))
nethercote27fec902004-06-16 21:26:32 +00001750 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1751 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001752 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001753 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1754 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1755 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1756 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1757 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1758 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1759 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001760
nethercote27fec902004-06-16 21:26:32 +00001761 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1762 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001763
nethercote27fec902004-06-16 21:26:32 +00001764 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1765 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1766 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001767 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001768 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1769 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001770
sewardj8b635a42004-11-22 19:01:47 +00001771 else VG_BNUM_CLO("--vex-iropt-verbosity",
1772 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1773 else VG_BNUM_CLO("--vex-iropt-level",
1774 VG_(clo_vex_control).iropt_level, 0, 2)
1775 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1776 VG_(clo_vex_control).iropt_precise_memory_exns)
1777 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1778 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1779 else VG_BNUM_CLO("--vex-guest-max-insns",
1780 VG_(clo_vex_control).guest_max_insns, 1, 100)
1781 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1782 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1783
nethercotef8548672004-06-21 12:42:35 +00001784 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001785 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001786 VG_(clo_log_to) = VgLogTo_Fd;
1787 VG_(clo_log_name) = NULL;
1788 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1789 }
1790 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1791 VG_(clo_log_to) = VgLogTo_Fd;
1792 VG_(clo_log_name) = NULL;
1793 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001794 }
1795
nethercotef8548672004-06-21 12:42:35 +00001796 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001797 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001798 VG_(clo_log_to) = VgLogTo_File;
1799 VG_(clo_log_name) = &arg[10];
1800 }
1801 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1802 VG_(clo_log_to) = VgLogTo_File;
1803 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001804 }
sewardjde4a1d02002-03-22 01:27:54 +00001805
nethercotef8548672004-06-21 12:42:35 +00001806 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001807 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001808 VG_(clo_log_to) = VgLogTo_Socket;
1809 VG_(clo_log_name) = &arg[12];
1810 }
1811 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1812 VG_(clo_log_to) = VgLogTo_Socket;
1813 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001814 }
1815
nethercote71980f02004-01-24 18:18:54 +00001816 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001817 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001818 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001819 VG_(message)(Vg_UserMsg,
1820 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001822 }
nethercote71980f02004-01-24 18:18:54 +00001823 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001824 VG_(clo_n_suppressions)++;
1825 }
sewardjde4a1d02002-03-22 01:27:54 +00001826
njn25e49d8e72002-09-23 09:36:25 +00001827 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001829 Int j;
nethercote71980f02004-01-24 18:18:54 +00001830 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001831
sewardj2a99cf62004-11-24 10:44:19 +00001832 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001833 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +00001834 "--trace-codegen argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001835 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001836 }
sewardj8b635a42004-11-22 19:01:47 +00001837 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001838 if ('0' == opt[j]) { /* do nothing */ }
sewardj8b635a42004-11-22 19:01:47 +00001839 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001840 else {
1841 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1842 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001843 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001844 }
1845 }
1846 }
sewardjde4a1d02002-03-22 01:27:54 +00001847
nethercote71980f02004-01-24 18:18:54 +00001848 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001849 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001850 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001851 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001852 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001853 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001854
nethercote71980f02004-01-24 18:18:54 +00001855 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001856 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001857 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001858 }
sewardjde4a1d02002-03-22 01:27:54 +00001859 }
1860
nethercote27fec902004-06-16 21:26:32 +00001861 // Check various option values
1862
njnf9ebf672003-05-12 21:41:30 +00001863 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001864 VG_(clo_verbosity) = 0;
1865
nethercote04d0fbc2004-01-26 16:48:06 +00001866 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001867 VG_(message)(Vg_UserMsg, "");
1868 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001869 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001870 VG_(message)(Vg_UserMsg,
1871 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001872 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001873 }
1874
nethercotef8548672004-06-21 12:42:35 +00001875 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001876 should be connected to whatever sink has been selected, and we
1877 indiscriminately chuck stuff into it without worrying what the
1878 nature of it is. Oh the wonder of Unix streams. */
1879
nethercotee1730692003-11-20 10:38:07 +00001880 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001881 the terminal any problems to do with processing command line
1882 opts. */
nethercotef8548672004-06-21 12:42:35 +00001883 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001884 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001885
1886 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001887
sewardj4cf05692002-10-27 20:28:29 +00001888 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001889 vg_assert(VG_(clo_log_name) == NULL);
1890 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001891 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001892
sewardj4cf05692002-10-27 20:28:29 +00001893 case VgLogTo_File: {
1894 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001895 Int seq = 0;
1896 Int pid = VG_(getpid)();
1897
nethercotef8548672004-06-21 12:42:35 +00001898 vg_assert(VG_(clo_log_name) != NULL);
1899 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001900
nethercote71980f02004-01-24 18:18:54 +00001901 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001902 if (seq == 0)
1903 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001904 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001905 else
1906 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001907 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001908 seq++;
1909
nethercotef8548672004-06-21 12:42:35 +00001910 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001911 = VG_(open)(logfilename,
1912 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1913 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001914 if (eventually_log_fd >= 0) {
1915 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001916 break;
1917 } else {
nethercotef8548672004-06-21 12:42:35 +00001918 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001919 VG_(message)(Vg_UserMsg,
1920 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001921 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001922 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001923 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001924 break;
1925 }
1926 }
1927 }
sewardj4cf05692002-10-27 20:28:29 +00001928 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001929 }
1930
1931 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001932 vg_assert(VG_(clo_log_name) != NULL);
1933 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1934 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1935 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001936 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001937 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001938 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001939 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001940 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001941 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001942 }
nethercotef8548672004-06-21 12:42:35 +00001943 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001944 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001945 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001946 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001947 VG_(message)(Vg_UserMsg,
1948 "Log messages will sent to stderr instead." );
1949 VG_(message)(Vg_UserMsg,
1950 "" );
1951 /* We don't change anything here. */
1952 } else {
nethercotef8548672004-06-21 12:42:35 +00001953 vg_assert(eventually_log_fd > 0);
1954 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001955 VG_(logging_to_filedes) = False;
1956 }
sewardj73cf3bc2002-11-03 03:20:15 +00001957 break;
1958 }
1959
sewardj4cf05692002-10-27 20:28:29 +00001960 }
1961
nethercotef8548672004-06-21 12:42:35 +00001962 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001963 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001964 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001965 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1966 else {
nethercotef8548672004-06-21 12:42:35 +00001967 VG_(clo_log_fd) = eventually_log_fd;
1968 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001969 }
1970
sewardj4cf05692002-10-27 20:28:29 +00001971 /* Ok, the logging sink is running now. Print a suitable preamble.
1972 If logging to file or a socket, write details of parent PID and
1973 command line args, to help people trying to interpret the
1974 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001975
sewardj83adf412002-05-01 01:25:45 +00001976 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001977 /* Tool details */
nethercotea131bb82004-09-06 15:34:37 +00001978 VG_(message)(Vg_UserMsg, "%s%s%s, %s for %s.",
njnd04b7c62002-10-03 14:05:52 +00001979 VG_(details).name,
1980 NULL == VG_(details).version ? "" : "-",
1981 NULL == VG_(details).version
1982 ? (Char*)"" : VG_(details).version,
nethercotea131bb82004-09-06 15:34:37 +00001983 VG_(details).description,
1984 VG_PLATFORM);
njnd04b7c62002-10-03 14:05:52 +00001985 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001986
njnd04b7c62002-10-03 14:05:52 +00001987 /* Core details */
1988 VG_(message)(Vg_UserMsg,
nethercotea131bb82004-09-06 15:34:37 +00001989 "Using valgrind-%s, a program supervision framework for %s.",
1990 VERSION, VG_PLATFORM);
sewardjde4a1d02002-03-22 01:27:54 +00001991 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00001992 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00001993 }
1994
nethercotec1e395d2003-11-10 13:26:49 +00001995 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00001996 VG_(message)(Vg_UserMsg, "");
1997 VG_(message)(Vg_UserMsg,
1998 "My PID = %d, parent PID = %d. Prog and args are:",
1999 VG_(getpid)(), VG_(getppid)() );
2000 for (i = 0; i < VG_(client_argc); i++)
2001 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2002 }
2003
sewardjde4a1d02002-03-22 01:27:54 +00002004 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002005 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002006 if (VG_(clo_log_to) != VgLogTo_Fd)
2007 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002008 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002009 VG_(message)(Vg_UserMsg, "Command line");
2010 for (i = 0; i < VG_(client_argc); i++)
2011 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2012
sewardjde4a1d02002-03-22 01:27:54 +00002013 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002014 for (i = 1; i < vg_argc; i++) {
2015 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002016 }
nethercotea70f7352004-04-18 12:08:46 +00002017
2018 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2019 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2020 if (fd < 0) {
2021 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2022 } else {
2023 #define BUF_LEN 256
2024 Char version_buf[BUF_LEN];
2025 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2026 vg_assert(n <= 256);
2027 if (n > 0) {
2028 version_buf[n-1] = '\0';
2029 VG_(message)(Vg_UserMsg, " %s", version_buf);
2030 } else {
2031 VG_(message)(Vg_UserMsg, " (empty?)");
2032 }
2033 VG_(close)(fd);
2034 #undef BUF_LEN
2035 }
sewardjde4a1d02002-03-22 01:27:54 +00002036 }
2037
fitzhardinge98abfc72003-12-16 02:05:15 +00002038 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002039 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002040 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002041 needs one, load the default */
2042 static const Char default_supp[] = "default.supp";
2043 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2044 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2045 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2046 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2047 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002048 }
sewardj4cf05692002-10-27 20:28:29 +00002049
njn6a230532003-07-21 10:38:23 +00002050 if (VG_(clo_gen_suppressions) &&
njn95ec8702004-11-22 16:46:13 +00002051 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002052 VG_(message)(Vg_UserMsg,
2053 "Can't use --gen-suppressions=yes with this tool,");
2054 VG_(message)(Vg_UserMsg,
2055 "as it doesn't generate errors.");
2056 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002057 }
sewardjde4a1d02002-03-22 01:27:54 +00002058}
2059
nethercotef6a1d502004-08-09 12:21:57 +00002060// Build the string for VALGRINDCLO.
2061Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2062{
2063 /* If we're tracing the children, then we need to start it
2064 with our starter+arguments, which are copied into VALGRINDCLO,
2065 except the --exec= option is changed if present.
2066 */
2067 Int i;
2068 Char *exec;
2069 Char *cp;
2070 Char *optvar;
2071 Int optlen, execlen;
2072
2073 // All these allocated blocks are not free - because we're either
2074 // going to exec, or panic when we fail.
2075
2076 // Create --exec= option: "--exec=<exename>"
2077 exec = VG_(arena_malloc)(VG_AR_CORE,
2078 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2079 vg_assert(NULL != exec);
2080 VG_(sprintf)(exec, "--exec=%s", exename);
2081
2082 // Allocate space for optvar (may overestimate by counting --exec twice,
2083 // no matter)
2084 optlen = 1;
2085 for (i = 0; i < vg_argc; i++)
2086 optlen += VG_(strlen)(vg_argv[i]) + 1;
2087 optlen += VG_(strlen)(exec)+1;
2088 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2089
2090 // Copy all valgrind args except the old --exec (if present)
2091 // VG_CLO_SEP is the separator.
2092 cp = optvar;
2093 for (i = 1; i < vg_argc; i++) {
2094 Char *arg = vg_argv[i];
2095
2096 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2097 // don't copy existing --exec= arg
2098 } else if (VG_(strcmp)(arg, "--") == 0) {
2099 // stop at "--"
2100 break;
2101 } else {
2102 // copy non "--exec" arg
2103 Int len = VG_(strlen)(arg);
2104 VG_(memcpy)(cp, arg, len);
2105 cp += len;
2106 *cp++ = VG_CLO_SEP;
2107 }
2108 }
2109 // Add the new --exec= option
2110 execlen = VG_(strlen)(exec);
2111 VG_(memcpy)(cp, exec, execlen);
2112 cp += execlen;
2113 *cp++ = VG_CLO_SEP;
2114
2115 *cp = '\0';
2116
2117 return optvar;
2118}
2119
2120// Build "/proc/self/fd/<execfd>".
2121Char* VG_(build_child_exename)( void )
2122{
2123 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2124 vg_assert(NULL != exename);
2125 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2126 return exename;
2127}
2128
sewardjde4a1d02002-03-22 01:27:54 +00002129
nethercote71980f02004-01-24 18:18:54 +00002130/*====================================================================*/
2131/*=== File descriptor setup ===*/
2132/*====================================================================*/
2133
2134static void setup_file_descriptors(void)
2135{
2136 struct vki_rlimit rl;
2137
2138 /* Get the current file descriptor limits. */
2139 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2140 rl.rlim_cur = 1024;
2141 rl.rlim_max = 1024;
2142 }
2143
2144 /* Work out where to move the soft limit to. */
2145 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2146 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2147 } else {
2148 rl.rlim_cur = rl.rlim_max;
2149 }
2150
2151 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002152 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2153 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002154
2155 /* Update the soft limit. */
2156 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2157
nethercotef6a1d502004-08-09 12:21:57 +00002158 if (vgexecfd != -1)
2159 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002160 if (VG_(clexecfd) != -1)
2161 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2162}
2163
nethercote71980f02004-01-24 18:18:54 +00002164/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002165/*=== Initialise program data/text, etc. ===*/
2166/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002167
nethercote71980f02004-01-24 18:18:54 +00002168static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002169 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002170 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002171{
nethercote71980f02004-01-24 18:18:54 +00002172 UInt prot = 0;
2173 UInt flags = SF_MMAP|SF_NOSYMS;
2174 Bool is_stack_segment;
2175
2176 is_stack_segment =
2177 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2178
2179 /* Only record valgrind mappings for now, without loading any
2180 symbols. This is so we know where the free space is before we
2181 start allocating more memory (note: heap is OK, it's just mmap
2182 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002183 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002184 flags |= SF_VALGRIND;
2185 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2186 }
sewardjde4a1d02002-03-22 01:27:54 +00002187}
2188
nethercote71980f02004-01-24 18:18:54 +00002189// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002190Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002191
nethercote71980f02004-01-24 18:18:54 +00002192static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002193 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002194 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002195{
nethercote71980f02004-01-24 18:18:54 +00002196 UInt prot = 0;
2197 UInt flags;
2198 Bool is_stack_segment;
2199 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002200
nethercote71980f02004-01-24 18:18:54 +00002201 is_stack_segment
2202 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002203
nethercote71980f02004-01-24 18:18:54 +00002204 if (rr == 'r') prot |= VKI_PROT_READ;
2205 if (ww == 'w') prot |= VKI_PROT_WRITE;
2206 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002207
nethercote71980f02004-01-24 18:18:54 +00002208 if (is_stack_segment)
2209 flags = SF_STACK | SF_GROWDOWN;
2210 else
2211 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002212
nethercote71980f02004-01-24 18:18:54 +00002213 if (filename != NULL)
2214 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002215
nethercote820bd8c2004-09-07 23:04:49 +00002216 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002217 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002218
nethercote71980f02004-01-24 18:18:54 +00002219 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002220
nethercote71980f02004-01-24 18:18:54 +00002221 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2222 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002223
nethercote71980f02004-01-24 18:18:54 +00002224 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002225 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002226 vg_assert(0 != r_esp);
2227 if (is_stack_segment) {
2228 if (0)
2229 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2230 start,r_esp);
2231 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002232 }
sewardjde4a1d02002-03-22 01:27:54 +00002233}
2234
2235
nethercote71980f02004-01-24 18:18:54 +00002236/*====================================================================*/
2237/*=== Sanity check machinery (permanently engaged) ===*/
2238/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002239
2240/* A fast sanity check -- suitable for calling circa once per
2241 millisecond. */
2242
nethercote885dd912004-08-03 23:14:00 +00002243void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002244{
njn37cea302002-09-30 11:24:00 +00002245 VGP_PUSHCC(VgpCoreCheapSanity);
2246
nethercote27fec902004-06-16 21:26:32 +00002247 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002248
2249 /* --- First do all the tests that we can do quickly. ---*/
2250
nethercote297effd2004-08-02 15:07:57 +00002251 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002252
njn25e49d8e72002-09-23 09:36:25 +00002253 /* Check stuff pertaining to the memory check system. */
2254
2255 /* Check that nobody has spuriously claimed that the first or
2256 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002257 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002258 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002259 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002260 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002261 }
njn25e49d8e72002-09-23 09:36:25 +00002262
2263 /* --- Now some more expensive checks. ---*/
2264
2265 /* Once every 25 times, check some more expensive stuff. */
2266 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002267 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002268 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002269
njn37cea302002-09-30 11:24:00 +00002270 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002271 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002272
nethercote885dd912004-08-03 23:14:00 +00002273 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002274
njn25e49d8e72002-09-23 09:36:25 +00002275# if 0
2276 { void zzzmemscan(void); zzzmemscan(); }
2277# endif
2278
nethercote297effd2004-08-02 15:07:57 +00002279 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002280 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002281
2282 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002283 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002284 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002285 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002286 }
2287 /*
nethercote297effd2004-08-02 15:07:57 +00002288 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002289 */
njn37cea302002-09-30 11:24:00 +00002290 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002291 }
2292
nethercote27fec902004-06-16 21:26:32 +00002293 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002294 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002295 /* Check sanity of the low-level memory manager. Note that bugs
2296 in the client's code can cause this to fail, so we don't do
2297 this check unless specially asked for. And because it's
2298 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002299 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002300 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002301 }
njn37cea302002-09-30 11:24:00 +00002302 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002303}
nethercote71980f02004-01-24 18:18:54 +00002304
2305
2306/*====================================================================*/
2307/*=== main() ===*/
2308/*====================================================================*/
2309
nethercotec314eba2004-07-15 12:59:41 +00002310/*
2311 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002312 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002313 loads the client executable (and the dynamic linker, if necessary)
2314 into the client part, and calls into Valgrind proper.
2315
2316 The code is careful not to allow spurious mappings to appear in the
2317 wrong parts of the address space. In particular, to make sure
2318 dlopen puts things in the right place, it will pad out the forbidden
2319 chunks of address space so that dlopen is forced to put things where
2320 we want them.
2321
2322 The memory map it creates is:
2323
2324 CLIENT_BASE +-------------------------+
2325 | client address space |
2326 : :
2327 : :
2328 | client stack |
2329 client_end +-------------------------+
2330 | redzone |
2331 shadow_base +-------------------------+
2332 | |
nethercote996901a2004-08-03 13:29:09 +00002333 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002334 | (may be 0 sized) |
2335 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002336 valgrind_base +-------------------------+
2337 | kickstart executable |
2338 | valgrind heap vvvvvvvvv| (barely used)
2339 - -
2340 | valgrind .so files |
2341 | and mappings |
2342 - -
2343 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002344 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002345 : kernel :
2346
2347 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2348 VG_(mmap)(), we need to build the segment skip-list, so we know where
2349 we can put things. However, building that structure requires
2350 allocating memory. So we need to a bootstrapping process. It's done
2351 by making VG_(arena_malloc)() have a special static superblock that's
2352 used for the first 1MB's worth of allocations. This is enough to
2353 build the segment skip-list.
2354*/
2355
nethercote31779c72004-07-30 21:50:15 +00002356static int prmap(char *start, char *end, const char *perm, off_t off,
2357 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002358 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2359 start, end, perm, maj, min, ino);
2360 return True;
2361}
2362
nethercote71980f02004-01-24 18:18:54 +00002363int main(int argc, char **argv)
2364{
2365 char **cl_argv;
2366 const char *tool = NULL;
2367 const char *exec = NULL;
2368 char *preload; /* tool-specific LD_PRELOAD .so */
2369 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002370 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002371 struct exeinfo info;
2372 ToolInfo *toolinfo = NULL;
2373 void *tool_dlhandle;
2374 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002375 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002376 UInt * client_auxv;
2377 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002378 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002379 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002380 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002381 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002382 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2383
nethercote71980f02004-01-24 18:18:54 +00002384
2385 //============================================================
2386 // Nb: startup is complex. Prerequisites are shown at every step.
2387 //
2388 // *** Be very careful when messing with the order ***
2389 //============================================================
2390
nethercotef4928da2004-06-15 10:54:40 +00002391 //============================================================
2392 // Command line argument handling order:
2393 // * If --help/--help-debug are present, show usage message
2394 // (if --tool is also present, that includes the tool-specific usage)
2395 // * Then, if --tool is missing, abort with error msg
2396 // * Then, if client is missing, abort with error msg
2397 // * Then, if any cmdline args are bad, abort with error msg
2398 //============================================================
2399
fitzhardingeb50068f2004-02-24 23:42:55 +00002400 // Get the current process datasize rlimit, and set it to zero.
2401 // This prevents any internal uses of brk() from having any effect.
2402 // We remember the old value so we can restore it on exec, so that
2403 // child processes will have a reasonable brk value.
2404 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2405 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2406 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002407
2408 // Get the current process stack rlimit.
2409 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2410
nethercote71980f02004-01-24 18:18:54 +00002411 //--------------------------------------------------------------
2412 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002413 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002414 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002415 {
2416 void* init_sp = argv - 1;
2417 padfile = scan_auxv(init_sp);
2418 }
nethercote71980f02004-01-24 18:18:54 +00002419
2420 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002421 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002422 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002423 }
2424
2425 //--------------------------------------------------------------
2426 // Look for alternative libdir
2427 // p: n/a
2428 //--------------------------------------------------------------
2429 { char *cp = getenv(VALGRINDLIB);
2430 if (cp != NULL)
2431 VG_(libdir) = cp;
2432 }
2433
2434 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002435 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2436 // Pre-process the command line.
2437 // p: n/a
2438 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002439 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002440 pre_process_cmd_line_options(&need_help, &tool, &exec);
2441
2442 //==============================================================
2443 // Nb: once a tool is specified, the tool.so must be loaded even if
2444 // they specified --help or didn't specify a client program.
2445 //==============================================================
2446
2447 //--------------------------------------------------------------
2448 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002449 // p: set-libdir [for VG_(libdir)]
2450 // p: pre_process_cmd_line_options() [for 'tool']
2451 //--------------------------------------------------------------
2452 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2453
2454 //==============================================================
2455 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002456 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002457 //==============================================================
2458
2459 //--------------------------------------------------------------
2460 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002461 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002462 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002463 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002464
2465 //--------------------------------------------------------------
2466 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002467 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2468 // p: layout_remaining_space [so there's space]
2469 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002470 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002471
2472 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002473 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002474 // p: layout_remaining_space() [everything must be mapped in before now]
2475 // p: load_client() [ditto]
2476 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002477 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2478 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002479
2480 //--------------------------------------------------------------
2481 // Set up client's environment
2482 // p: set-libdir [for VG_(libdir)]
2483 // p: load_tool() [for 'preload']
2484 //--------------------------------------------------------------
2485 env = fix_environment(environ, preload);
2486
2487 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002488 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002489 // p: load_client() [for 'info']
2490 // p: fix_environment() [for 'env']
2491 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002492 {
2493 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002494 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2495 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002496 }
nethercote71980f02004-01-24 18:18:54 +00002497
2498 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002499 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002500 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002501 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002502
2503 //==============================================================
2504 // Finished setting up operating environment. Now initialise
2505 // Valgrind. (This is where the old VG_(main)() started.)
2506 //==============================================================
2507
2508 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002509 // atfork
2510 // p: n/a
2511 //--------------------------------------------------------------
2512 VG_(atfork)(NULL, NULL, newpid);
2513 newpid(VG_INVALID_THREADID);
2514
2515 //--------------------------------------------------------------
2516 // setup file descriptors
2517 // p: n/a
2518 //--------------------------------------------------------------
2519 setup_file_descriptors();
2520
2521 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002522 // Read /proc/self/maps into a buffer
2523 // p: all memory layout, environment setup [so memory maps are right]
2524 //--------------------------------------------------------------
2525 VG_(read_procselfmaps)();
2526
2527 //--------------------------------------------------------------
2528 // Build segment map (Valgrind segments only)
2529 // p: read proc/self/maps
njnd2252832004-11-26 10:53:33 +00002530 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002531 //--------------------------------------------------------------
2532 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2533
2534 //==============================================================
2535 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2536 //==============================================================
2537
2538 //--------------------------------------------------------------
2539 // Init tool: pre_clo_init, process cmd line, post_clo_init
2540 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2541 // p: load_tool() [for 'tool']
2542 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2543 // p: parse_procselfmaps [so VG segments are setup so tool can
2544 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002545 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002546 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002547 VG_(tool_init_dlsym)(tool_dlhandle);
2548 VG_(sanity_check_needs)();
2549
nethercotef4928da2004-06-15 10:54:40 +00002550 // If --tool and --help/--help-debug was given, now give the core+tool
2551 // help message
nethercotef4928da2004-06-15 10:54:40 +00002552 if (need_help) {
2553 usage(/*--help-debug?*/2 == need_help);
2554 }
nethercotec314eba2004-07-15 12:59:41 +00002555 process_cmd_line_options(client_auxv, tool);
2556
njn26f02512004-11-22 18:33:15 +00002557 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002558
2559 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002560 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002561 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002562 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002563 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002564 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002565 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002566 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002567
njnca0518d2004-11-26 19:34:36 +00002568#ifdef __i386__
nethercotec314eba2004-07-15 12:59:41 +00002569 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002570 // Protect client trampoline page (which is also sysinfo stuff)
2571 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002572 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002573 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2574 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002575#endif
nethercotec314eba2004-07-15 12:59:41 +00002576
2577 //==============================================================
2578 // Can use VG_(map)() after segments set up
2579 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002580
2581 //--------------------------------------------------------------
2582 // Allow GDB attach
2583 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2584 //--------------------------------------------------------------
2585 /* Hook to delay things long enough so we can get the pid and
2586 attach GDB in another shell. */
2587 if (VG_(clo_wait_for_gdb)) {
2588 VG_(printf)("pid=%d\n", VG_(getpid)());
2589 /* do "jump *$eip" to skip this in gdb */
njnca6fef02004-11-29 16:49:18 +00002590 VG_(do_syscall0)(__NR_pause);
nethercote71980f02004-01-24 18:18:54 +00002591 }
2592
2593 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002594 // Search for file descriptors that are inherited from our parent
2595 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2596 //--------------------------------------------------------------
2597 if (VG_(clo_track_fds))
2598 VG_(init_preopened_fds)();
2599
2600 //--------------------------------------------------------------
2601 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002602 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2603 //--------------------------------------------------------------
2604 VG_(scheduler_init)();
2605
2606 //--------------------------------------------------------------
sewardj2a99cf62004-11-24 10:44:19 +00002607 // Set up state of thread 1
2608 // p: {pre,post}_clo_init() [for tool helper registration]
2609 // load_client() [for 'client_eip']
2610 // setup_client_stack() [for 'sp_at_startup']
2611 // setup_scheduler() [for the rest of state 1 stuff]
2612 //--------------------------------------------------------------
2613 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002614
2615 // Tell the tool that we just wrote to the registers.
2616 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2617 sizeof(VexGuestArchState));
2618
2619 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002620 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002621
2622 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002623 // Set up the ProxyLWP machinery
2624 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002625 //--------------------------------------------------------------
2626 VG_(proxy_init)();
2627
2628 //--------------------------------------------------------------
2629 // Initialise the signal handling subsystem
2630 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2631 // p: VG_(proxy_init)() [else breaks...]
2632 //--------------------------------------------------------------
2633 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2634 VG_(sigstartup_actions)();
2635
2636 //--------------------------------------------------------------
2637 // Perhaps we're profiling Valgrind?
2638 // p: process_cmd_line_options() [for VG_(clo_profile)]
2639 // p: others?
2640 //
2641 // XXX: this seems to be broken? It always says the tool wasn't built
2642 // for profiling; vg_profile.c's functions don't seem to be overriding
2643 // vg_dummy_profile.c's?
2644 //
2645 // XXX: want this as early as possible. Looking for --profile
2646 // in pre_process_cmd_line_options() could get it earlier.
2647 //--------------------------------------------------------------
2648 if (VG_(clo_profile))
2649 VGP_(init_profiling)();
2650
2651 VGP_PUSHCC(VgpStartup);
2652
2653 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002654 // Read suppression file
2655 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2656 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002657 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002658 VG_(load_suppressions)();
2659
2660 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002661 // Initialise translation table and translation cache
2662 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2663 // aren't identified as part of the client, which would waste
2664 // > 20M of virtual address space.]
2665 //--------------------------------------------------------------
2666 VG_(init_tt_tc)();
2667
2668 //--------------------------------------------------------------
2669 // Read debug info to find glibc entry points to intercept
2670 // p: parse_procselfmaps? [XXX for debug info?]
2671 // p: init_tt_tc? [XXX ???]
2672 //--------------------------------------------------------------
2673 VG_(setup_code_redirect_table)();
2674
2675 //--------------------------------------------------------------
2676 // Verbosity message
2677 // p: end_rdtsc_calibration [so startup message is printed first]
2678 //--------------------------------------------------------------
2679 if (VG_(clo_verbosity) == 1)
2680 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2681 if (VG_(clo_verbosity) > 0)
2682 VG_(message)(Vg_UserMsg, "");
2683
2684 //--------------------------------------------------------------
2685 // Setup pointercheck
2686 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2687 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002688 if (VG_(clo_pointercheck))
2689 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002690
nethercote71980f02004-01-24 18:18:54 +00002691 //--------------------------------------------------------------
2692 // Run!
2693 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002694 VGP_POPCC(VgpStartup);
2695 VGP_PUSHCC(VgpSched);
2696
nethercote238a3c32004-08-09 13:13:31 +00002697 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002698
nethercote238a3c32004-08-09 13:13:31 +00002699 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002700
2701
2702 //--------------------------------------------------------------
2703 // Finalisation: cleanup, messages, etc. Order no so important, only
2704 // affects what order the messages come.
2705 //--------------------------------------------------------------
2706 if (VG_(clo_verbosity) > 0)
2707 VG_(message)(Vg_UserMsg, "");
2708
2709 if (src == VgSrc_Deadlock) {
2710 VG_(message)(Vg_UserMsg,
2711 "Warning: pthread scheduler exited due to deadlock");
2712 }
2713
2714 /* Print out file descriptor summary and stats. */
2715 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002716 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002717
njn95ec8702004-11-22 16:46:13 +00002718 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002719 VG_(show_all_errors)();
2720
njn26f02512004-11-22 18:33:15 +00002721 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002722
nethercote885dd912004-08-03 23:14:00 +00002723 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002724
2725 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002726 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002727
nethercote71980f02004-01-24 18:18:54 +00002728 if (VG_(clo_profile))
2729 VGP_(done_profiling)();
2730
nethercote71980f02004-01-24 18:18:54 +00002731 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2732 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002733 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2734 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002735 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2736
sewardj8b635a42004-11-22 19:01:47 +00002737 /* Print Vex storage stats */
njn383ae5e2004-11-23 17:10:15 +00002738 LibVEX_ClearTemporary( False/*show stats*/ );
sewardj8b635a42004-11-22 19:01:47 +00002739
nethercote71980f02004-01-24 18:18:54 +00002740 //--------------------------------------------------------------
2741 // Exit, according to the scheduler's return code
2742 //--------------------------------------------------------------
2743 switch (src) {
2744 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002745 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002746 VG_(proxy_shutdown)();
2747
2748 /* The thread's %EBX at the time it did __NR_exit() will hold
2749 the arg to __NR_exit(), so we just do __NR_exit() with
2750 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002751 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002752 /* NOT ALIVE HERE! */
2753 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2754 break; /* what the hell :) */
2755
2756 case VgSrc_Deadlock:
2757 /* Just exit now. No point in continuing. */
2758 VG_(proxy_shutdown)();
2759 VG_(exit)(0);
2760 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2761 break;
2762
nethercote71980f02004-01-24 18:18:54 +00002763 case VgSrc_FatalSig:
2764 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002765 vg_assert(fatal_sigNo != -1);
2766 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002767 VG_(core_panic)("main(): signal was supposed to be fatal");
2768 break;
2769
2770 default:
2771 VG_(core_panic)("main(): unexpected scheduler return code");
2772 }
2773
2774 abort();
2775}
2776
2777
sewardjde4a1d02002-03-22 01:27:54 +00002778/*--------------------------------------------------------------------*/
2779/*--- end vg_main.c ---*/
2780/*--------------------------------------------------------------------*/