blob: ad4341bc0b16707467d2cc7aeba9de3bc51fee78 [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/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
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
fitzhardinge98abfc72003-12-16 02:05:15 +0000112/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000113static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000114
115/* client executable */
116Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000117
118/* Path to library directory */
119const Char *VG_(libdir) = VG_LIBDIR;
120
121/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000122static Int vg_argc;
123static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
jsgf855d93d2003-10-13 22:26:55 +0000125/* PID of the main thread */
126Int VG_(main_pid);
127
128/* PGRP of process */
129Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000130
thughesad1c9562004-06-26 11:27:52 +0000131/* Application-visible file descriptor limits */
132Int VG_(fd_soft_limit) = -1;
133Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000134
nethercote4ad74312004-10-26 09:59:49 +0000135/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000136 envp[] as extracted from the client's stack at startup-time. */
137Int VG_(client_argc);
138Char** VG_(client_argv);
139Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000140
njn16de5572004-11-27 14:27:21 +0000141// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000142OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000143
sewardjde4a1d02002-03-22 01:27:54 +0000144/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000145 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000146 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000147
nethercote71980f02004-01-24 18:18:54 +0000148/* Counts downwards in VG_(run_innerloop). */
149UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000150
151/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000152ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000153
nethercote71980f02004-01-24 18:18:54 +0000154/* Tell the logging mechanism whether we are logging to a file
155 descriptor or a socket descriptor. */
156Bool VG_(logging_to_filedes) = True;
157
sewardj73cf3bc2002-11-03 03:20:15 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159/*====================================================================*/
160/*=== Counters, for profiling purposes only ===*/
161/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000162
sewardjde4a1d02002-03-22 01:27:54 +0000163/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000164static UInt sanity_fast_count = 0;
165static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000166
nethercote3a42fb82004-08-03 18:08:50 +0000167static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000168{
nethercote3a42fb82004-08-03 18:08:50 +0000169 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000170 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000171 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000172 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000173
nethercote3a42fb82004-08-03 18:08:50 +0000174 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000175 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000176
nethercote71980f02004-01-24 18:18:54 +0000177 VG_(message)(Vg_DebugMsg,
178 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000179 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000182 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000183 VG_(message)(Vg_DebugMsg, "");
184 VG_(message)(Vg_DebugMsg,
185 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000186 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000187 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000188 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000189 VG_(message)(Vg_DebugMsg,
190 "------ Valgrind's ExeContext management stats follow ------" );
191 VG_(print_ExeContext_stats)();
192 }
nethercote71980f02004-01-24 18:18:54 +0000193}
194
195
196/*====================================================================*/
197/*=== Miscellaneous global functions ===*/
198/*====================================================================*/
199
nethercotecf97ffb2004-09-09 13:40:31 +0000200static Int ptrace_setregs(Int pid, ThreadId tid)
201{
sewardj2a99cf62004-11-24 10:44:19 +0000202 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000203}
204
nethercote04d0fbc2004-01-26 16:48:06 +0000205/* Start debugger and get it to attach to this process. Called if the
206 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000207 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000208 meaningfully get the debugger to continue the program, though; to
209 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000210void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000211{
212 Int pid;
213
214 if ((pid = fork()) == 0) {
215 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000216 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000217
218 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000219 Int status;
220 Int res;
221
nethercote71980f02004-01-24 18:18:54 +0000222 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
223 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000224 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000225 kill(pid, SIGSTOP) == 0 &&
226 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000227 Char pidbuf[15];
228 Char file[30];
229 Char buf[100];
230 Char *bufptr;
231 Char *cmdptr;
232
233 VG_(sprintf)(pidbuf, "%d", pid);
234 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
235
236 bufptr = buf;
237 cmdptr = VG_(clo_db_command);
238
239 while (*cmdptr) {
240 switch (*cmdptr) {
241 case '%':
242 switch (*++cmdptr) {
243 case 'f':
244 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
245 bufptr += VG_(strlen)(file);
246 cmdptr++;
247 break;
248 case 'p':
249 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
250 bufptr += VG_(strlen)(pidbuf);
251 cmdptr++;
252 break;
253 default:
254 *bufptr++ = *cmdptr++;
255 break;
256 }
257 break;
258 default:
259 *bufptr++ = *cmdptr++;
260 break;
261 }
262 }
263
264 *bufptr++ = '\0';
265
266 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000267 res = VG_(system)(buf);
268 if (res == 0) {
269 VG_(message)(Vg_UserMsg, "");
270 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000271 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000272 } else {
273 VG_(message)(Vg_UserMsg, "Apparently failed!");
274 VG_(message)(Vg_UserMsg, "");
275 }
276 }
277
nethercote73b526f2004-10-31 18:48:21 +0000278 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000279 VG_(waitpid)(pid, &status, 0);
280 }
281}
282
283
284/* Print some helpful-ish text about unimplemented things, and give
285 up. */
286void VG_(unimplemented) ( Char* msg )
287{
288 VG_(message)(Vg_UserMsg, "");
289 VG_(message)(Vg_UserMsg,
290 "Valgrind detected that your program requires");
291 VG_(message)(Vg_UserMsg,
292 "the following unimplemented functionality:");
293 VG_(message)(Vg_UserMsg, " %s", msg);
294 VG_(message)(Vg_UserMsg,
295 "This may be because the functionality is hard to implement,");
296 VG_(message)(Vg_UserMsg,
297 "or because no reasonable program would behave this way,");
298 VG_(message)(Vg_UserMsg,
299 "or because nobody has yet needed it. In any case, let us know at");
300 VG_(message)(Vg_UserMsg,
301 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
302 VG_(message)(Vg_UserMsg,
303 "");
304 VG_(message)(Vg_UserMsg,
305 "Valgrind has to exit now. Sorry. Bye!");
306 VG_(message)(Vg_UserMsg,
307 "");
308 VG_(pp_sched_status)();
309 VG_(exit)(1);
310}
311
sewardj2a99cf62004-11-24 10:44:19 +0000312/* Get the simulated stack pointer */
313Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000314{
njncf45fd42004-11-24 16:30:22 +0000315 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000316}
317
njnea4b28c2004-11-30 16:04:58 +0000318/* Debugging thing .. can be called from assembly with OYNK macro. */
319void VG_(oynk) ( Int n )
320{
321 OINK(n);
322}
323
nethercote71980f02004-01-24 18:18:54 +0000324/* Initialize the PID and PGRP of scheduler LWP; this is also called
325 in any new children after fork. */
326static void newpid(ThreadId unused)
327{
328 /* PID of scheduler LWP */
329 VG_(main_pid) = VG_(getpid)();
330 VG_(main_pgrp) = VG_(getpgrp)();
331}
332
333/*====================================================================*/
334/*=== Check we were launched by stage 1 ===*/
335/*====================================================================*/
336
337/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000338int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000339{
nethercoteebf1d862004-11-01 18:22:05 +0000340 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000341 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000342
343 for (; auxv->a_type != AT_NULL; auxv++)
344 switch(auxv->a_type) {
345 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000346 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000347 found |= 1;
348 break;
349
350 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000351 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 2;
353 break;
nethercote7f390022004-10-25 17:18:24 +0000354
355 case AT_PHDR:
356 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
357 break;
nethercote71980f02004-01-24 18:18:54 +0000358 }
359
nethercote361a14e2004-07-26 11:11:56 +0000360 if ( found != (1|2) ) {
361 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000362 exit(127);
363 }
nethercote31779c72004-07-30 21:50:15 +0000364 vg_assert(padfile >= 0);
365 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000366}
367
368
369/*====================================================================*/
370/*=== Address space determination ===*/
371/*====================================================================*/
372
nethercote7f390022004-10-25 17:18:24 +0000373extern char _start[];
374
nethercote31779c72004-07-30 21:50:15 +0000375static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000376{
nethercotea3c3cf22004-11-01 18:38:00 +0000377 Int ires;
378 void* vres;
379 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000380
nethercote7f390022004-10-25 17:18:24 +0000381 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
382 // this is a workable approximation
383 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000384 VG_(valgrind_base) = PGROUNDDN(&_start);
385 }
386
nethercote820bd8c2004-09-07 23:04:49 +0000387 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000388
nethercote31779c72004-07-30 21:50:15 +0000389 // This gives the client the largest possible address space while
390 // taking into account the tool's shadow needs.
391 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000392 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000393 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000394 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000395 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000396 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000397 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000398
nethercote31779c72004-07-30 21:50:15 +0000399 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000400 VG_(shadow_end) = VG_(valgrind_base);
401 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000402
nethercotee2097312004-06-27 12:29:56 +0000403#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
404
nethercote71980f02004-01-24 18:18:54 +0000405 if (0)
nethercotee2097312004-06-27 12:29:56 +0000406 VG_(printf)(
407 "client_base %8x (%dMB)\n"
408 "client_mapbase %8x (%dMB)\n"
409 "client_end %8x (%dMB)\n"
410 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000411 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000412 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000413 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000414 VG_(client_base), SEGSIZE(client_base, client_mapbase),
415 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
416 VG_(client_end), SEGSIZE(client_end, shadow_base),
417 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000418 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000419 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
420 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000421 );
422
423#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000424
425 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000426 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000427 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000428 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000431 ires = munmap((void*)VG_(client_base), client_size);
432 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000433
434 // Map shadow memory.
435 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000436 if (shadow_size != 0) {
437 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000438 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000439 if ((void*)-1 == vres) {
440 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000441 "valgrind: Could not allocate address space (%p bytes)\n"
442 "valgrind: for shadow memory\n"
443 "valgrind: Possible causes:\n"
444 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
445 "valgrind: needs at least 1.5GB swap space.\n"
446 "valgrind: - Or, your virtual memory size may be limited (check\n"
447 "valgrind: with 'ulimit -v').\n"
448 "valgrind: - Or, your system may use a kernel that provides only a\n"
449 "valgrind: too-small (eg. 2GB) user address space.\n"
450 , (void*)shadow_size
451 );
nethercoted4722622004-08-30 19:36:42 +0000452 exit(1);
453 }
nethercotee567e702004-07-10 17:49:17 +0000454 }
nethercote71980f02004-01-24 18:18:54 +0000455}
456
457/*====================================================================*/
458/*=== Command line setup ===*/
459/*====================================================================*/
460
461/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
462static char* get_file_clo(char* dir)
463{
464# define FLEN 512
465 Int fd, n;
466 struct stat s1;
467 char* f_clo = NULL;
468 char filename[FLEN];
469
470 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
471 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
472 if ( fd > 0 ) {
473 if ( 0 == fstat(fd, &s1) ) {
474 f_clo = malloc(s1.st_size+1);
475 vg_assert(f_clo);
476 n = read(fd, f_clo, s1.st_size);
477 if (n == -1) n = 0;
478 f_clo[n] = '\0';
479 }
480 close(fd);
481 }
482 return f_clo;
483# undef FLEN
484}
485
nethercotee2097312004-06-27 12:29:56 +0000486#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
487
nethercote71980f02004-01-24 18:18:54 +0000488static Int count_args(char* s)
489{
490 Int n = 0;
491 if (s) {
492 char* cp = s;
493 while (True) {
494 // We have alternating sequences: blanks, non-blanks, blanks...
495 // count the non-blanks sequences.
496 while ( ISSPACE(*cp) ) cp++;
497 if ( !*cp ) break;
498 n++;
499 while ( !ISSPACE(*cp) && *cp ) cp++;
500 }
501 }
502 return n;
503}
504
505/* add args out of environment, skipping multiple spaces and -- args */
506static char** copy_args( char* s, char** to )
507{
508 if (s) {
509 char* cp = s;
510 while (True) {
511 // We have alternating sequences: blanks, non-blanks, blanks...
512 // copy the non-blanks sequences, and add terminating '\0'
513 while ( ISSPACE(*cp) ) cp++;
514 if ( !*cp ) break;
515 *to++ = cp;
516 while ( !ISSPACE(*cp) && *cp ) cp++;
517 if ( *cp ) *cp++ = '\0'; // terminate if necessary
518 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
519 }
520 }
521 return to;
522}
523
nethercotee2097312004-06-27 12:29:56 +0000524#undef ISSPACE
525
nethercote71980f02004-01-24 18:18:54 +0000526// Augment command line with arguments from environment and .valgrindrc
527// files.
528static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
529{
nethercotef6a1d502004-08-09 12:21:57 +0000530 int vg_argc0 = *vg_argc_inout;
531 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000532
533 char* env_clo = getenv(VALGRINDOPTS);
534 char* f1_clo = get_file_clo( getenv("HOME") );
535 char* f2_clo = get_file_clo(".");
536
537 /* copy any extra args from file or environment, if present */
538 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
539 /* ' ' separated extra options */
540 char **from;
541 char **to;
thughescaca0022004-09-13 10:20:34 +0000542 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
543
544 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
545
nethercote71980f02004-01-24 18:18:54 +0000546 env_arg_count = count_args(env_clo);
547 f1_arg_count = count_args(f1_clo);
548 f2_arg_count = count_args(f2_clo);
549
550 if (0)
551 printf("extra-argc=%d %d %d\n",
552 env_arg_count, f1_arg_count, f2_arg_count);
553
554 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000555 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000556 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000557 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000558 vg_assert(vg_argv0);
559 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000560
561 /* copy argv[0] */
562 *to++ = *from++;
563
564 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
565 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
566 * to override less local ones. */
567 to = copy_args(f1_clo, to);
568 to = copy_args(env_clo, to);
569 to = copy_args(f2_clo, to);
570
571 /* copy original arguments, stopping at command or -- */
572 while (*from) {
573 if (**from != '-')
574 break;
575 if (VG_STREQ(*from, "--")) {
576 from++; /* skip -- */
577 break;
578 }
579 *to++ = *from++;
580 }
581
582 /* add -- */
583 *to++ = "--";
584
nethercotef6a1d502004-08-09 12:21:57 +0000585 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000586
587 /* copy rest of original command line, then NULL */
588 while (*from) *to++ = *from++;
589 *to = NULL;
590 }
591
nethercotef6a1d502004-08-09 12:21:57 +0000592 *vg_argc_inout = vg_argc0;
593 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000594}
595
nethercotef6a1d502004-08-09 12:21:57 +0000596#define VG_CLO_SEP '\01'
597
nethercote71980f02004-01-24 18:18:54 +0000598static void get_command_line( int argc, char** argv,
599 Int* vg_argc_out, Char*** vg_argv_out,
600 char*** cl_argv_out )
601{
nethercotef6a1d502004-08-09 12:21:57 +0000602 int vg_argc0;
603 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000604 char** cl_argv;
605 char* env_clo = getenv(VALGRINDCLO);
606
607 if (env_clo != NULL && *env_clo != '\0') {
608 char *cp;
609 char **cpp;
610
nethercotef6a1d502004-08-09 12:21:57 +0000611 /* OK, VALGRINDCLO is set, which means we must be a child of another
612 Valgrind process using --trace-children, so we're getting all our
613 arguments from VALGRINDCLO, and the entire command line belongs to
614 the client (including argv[0]) */
615 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000616 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000617 if (*cp == VG_CLO_SEP)
618 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000619
nethercotef6a1d502004-08-09 12:21:57 +0000620 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
621 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000622
nethercotef6a1d502004-08-09 12:21:57 +0000623 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000624
625 *cpp++ = "valgrind"; /* nominal argv[0] */
626 *cpp++ = env_clo;
627
nethercotef6a1d502004-08-09 12:21:57 +0000628 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000629 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000630 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000631 *cp++ = '\0'; /* chop it up in place */
632 *cpp++ = cp;
633 }
634 }
635 *cpp = NULL;
636 cl_argv = argv;
637
638 } else {
639 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000640 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000641
nethercotef6a1d502004-08-09 12:21:57 +0000642 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
643 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000644 break;
nethercotef6a1d502004-08-09 12:21:57 +0000645 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
646 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000647 break;
648 }
649 }
nethercotef6a1d502004-08-09 12:21:57 +0000650 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000651
652 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000653 Note we don't do this if getting args from VALGRINDCLO, as
654 those extra args will already be present in VALGRINDCLO. */
655 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000656 }
657
658 if (0) {
659 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000660 for (i = 0; i < vg_argc0; i++)
661 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000662 }
663
nethercotef6a1d502004-08-09 12:21:57 +0000664 *vg_argc_out = vg_argc0;
665 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000666 *cl_argv_out = cl_argv;
667}
668
669
670/*====================================================================*/
671/*=== Environment and stack setup ===*/
672/*====================================================================*/
673
674/* Scan a colon-separated list, and call a function on each element.
675 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000676 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000677 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000678
679 This routine will return True if (*func) returns True and False if
680 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000681*/
thughes4ad52d02004-06-27 17:37:21 +0000682static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000683{
684 char *cp, *entry;
685 int end;
686
687 if (colsep == NULL ||
688 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000689 return False;
nethercote71980f02004-01-24 18:18:54 +0000690
691 entry = cp = colsep;
692
693 do {
694 end = (*cp == '\0');
695
696 if (*cp == ':' || *cp == '\0') {
697 char save = *cp;
698
699 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000700 if ((*func)(entry)) {
701 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000702 return True;
thughes21942d92004-07-12 09:35:37 +0000703 }
nethercote71980f02004-01-24 18:18:54 +0000704 *cp = save;
705 entry = cp+1;
706 }
707 cp++;
708 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000709
710 return False;
711}
712
713static Bool contains(const char *p) {
714 if (VG_STREQ(p, VG_(libdir))) {
715 return True;
716 }
717 return False;
nethercote71980f02004-01-24 18:18:54 +0000718}
719
720/* Prepare the client's environment. This is basically a copy of our
721 environment, except:
722 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
723 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
724
725 If any of these is missing, then it is added.
726
727 Yummy. String hacking in C.
728
729 If this needs to handle any more variables it should be hacked
730 into something table driven.
731 */
732static char **fix_environment(char **origenv, const char *preload)
733{
734 static const char inject_so[] = "vg_inject.so";
735 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
736 static const char ld_preload[] = "LD_PRELOAD=";
737 static const char valgrind_clo[] = VALGRINDCLO "=";
738 static const int ld_library_path_len = sizeof(ld_library_path)-1;
739 static const int ld_preload_len = sizeof(ld_preload)-1;
740 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
741 int ld_preload_done = 0;
742 int ld_library_path_done = 0;
743 char *inject_path;
744 int inject_path_len;
745 int vgliblen = strlen(VG_(libdir));
746 char **cpp;
747 char **ret;
748 int envc;
749 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
750
751 /* Find the vg_inject.so; also make room for the tool preload
752 library */
753 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
754 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000755 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000756
757 if (preload)
758 snprintf(inject_path, inject_path_len, "%s/%s:%s",
759 VG_(libdir), inject_so, preload);
760 else
761 snprintf(inject_path, inject_path_len, "%s/%s",
762 VG_(libdir), inject_so);
763
764 /* Count the original size of the env */
765 envc = 0; /* trailing NULL */
766 for (cpp = origenv; cpp && *cpp; cpp++)
767 envc++;
768
769 /* Allocate a new space */
770 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000771 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000772
773 /* copy it over */
774 for (cpp = ret; *origenv; )
775 *cpp++ = *origenv++;
776 *cpp = NULL;
777
778 vg_assert(envc == (cpp - ret));
779
780 /* Walk over the new environment, mashing as we go */
781 for (cpp = ret; cpp && *cpp; cpp++) {
782 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000783 /* If the LD_LIBRARY_PATH already contains libdir, then don't
784 bother adding it again, even if it isn't the first (it
785 seems that the Java runtime will keep reexecing itself
786 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000787 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000788 int len = strlen(*cpp) + vgliblen*2 + 16;
789 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000790 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000791
792 snprintf(cp, len, "%s%s:%s",
793 ld_library_path, VG_(libdir),
794 (*cpp)+ld_library_path_len);
795
796 *cpp = cp;
797 }
798
799 ld_library_path_done = 1;
800 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
801 int len = strlen(*cpp) + inject_path_len;
802 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000803 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000804
805 snprintf(cp, len, "%s%s:%s",
806 ld_preload, inject_path, (*cpp)+ld_preload_len);
807
808 *cpp = cp;
809
810 ld_preload_done = 1;
811 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
812 *cpp = "";
813 }
814 }
815
816 /* Add the missing bits */
817
818 if (!ld_library_path_done) {
819 int len = ld_library_path_len + vgliblen*2 + 16;
820 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000821 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000822
823 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
824
825 ret[envc++] = cp;
826 }
827
828 if (!ld_preload_done) {
829 int len = ld_preload_len + inject_path_len;
830 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000831 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000832
833 snprintf(cp, len, "%s%s",
834 ld_preload, inject_path);
835
836 ret[envc++] = cp;
837 }
838
839 ret[envc] = NULL;
840
841 return ret;
842}
843
844extern char **environ; /* our environment */
845//#include <error.h>
846
847/* Add a string onto the string table, and return its address */
848static char *copy_str(char **tab, const char *str)
849{
850 char *cp = *tab;
851 char *orig = cp;
852
853 while(*str)
854 *cp++ = *str++;
855 *cp++ = '\0';
856
857 if (0)
nethercote545fe672004-11-01 16:52:43 +0000858 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000859
860 *tab = cp;
861
862 return orig;
863}
864
865/*
866 This sets up the client's initial stack, containing the args,
867 environment and aux vector.
868
869 The format of the stack is:
870
871 higher address +-----------------+
872 | Trampoline code |
873 +-----------------+
874 | |
875 : string table :
876 | |
877 +-----------------+
878 | AT_NULL |
879 - -
880 | auxv |
881 +-----------------+
882 | NULL |
883 - -
884 | envp |
885 +-----------------+
886 | NULL |
887 - -
888 | argv |
889 +-----------------+
890 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000891 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000892 | undefined |
893 : :
894 */
nethercotec25c4492004-10-18 11:52:17 +0000895static Addr setup_client_stack(void* init_sp,
896 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000897 const struct exeinfo *info,
898 UInt** client_auxv)
899{
nethercotee567e702004-07-10 17:49:17 +0000900 void* res;
nethercote71980f02004-01-24 18:18:54 +0000901 char **cpp;
902 char *strtab; /* string table */
903 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000904 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000905 struct ume_auxv *auxv;
906 const struct ume_auxv *orig_auxv;
907 const struct ume_auxv *cauxv;
908 unsigned stringsize; /* total size of strings in bytes */
909 unsigned auxsize; /* total size of auxv in bytes */
910 int argc; /* total argc */
911 int envc; /* total number of env vars */
912 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000913 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000914
915 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000916 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000917
918 /* ==================== compute sizes ==================== */
919
920 /* first of all, work out how big the client stack will be */
921 stringsize = 0;
922
923 /* paste on the extra args if the loader needs them (ie, the #!
924 interpreter and its argument) */
925 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000926 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000927 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000928 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000929 }
nethercoted6a56872004-07-26 15:32:47 +0000930 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000931 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000932 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000933 }
934
935 /* now scan the args we're given... */
936 for (cpp = orig_argv; *cpp; cpp++) {
937 argc++;
938 stringsize += strlen(*cpp) + 1;
939 }
940
941 /* ...and the environment */
942 envc = 0;
943 for (cpp = orig_envp; cpp && *cpp; cpp++) {
944 envc++;
945 stringsize += strlen(*cpp) + 1;
946 }
947
948 /* now, how big is the auxv? */
949 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
950 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
951 if (cauxv->a_type == AT_PLATFORM)
952 stringsize += strlen(cauxv->u.a_ptr) + 1;
953 auxsize += sizeof(*cauxv);
954 }
955
956 /* OK, now we know how big the client stack is */
957 stacksize =
958 sizeof(int) + /* argc */
959 sizeof(char **)*argc + /* argv */
960 sizeof(char **) + /* terminal NULL */
961 sizeof(char **)*envc + /* envp */
962 sizeof(char **) + /* terminal NULL */
963 auxsize + /* auxv */
964 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000965 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000966
nethercotef84f6952004-07-15 14:58:33 +0000967 // decide where stack goes!
968 VG_(clstk_end) = VG_(client_end);
969
nethercote73b526f2004-10-31 18:48:21 +0000970 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000971
nethercote71980f02004-01-24 18:18:54 +0000972 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000973 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000974 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
975
nethercote71980f02004-01-24 18:18:54 +0000976 /* base of the string table (aligned) */
977 stringbase = strtab = (char *)(VG_(client_trampoline_code) - ROUNDUP(stringsize, sizeof(int)));
978
979 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000980
nethercote5ee67ca2004-06-22 14:00:09 +0000981 if (0)
982 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000983 "clstk_base %p\n"
984 "clstk_end %p\n",
985 stringsize, auxsize, stacksize,
986 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000987
988
nethercote71980f02004-01-24 18:18:54 +0000989 /* ==================== allocate space ==================== */
990
991 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000992 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000993 PROT_READ | PROT_WRITE | PROT_EXEC,
994 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
995 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000996
997 /* ==================== copy client stack ==================== */
998
nethercotea3c3cf22004-11-01 18:38:00 +0000999 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +00001000
1001 /* --- argc --- */
1002 *ptr++ = argc; /* client argc */
1003
1004 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001005 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001006 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001007 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001008 }
nethercoted6a56872004-07-26 15:32:47 +00001009 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001010 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001011 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001012 }
1013 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001014 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001015 }
1016 *ptr++ = 0;
1017
1018 /* --- envp --- */
1019 VG_(client_envp) = (Char **)ptr;
1020 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001021 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001022 *ptr++ = 0;
1023
1024 /* --- auxv --- */
1025 auxv = (struct ume_auxv *)ptr;
1026 *client_auxv = (UInt *)auxv;
1027
1028 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1029 /* copy the entry... */
1030 *auxv = *orig_auxv;
1031
1032 /* ...and fix up the copy */
1033 switch(auxv->a_type) {
1034 case AT_PHDR:
1035 if (info->phdr == 0)
1036 auxv->a_type = AT_IGNORE;
1037 else
1038 auxv->u.a_val = info->phdr;
1039 break;
1040
1041 case AT_PHNUM:
1042 if (info->phdr == 0)
1043 auxv->a_type = AT_IGNORE;
1044 else
1045 auxv->u.a_val = info->phnum;
1046 break;
1047
1048 case AT_BASE:
1049 if (info->interp_base == 0)
1050 auxv->a_type = AT_IGNORE;
1051 else
1052 auxv->u.a_val = info->interp_base;
1053 break;
1054
1055 case AT_PLATFORM: /* points to a platform description string */
1056 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1057 break;
1058
1059 case AT_ENTRY:
1060 auxv->u.a_val = info->entry;
1061 break;
1062
1063 case AT_IGNORE:
1064 case AT_EXECFD:
1065 case AT_PHENT:
1066 case AT_PAGESZ:
1067 case AT_FLAGS:
1068 case AT_NOTELF:
1069 case AT_UID:
1070 case AT_EUID:
1071 case AT_GID:
1072 case AT_EGID:
1073 case AT_CLKTCK:
1074 case AT_HWCAP:
1075 case AT_FPUCW:
1076 case AT_DCACHEBSIZE:
1077 case AT_ICACHEBSIZE:
1078 case AT_UCACHEBSIZE:
1079 /* All these are pointerless, so we don't need to do anything
1080 about them. */
1081 break;
1082
1083 case AT_SECURE:
1084 /* If this is 1, then it means that this program is running
1085 suid, and therefore the dynamic linker should be careful
1086 about LD_PRELOAD, etc. However, since stage1 (the thing
1087 the kernel actually execve's) should never be SUID, and we
1088 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1089 set AT_SECURE to 0. */
1090 auxv->u.a_val = 0;
1091 break;
1092
1093 case AT_SYSINFO:
1094 /* Leave this unmolested for now, but we'll update it later
1095 when we set up the client trampoline code page */
1096 break;
1097
1098 case AT_SYSINFO_EHDR:
1099 /* Trash this, because we don't reproduce it */
1100 auxv->a_type = AT_IGNORE;
1101 break;
1102
1103 default:
1104 /* stomp out anything we don't know about */
1105 if (0)
nethercote545fe672004-11-01 16:52:43 +00001106 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001107 auxv->a_type = AT_IGNORE;
1108 break;
1109
1110 }
1111 }
1112 *auxv = *orig_auxv;
1113 vg_assert(auxv->a_type == AT_NULL);
1114
njnc6168192004-11-29 13:54:10 +00001115// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1116// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
njnca0518d2004-11-26 19:34:36 +00001117#ifdef __x86__
nethercotef84f6952004-07-15 14:58:33 +00001118 /* --- trampoline page --- */
1119 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1120 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001121#endif
nethercotef84f6952004-07-15 14:58:33 +00001122
nethercote71980f02004-01-24 18:18:54 +00001123 vg_assert((strtab-stringbase) == stringsize);
1124
nethercote5ee67ca2004-06-22 14:00:09 +00001125 /* We know the initial ESP is pointing at argc/argv */
1126 VG_(client_argc) = *(Int*)cl_esp;
1127 VG_(client_argv) = (Char**)(cl_esp + sizeof(Int));
1128
nethercote71980f02004-01-24 18:18:54 +00001129 return cl_esp;
1130}
1131
1132/*====================================================================*/
1133/*=== Find executable ===*/
1134/*====================================================================*/
1135
thughes4ad52d02004-06-27 17:37:21 +00001136static const char* executable_name;
1137
1138static Bool match_executable(const char *entry) {
1139 char buf[strlen(entry) + strlen(executable_name) + 2];
1140
1141 /* empty PATH element means . */
1142 if (*entry == '\0')
1143 entry = ".";
1144
1145 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1146
1147 if (access(buf, R_OK|X_OK) == 0) {
1148 executable_name = strdup(buf);
1149 vg_assert(NULL != executable_name);
1150 return True;
1151 }
1152 return False;
1153}
1154
nethercote71980f02004-01-24 18:18:54 +00001155static const char* find_executable(const char* exec)
1156{
1157 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001158 executable_name = exec;
1159 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001160 /* no '/' - we need to search the path */
1161 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001162 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001163 }
thughes4ad52d02004-06-27 17:37:21 +00001164 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001165}
1166
1167
1168/*====================================================================*/
1169/*=== Loading tools ===*/
1170/*====================================================================*/
1171
1172static void list_tools(void)
1173{
1174 DIR *dir = opendir(VG_(libdir));
1175 struct dirent *de;
1176 int first = 1;
1177
1178 if (dir == NULL) {
1179 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001180 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001181 return;
1182 }
1183
nethercotef4928da2004-06-15 10:54:40 +00001184 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001185 int len = strlen(de->d_name);
1186
njn063c5402004-11-22 16:58:05 +00001187 /* look for vgtool_TOOL.so names */
1188 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1189 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001190 VG_STREQ(de->d_name + len - 3, ".so")) {
1191 if (first) {
1192 fprintf(stderr, "Available tools:\n");
1193 first = 0;
1194 }
1195 de->d_name[len-3] = '\0';
1196 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001197 }
1198 }
1199
1200 closedir(dir);
1201
1202 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001203 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1204 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001205}
1206
1207
1208/* Find and load a tool, and check it looks ok. Also looks to see if there's
1209 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1210static void load_tool( const char *toolname, void** handle_out,
1211 ToolInfo** toolinfo_out, char **preloadpath_out )
1212{
1213 Bool ok;
1214 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1215 char buf[len];
1216 void* handle;
1217 ToolInfo* toolinfo;
1218 char* preloadpath = NULL;
1219 Int* vg_malloc_redzonep;
1220
1221 // XXX: allowing full paths for --tool option -- does it make sense?
1222 // Doesn't allow for vgpreload_<tool>.so.
1223
1224 if (strchr(toolname, '/') != 0) {
1225 /* toolname contains '/', and so must be a pathname */
1226 handle = dlopen(toolname, RTLD_NOW);
1227 } else {
1228 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001229 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001230 handle = dlopen(buf, RTLD_NOW);
1231
1232 if (handle != NULL) {
1233 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1234 if (access(buf, R_OK) == 0) {
1235 preloadpath = strdup(buf);
1236 vg_assert(NULL != preloadpath);
1237 }
1238 }
1239 }
1240
1241 ok = (NULL != handle);
1242 if (!ok) {
1243 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1244 goto bad_load;
1245 }
1246
njn26f02512004-11-22 18:33:15 +00001247 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001248 ok = (NULL != toolinfo);
1249 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001250 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001251 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1252 goto bad_load;
1253 }
1254
1255 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1256 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001257 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001258 if (!ok) {
1259 fprintf(stderr, "Error:\n"
1260 " Tool and core interface versions do not match.\n"
1261 " Interface version used by core is: %d.%d (size %d)\n"
1262 " Interface version used by tool is: %d.%d (size %d)\n"
1263 " The major version numbers must match.\n",
1264 VG_CORE_INTERFACE_MAJOR_VERSION,
1265 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001266 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001267 toolinfo->interface_major_version,
1268 toolinfo->interface_minor_version,
1269 toolinfo->sizeof_ToolInfo);
1270 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1271 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001272 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001273 else
nethercote996901a2004-08-03 13:29:09 +00001274 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001275 goto bad_load;
1276 }
1277
1278 // Set redzone size for V's allocator
1279 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1280 if ( NULL != vg_malloc_redzonep ) {
1281 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1282 }
1283
1284 vg_assert(NULL != handle && NULL != toolinfo);
1285 *handle_out = handle;
1286 *toolinfo_out = toolinfo;
1287 *preloadpath_out = preloadpath;
1288 return;
1289
1290
1291 bad_load:
1292 if (handle != NULL)
1293 dlclose(handle);
1294
nethercotef4928da2004-06-15 10:54:40 +00001295 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001296 list_tools();
1297 exit(127);
1298}
1299
nethercotef4928da2004-06-15 10:54:40 +00001300
1301/*====================================================================*/
1302/*=== Command line errors ===*/
1303/*====================================================================*/
1304
1305static void abort_msg ( void )
1306{
nethercotef8548672004-06-21 12:42:35 +00001307 VG_(clo_log_to) = VgLogTo_Fd;
1308 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001309}
1310
1311void VG_(bad_option) ( Char* opt )
1312{
1313 abort_msg();
1314 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1315 VG_(printf)("valgrind: Use --help for more information.\n");
1316 VG_(exit)(1);
1317}
1318
1319static void missing_tool_option ( void )
1320{
1321 abort_msg();
1322 VG_(printf)("valgrind: Missing --tool option\n");
1323 list_tools();
1324 VG_(printf)("valgrind: Use --help for more information.\n");
1325 VG_(exit)(1);
1326}
1327
1328static void missing_prog ( void )
1329{
1330 abort_msg();
1331 VG_(printf)("valgrind: no program specified\n");
1332 VG_(printf)("valgrind: Use --help for more information.\n");
1333 VG_(exit)(1);
1334}
1335
1336static void config_error ( Char* msg )
1337{
1338 abort_msg();
1339 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1340 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1341 VG_(exit)(1);
1342}
1343
1344
nethercote71980f02004-01-24 18:18:54 +00001345/*====================================================================*/
1346/*=== Loading the client ===*/
1347/*====================================================================*/
1348
nethercotef4928da2004-06-15 10:54:40 +00001349static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001350 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1351{
1352 // If they didn't specify an executable with --exec, and didn't specify
1353 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001354 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001355 if (cl_argv[0] == NULL ||
1356 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1357 {
nethercotef4928da2004-06-15 10:54:40 +00001358 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001359 }
1360 }
1361
1362 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001363 info->exe_base = VG_(client_base);
1364 info->exe_end = VG_(client_end);
1365 info->argv = cl_argv;
1366
nethercotef4928da2004-06-15 10:54:40 +00001367 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001368 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001369 // Totally zero 'info' before continuing.
1370 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001371 } else {
1372 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001373 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001374 ret = do_exec(exec, info);
1375 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001376 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1377 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001378 exit(127);
1379 }
1380 }
1381
1382 /* Copy necessary bits of 'info' that were filled in */
1383 *client_eip = info->init_eip;
1384 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1385}
1386
nethercote969ecf12004-10-13 17:29:01 +00001387/*====================================================================*/
1388/*=== Address space unpadding ===*/
1389/*====================================================================*/
1390
1391typedef struct {
1392 char* killpad_start;
1393 char* killpad_end;
1394 struct stat* killpad_padstat;
1395} killpad_extra;
1396
1397static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1398 int maj, int min, int ino, void* ex)
1399{
1400 killpad_extra* extra = ex;
1401 void *b, *e;
1402 int res;
1403
1404 vg_assert(NULL != extra->killpad_padstat);
1405
1406 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1407 extra->killpad_padstat->st_ino != ino)
1408 return 1;
1409
1410 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1411 return 1;
1412
1413 if (segstart <= extra->killpad_start)
1414 b = extra->killpad_start;
1415 else
1416 b = segstart;
1417
1418 if (segend >= extra->killpad_end)
1419 e = extra->killpad_end;
1420 else
1421 e = segend;
1422
1423 res = munmap(b, (char *)e-(char *)b);
1424 vg_assert(0 == res);
1425
1426 return 1;
1427}
1428
1429// Remove padding of 'padfile' from a range of address space.
1430void as_unpad(void *start, void *end, int padfile)
1431{
1432 static struct stat padstat;
1433 killpad_extra extra;
1434 int res;
1435
1436 vg_assert(padfile > 0);
1437
1438 res = fstat(padfile, &padstat);
1439 vg_assert(0 == res);
1440 extra.killpad_padstat = &padstat;
1441 extra.killpad_start = start;
1442 extra.killpad_end = end;
1443 foreach_map(killpad, &extra);
1444}
1445
1446void as_closepadfile(int padfile)
1447{
1448 int res = close(padfile);
1449 vg_assert(0 == res);
1450}
1451
nethercote71980f02004-01-24 18:18:54 +00001452
1453/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001454/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001455/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001456
njn25e49d8e72002-09-23 09:36:25 +00001457/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001458VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001459Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001460Bool VG_(clo_db_attach) = False;
1461Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
njn43c799e2003-04-08 00:08:52 +00001462Bool VG_(clo_gen_suppressions) = False;
nethercote27fec902004-06-16 21:26:32 +00001463Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001464Int VG_(clo_verbosity) = 1;
1465Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001466Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001467
nethercotef1e5e152004-09-01 23:58:16 +00001468/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001469 fd is initially stdout, for --help, but gets moved to stderr by default
1470 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001471VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001472Int VG_(clo_log_fd) = 1;
1473Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001474
thughes6233a382004-08-21 11:10:44 +00001475Bool VG_(clo_time_stamp) = False;
1476
sewardj6024b212003-07-13 10:54:33 +00001477Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001478Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001479Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001480Bool VG_(clo_profile) = False;
sewardj8e4d7dc2004-11-28 18:07:41 +00001481Bool VG_(clo_bbprofile) = False;
njn25e49d8e72002-09-23 09:36:25 +00001482UChar VG_(clo_trace_codegen) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001483Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001484Bool VG_(clo_trace_syscalls) = False;
1485Bool VG_(clo_trace_signals) = False;
1486Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001487Bool VG_(clo_trace_sched) = False;
1488Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001489Int VG_(clo_dump_error) = 0;
1490Int VG_(clo_backtrace_size) = 4;
1491Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001492Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001493Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001494Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001495Bool VG_(clo_pointercheck) = True;
fitzhardinge462f4f92003-12-18 02:10:54 +00001496Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001497
jsgf855d93d2003-10-13 22:26:55 +00001498static Bool VG_(clo_wait_for_gdb) = False;
1499
1500/* If we're doing signal routing, poll for signals every 50mS by
1501 default. */
1502Int VG_(clo_signal_polltime) = 50;
1503
1504/* These flags reduce thread wakeup latency on syscall completion and
1505 signal delivery, respectively. The downside is possible unfairness. */
1506Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1507Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1508
sewardjde4a1d02002-03-22 01:27:54 +00001509
nethercote6c999f22004-01-31 22:55:15 +00001510void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001511{
njn25e49d8e72002-09-23 09:36:25 +00001512 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001513"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001514"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001515" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001516" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001517" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001518" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001519" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001520" -q --quiet run silently; only print error msgs\n"
1521" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001522" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001523" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001524" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001525"\n"
1526" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001527" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1528" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1529" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1530" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1531" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001532" --pointercheck=no|yes enforce client address space limits [yes]\n"
njn25e49d8e72002-09-23 09:36:25 +00001533"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001535" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1536" --log-file=<file> log messages to <file>.pid<pid>\n"
1537" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001538" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1539" --num-callers=<number> show <num> callers in stack traces [4]\n"
1540" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1541" --show-below-main=no|yes continue stack traces below main() [no]\n"
1542" --suppressions=<filename> suppress errors described in <filename>\n"
1543" --gen-suppressions=no|yes print suppressions for errors detected [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001544" --db-attach=no|yes start debugger when errors detected? [no]\n"
1545" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1546" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001547"\n";
njn7cf0bd32002-06-08 13:36:03 +00001548
njn25e49d8e72002-09-23 09:36:25 +00001549 Char* usage2 =
1550"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001551" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001552" --sanity-level=<number> level of sanity checking to do [1]\n"
1553" --single-step=no|yes translate each instr separately? [no]\n"
1554" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001555" --profile=no|yes profile? (tool must be built for it) [no]\n"
njnc767b432004-11-29 16:08:22 +00001556" --bbprofile=no|yes profile bbs? [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001557" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001558" --trace-codegen=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001559" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001560" --trace-syscalls=no|yes show all system calls? [no]\n"
1561" --trace-signals=no|yes show signal handling details? [no]\n"
1562" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001563" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001564" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001565" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001566"\n"
sewardj8b635a42004-11-22 19:01:47 +00001567" --vex-iropt-verbosity 0 .. 9 [0]\n"
1568" --vex-iropt-level 0 .. 2 [2]\n"
1569" --vex-iropt-precise-memory-exns [no]\n"
1570" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1571" --vex-guest-max-insns 1 .. 100 [50]\n"
1572" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1573"\n"
sewardj2a99cf62004-11-24 10:44:19 +00001574" --trace-codegen values (omit the middle space):\n"
1575" 1000 0000 show conversion into IR\n"
1576" 0100 0000 show after initial opt\n"
1577" 0010 0000 show after instrumentation\n"
1578" 0001 0000 show after second opt\n"
1579" 0000 1000 show after tree building\n"
1580" 0000 0100 show selecting insns\n"
1581" 0000 0010 show after reg-alloc\n"
1582" 0000 0001 show final assembly\n"
1583"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001584" debugging options for Valgrind tools that report errors\n"
1585" --dump-error=<number> show translation for basic block associated\n"
1586" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001587"\n";
njn3e884182003-04-15 13:03:23 +00001588
1589 Char* usage3 =
1590"\n"
nethercote71980f02004-01-24 18:18:54 +00001591" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001592"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001593" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001594" and licensed under the GNU General Public License, version 2.\n"
1595" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001596"\n"
nethercote137bc552003-11-14 17:47:54 +00001597" Tools are copyright and licensed by their authors. See each\n"
1598" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001599"\n";
njn7cf0bd32002-06-08 13:36:03 +00001600
fitzhardinge98abfc72003-12-16 02:05:15 +00001601 VG_(printf)(usage1);
1602 if (VG_(details).name) {
1603 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001604 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001605 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001606 else
1607 VG_(printf)(" (none)\n");
1608 }
nethercote6c999f22004-01-31 22:55:15 +00001609 if (debug_help) {
1610 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001611
nethercote6c999f22004-01-31 22:55:15 +00001612 if (VG_(details).name) {
1613 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1614
1615 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001616 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001617 else
1618 VG_(printf)(" (none)\n");
1619 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001620 }
nethercote421281e2003-11-20 16:20:55 +00001621 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001622 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001623}
sewardjde4a1d02002-03-22 01:27:54 +00001624
nethercote71980f02004-01-24 18:18:54 +00001625static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001626 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001627{
nethercote71980f02004-01-24 18:18:54 +00001628 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001629
sewardj8b635a42004-11-22 19:01:47 +00001630 LibVEX_default_VexControl(& VG_(clo_vex_control));
1631
nethercote71980f02004-01-24 18:18:54 +00001632 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001633 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001636 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001637 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1640 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001641 *need_help = 1;
1642
nethercotef6a1d502004-08-09 12:21:57 +00001643 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001644 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001645
nethercotef6c99d72004-11-09 14:35:43 +00001646 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001647 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001648
nethercotef6a1d502004-08-09 12:21:57 +00001649 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1650 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001651 }
1652 }
1653
nethercotef4928da2004-06-15 10:54:40 +00001654 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001655 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001656 if (0 == *need_help) {
1657 // neither --tool nor --help/--help-debug specified
1658 missing_tool_option();
1659 } else {
1660 // Give help message, without any tool-specific help
1661 usage(/*help-debug?*/2 == *need_help);
1662 }
nethercote71980f02004-01-24 18:18:54 +00001663 }
1664}
1665
nethercote5ee67ca2004-06-22 14:00:09 +00001666static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001667{
nethercotef8548672004-06-21 12:42:35 +00001668 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001669 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001670
nethercotee1730692003-11-20 10:38:07 +00001671 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001672 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001673
sewardj19d81412002-06-03 01:10:40 +00001674 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001675 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001676 config_error("Please use absolute paths in "
1677 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001678
njnc6168192004-11-29 13:54:10 +00001679// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001680#ifdef __x86__
1681 {
1682 Int *auxp;
1683 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1684 switch(auxp[0]) {
1685 case AT_SYSINFO:
1686 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1687 break;
1688 }
1689 }
1690 }
1691#endif
sewardjde4a1d02002-03-22 01:27:54 +00001692
nethercotef6a1d502004-08-09 12:21:57 +00001693 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001694
nethercotef6a1d502004-08-09 12:21:57 +00001695 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001696 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001697
thughes3bfd5a02004-07-18 08:05:44 +00001698 /* Look for a colon in the switch name */
1699 while (*colon && *colon != ':' && *colon != '=')
1700 colon++;
nethercote71980f02004-01-24 18:18:54 +00001701
1702 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001703 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001704 if (VG_CLO_STREQN(2, arg, "--") &&
1705 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1706 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1707 {
1708 // prefix matches, convert "--toolname:foo" to "--foo"
1709 if (0)
1710 VG_(printf)("tool-specific arg: %s\n", arg);
1711 arg += toolname_len + 1;
1712 arg[0] = '-';
1713 arg[1] = '-';
1714
1715 } else {
1716 // prefix doesn't match, skip to next arg
1717 continue;
1718 }
1719 }
1720
fitzhardinge98abfc72003-12-16 02:05:15 +00001721 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001722 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001723 continue;
nethercote71980f02004-01-24 18:18:54 +00001724 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001725 continue;
1726
nethercote71980f02004-01-24 18:18:54 +00001727 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001728 continue;
nethercote27fec902004-06-16 21:26:32 +00001729
nethercote71980f02004-01-24 18:18:54 +00001730 else if (VG_CLO_STREQ(arg, "-v") ||
1731 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001732 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001733
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQ(arg, "-q") ||
1735 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001736 VG_(clo_verbosity)--;
1737
nethercote27fec902004-06-16 21:26:32 +00001738 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001739 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1740 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1741 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
1742 else VG_BOOL_CLO("--gen-suppressions", VG_(clo_gen_suppressions))
1743 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1744 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
nethercote27fec902004-06-16 21:26:32 +00001745 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
1746 else VG_BOOL_CLO("--profile", VG_(clo_profile))
sewardj8e4d7dc2004-11-28 18:07:41 +00001747 else VG_BOOL_CLO("--bbprofile", VG_(clo_bbprofile))
nethercote27fec902004-06-16 21:26:32 +00001748 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1749 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001750 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001751 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1752 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1753 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1754 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1755 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1756 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1757 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001758
nethercote27fec902004-06-16 21:26:32 +00001759 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1760 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001761
nethercote27fec902004-06-16 21:26:32 +00001762 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1763 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1764 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001765 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001766 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1767 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001768
sewardj8b635a42004-11-22 19:01:47 +00001769 else VG_BNUM_CLO("--vex-iropt-verbosity",
1770 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1771 else VG_BNUM_CLO("--vex-iropt-level",
1772 VG_(clo_vex_control).iropt_level, 0, 2)
1773 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1774 VG_(clo_vex_control).iropt_precise_memory_exns)
1775 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1776 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1777 else VG_BNUM_CLO("--vex-guest-max-insns",
1778 VG_(clo_vex_control).guest_max_insns, 1, 100)
1779 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1780 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1781
nethercotef8548672004-06-21 12:42:35 +00001782 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001783 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001784 VG_(clo_log_to) = VgLogTo_Fd;
1785 VG_(clo_log_name) = NULL;
1786 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1787 }
1788 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1789 VG_(clo_log_to) = VgLogTo_Fd;
1790 VG_(clo_log_name) = NULL;
1791 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001792 }
1793
nethercotef8548672004-06-21 12:42:35 +00001794 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001795 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001796 VG_(clo_log_to) = VgLogTo_File;
1797 VG_(clo_log_name) = &arg[10];
1798 }
1799 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1800 VG_(clo_log_to) = VgLogTo_File;
1801 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001802 }
sewardjde4a1d02002-03-22 01:27:54 +00001803
nethercotef8548672004-06-21 12:42:35 +00001804 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001805 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001806 VG_(clo_log_to) = VgLogTo_Socket;
1807 VG_(clo_log_name) = &arg[12];
1808 }
1809 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1810 VG_(clo_log_to) = VgLogTo_Socket;
1811 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001812 }
1813
nethercote71980f02004-01-24 18:18:54 +00001814 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001815 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001816 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001817 VG_(message)(Vg_UserMsg,
1818 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001819 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001820 }
nethercote71980f02004-01-24 18:18:54 +00001821 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001822 VG_(clo_n_suppressions)++;
1823 }
sewardjde4a1d02002-03-22 01:27:54 +00001824
njn25e49d8e72002-09-23 09:36:25 +00001825 /* "vwxyz" --> 000zyxwv (binary) */
nethercote71980f02004-01-24 18:18:54 +00001826 else if (VG_CLO_STREQN(16, arg, "--trace-codegen=")) {
njn25e49d8e72002-09-23 09:36:25 +00001827 Int j;
nethercote71980f02004-01-24 18:18:54 +00001828 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001829
sewardj2a99cf62004-11-24 10:44:19 +00001830 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001831 VG_(message)(Vg_UserMsg,
sewardj8b635a42004-11-22 19:01:47 +00001832 "--trace-codegen argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001833 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001834 }
sewardj8b635a42004-11-22 19:01:47 +00001835 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001836 if ('0' == opt[j]) { /* do nothing */ }
sewardj8b635a42004-11-22 19:01:47 +00001837 else if ('1' == opt[j]) VG_(clo_trace_codegen) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001838 else {
1839 VG_(message)(Vg_UserMsg, "--trace-codegen argument can only "
1840 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001841 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001842 }
1843 }
1844 }
sewardjde4a1d02002-03-22 01:27:54 +00001845
sewardjc771b292004-11-30 18:55:21 +00001846 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1847
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
sewardj998d40d2004-12-06 14:24:52 +00001861 /* Make VEX control parameters sane */
1862
1863 if (VG_(clo_vex_control).guest_chase_thresh
1864 >= VG_(clo_vex_control).guest_max_insns)
1865 VG_(clo_vex_control).guest_chase_thresh
1866 = VG_(clo_vex_control).guest_max_insns - 1;
1867
1868 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1869 VG_(clo_vex_control).guest_chase_thresh = 0;
1870
1871 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001872
njnf9ebf672003-05-12 21:41:30 +00001873 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001874 VG_(clo_verbosity) = 0;
1875
nethercote04d0fbc2004-01-26 16:48:06 +00001876 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001877 VG_(message)(Vg_UserMsg, "");
1878 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001879 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001880 VG_(message)(Vg_UserMsg,
1881 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001882 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001883 }
1884
nethercotef8548672004-06-21 12:42:35 +00001885 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001886 should be connected to whatever sink has been selected, and we
1887 indiscriminately chuck stuff into it without worrying what the
1888 nature of it is. Oh the wonder of Unix streams. */
1889
nethercotee1730692003-11-20 10:38:07 +00001890 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001891 the terminal any problems to do with processing command line
1892 opts. */
nethercotef8548672004-06-21 12:42:35 +00001893 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001894 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001895
1896 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001897
sewardj4cf05692002-10-27 20:28:29 +00001898 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001899 vg_assert(VG_(clo_log_name) == NULL);
1900 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001901 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001902
sewardj4cf05692002-10-27 20:28:29 +00001903 case VgLogTo_File: {
1904 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001905 Int seq = 0;
1906 Int pid = VG_(getpid)();
1907
nethercotef8548672004-06-21 12:42:35 +00001908 vg_assert(VG_(clo_log_name) != NULL);
1909 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001910
nethercote71980f02004-01-24 18:18:54 +00001911 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001912 if (seq == 0)
1913 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001914 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001915 else
1916 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001917 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001918 seq++;
1919
nethercotef8548672004-06-21 12:42:35 +00001920 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001921 = VG_(open)(logfilename,
1922 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1923 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001924 if (eventually_log_fd >= 0) {
1925 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
jsgff3c3f1a2003-10-14 22:13:28 +00001926 break;
1927 } else {
nethercotef8548672004-06-21 12:42:35 +00001928 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001929 VG_(message)(Vg_UserMsg,
1930 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001931 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001932 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001933 "--log-file=<file> didn't work out for some reason.");
jsgff3c3f1a2003-10-14 22:13:28 +00001934 break;
1935 }
1936 }
1937 }
sewardj4cf05692002-10-27 20:28:29 +00001938 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001939 }
1940
1941 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001942 vg_assert(VG_(clo_log_name) != NULL);
1943 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1944 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1945 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001946 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001947 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001948 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001949 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001950 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001951 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001952 }
nethercotef8548672004-06-21 12:42:35 +00001953 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001954 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001955 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001956 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001957 VG_(message)(Vg_UserMsg,
1958 "Log messages will sent to stderr instead." );
1959 VG_(message)(Vg_UserMsg,
1960 "" );
1961 /* We don't change anything here. */
1962 } else {
nethercotef8548672004-06-21 12:42:35 +00001963 vg_assert(eventually_log_fd > 0);
1964 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001965 VG_(logging_to_filedes) = False;
1966 }
sewardj73cf3bc2002-11-03 03:20:15 +00001967 break;
1968 }
1969
sewardj4cf05692002-10-27 20:28:29 +00001970 }
1971
nethercotef8548672004-06-21 12:42:35 +00001972 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001973 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001974 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001975 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1976 else {
nethercotef8548672004-06-21 12:42:35 +00001977 VG_(clo_log_fd) = eventually_log_fd;
1978 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001979 }
1980
sewardj4cf05692002-10-27 20:28:29 +00001981 /* Ok, the logging sink is running now. Print a suitable preamble.
1982 If logging to file or a socket, write details of parent PID and
1983 command line args, to help people trying to interpret the
1984 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001985
sewardj83adf412002-05-01 01:25:45 +00001986 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001987 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001988 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001989 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001990 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001991 NULL == VG_(details).version
1992 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001993 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001994 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001995
njnd04b7c62002-10-03 14:05:52 +00001996 /* Core details */
1997 VG_(message)(Vg_UserMsg,
sewardjc7025332004-12-13 18:30:39 +00001998 "Using LibVEX-%s, a library for dynamic binary translation.",
1999 /*VERSION*/ "SVN >= 653");
2000 VG_(message)(Vg_UserMsg,
2001 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2002 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002003 "Using valgrind-%s, a dynamic binary instrumentation framework.",
sewardjc7025332004-12-13 18:30:39 +00002004 /*VERSION*/ "SVN >= 3196");
sewardjde4a1d02002-03-22 01:27:54 +00002005 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00002006 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002007 }
2008
nethercotec1e395d2003-11-10 13:26:49 +00002009 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002010 VG_(message)(Vg_UserMsg, "");
2011 VG_(message)(Vg_UserMsg,
2012 "My PID = %d, parent PID = %d. Prog and args are:",
2013 VG_(getpid)(), VG_(getppid)() );
2014 for (i = 0; i < VG_(client_argc); i++)
2015 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2016 }
2017
sewardjde4a1d02002-03-22 01:27:54 +00002018 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002019 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002020 if (VG_(clo_log_to) != VgLogTo_Fd)
2021 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002022 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002023 VG_(message)(Vg_UserMsg, "Command line");
2024 for (i = 0; i < VG_(client_argc); i++)
2025 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2026
sewardjde4a1d02002-03-22 01:27:54 +00002027 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002028 for (i = 1; i < vg_argc; i++) {
2029 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002030 }
nethercotea70f7352004-04-18 12:08:46 +00002031
2032 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2033 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2034 if (fd < 0) {
2035 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2036 } else {
2037 #define BUF_LEN 256
2038 Char version_buf[BUF_LEN];
2039 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2040 vg_assert(n <= 256);
2041 if (n > 0) {
2042 version_buf[n-1] = '\0';
2043 VG_(message)(Vg_UserMsg, " %s", version_buf);
2044 } else {
2045 VG_(message)(Vg_UserMsg, " (empty?)");
2046 }
2047 VG_(close)(fd);
2048 #undef BUF_LEN
2049 }
sewardjde4a1d02002-03-22 01:27:54 +00002050 }
2051
fitzhardinge98abfc72003-12-16 02:05:15 +00002052 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002053 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002054 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002055 needs one, load the default */
2056 static const Char default_supp[] = "default.supp";
2057 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2058 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2059 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2060 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2061 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002062 }
sewardj4cf05692002-10-27 20:28:29 +00002063
njn6a230532003-07-21 10:38:23 +00002064 if (VG_(clo_gen_suppressions) &&
njn95ec8702004-11-22 16:46:13 +00002065 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002066 VG_(message)(Vg_UserMsg,
2067 "Can't use --gen-suppressions=yes with this tool,");
2068 VG_(message)(Vg_UserMsg,
2069 "as it doesn't generate errors.");
2070 VG_(bad_option)("--gen-suppressions=yes");
njn6a230532003-07-21 10:38:23 +00002071 }
sewardjde4a1d02002-03-22 01:27:54 +00002072}
2073
nethercotef6a1d502004-08-09 12:21:57 +00002074// Build the string for VALGRINDCLO.
2075Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2076{
2077 /* If we're tracing the children, then we need to start it
2078 with our starter+arguments, which are copied into VALGRINDCLO,
2079 except the --exec= option is changed if present.
2080 */
2081 Int i;
2082 Char *exec;
2083 Char *cp;
2084 Char *optvar;
2085 Int optlen, execlen;
2086
2087 // All these allocated blocks are not free - because we're either
2088 // going to exec, or panic when we fail.
2089
2090 // Create --exec= option: "--exec=<exename>"
2091 exec = VG_(arena_malloc)(VG_AR_CORE,
2092 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2093 vg_assert(NULL != exec);
2094 VG_(sprintf)(exec, "--exec=%s", exename);
2095
2096 // Allocate space for optvar (may overestimate by counting --exec twice,
2097 // no matter)
2098 optlen = 1;
2099 for (i = 0; i < vg_argc; i++)
2100 optlen += VG_(strlen)(vg_argv[i]) + 1;
2101 optlen += VG_(strlen)(exec)+1;
2102 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2103
2104 // Copy all valgrind args except the old --exec (if present)
2105 // VG_CLO_SEP is the separator.
2106 cp = optvar;
2107 for (i = 1; i < vg_argc; i++) {
2108 Char *arg = vg_argv[i];
2109
2110 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2111 // don't copy existing --exec= arg
2112 } else if (VG_(strcmp)(arg, "--") == 0) {
2113 // stop at "--"
2114 break;
2115 } else {
2116 // copy non "--exec" arg
2117 Int len = VG_(strlen)(arg);
2118 VG_(memcpy)(cp, arg, len);
2119 cp += len;
2120 *cp++ = VG_CLO_SEP;
2121 }
2122 }
2123 // Add the new --exec= option
2124 execlen = VG_(strlen)(exec);
2125 VG_(memcpy)(cp, exec, execlen);
2126 cp += execlen;
2127 *cp++ = VG_CLO_SEP;
2128
2129 *cp = '\0';
2130
2131 return optvar;
2132}
2133
2134// Build "/proc/self/fd/<execfd>".
2135Char* VG_(build_child_exename)( void )
2136{
2137 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2138 vg_assert(NULL != exename);
2139 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2140 return exename;
2141}
2142
sewardjde4a1d02002-03-22 01:27:54 +00002143
nethercote71980f02004-01-24 18:18:54 +00002144/*====================================================================*/
2145/*=== File descriptor setup ===*/
2146/*====================================================================*/
2147
2148static void setup_file_descriptors(void)
2149{
2150 struct vki_rlimit rl;
2151
2152 /* Get the current file descriptor limits. */
2153 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2154 rl.rlim_cur = 1024;
2155 rl.rlim_max = 1024;
2156 }
2157
2158 /* Work out where to move the soft limit to. */
2159 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2160 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2161 } else {
2162 rl.rlim_cur = rl.rlim_max;
2163 }
2164
2165 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002166 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2167 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002168
2169 /* Update the soft limit. */
2170 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2171
nethercotef6a1d502004-08-09 12:21:57 +00002172 if (vgexecfd != -1)
2173 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002174 if (VG_(clexecfd) != -1)
2175 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2176}
2177
nethercote71980f02004-01-24 18:18:54 +00002178/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002179/*=== Initialise program data/text, etc. ===*/
2180/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002181
nethercote71980f02004-01-24 18:18:54 +00002182static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002183 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002184 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002185{
nethercote71980f02004-01-24 18:18:54 +00002186 UInt prot = 0;
2187 UInt flags = SF_MMAP|SF_NOSYMS;
2188 Bool is_stack_segment;
2189
2190 is_stack_segment =
2191 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2192
2193 /* Only record valgrind mappings for now, without loading any
2194 symbols. This is so we know where the free space is before we
2195 start allocating more memory (note: heap is OK, it's just mmap
2196 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002197 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002198 flags |= SF_VALGRIND;
2199 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2200 }
sewardjde4a1d02002-03-22 01:27:54 +00002201}
2202
nethercote71980f02004-01-24 18:18:54 +00002203// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002204Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002205
nethercote71980f02004-01-24 18:18:54 +00002206static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002207 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002208 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002209{
nethercote71980f02004-01-24 18:18:54 +00002210 UInt prot = 0;
2211 UInt flags;
2212 Bool is_stack_segment;
2213 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002214
nethercote71980f02004-01-24 18:18:54 +00002215 is_stack_segment
2216 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002217
nethercote71980f02004-01-24 18:18:54 +00002218 if (rr == 'r') prot |= VKI_PROT_READ;
2219 if (ww == 'w') prot |= VKI_PROT_WRITE;
2220 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002221
nethercote71980f02004-01-24 18:18:54 +00002222 if (is_stack_segment)
2223 flags = SF_STACK | SF_GROWDOWN;
2224 else
2225 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002226
nethercote71980f02004-01-24 18:18:54 +00002227 if (filename != NULL)
2228 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002229
nethercote820bd8c2004-09-07 23:04:49 +00002230 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002231 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002232
nethercote71980f02004-01-24 18:18:54 +00002233 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002234
nethercote71980f02004-01-24 18:18:54 +00002235 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2236 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002237
nethercote71980f02004-01-24 18:18:54 +00002238 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002239 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002240 vg_assert(0 != r_esp);
2241 if (is_stack_segment) {
2242 if (0)
2243 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2244 start,r_esp);
2245 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002246 }
sewardjde4a1d02002-03-22 01:27:54 +00002247}
2248
2249
nethercote71980f02004-01-24 18:18:54 +00002250/*====================================================================*/
2251/*=== Sanity check machinery (permanently engaged) ===*/
2252/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002253
2254/* A fast sanity check -- suitable for calling circa once per
2255 millisecond. */
2256
nethercote885dd912004-08-03 23:14:00 +00002257void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002258{
njn37cea302002-09-30 11:24:00 +00002259 VGP_PUSHCC(VgpCoreCheapSanity);
2260
nethercote27fec902004-06-16 21:26:32 +00002261 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002262
2263 /* --- First do all the tests that we can do quickly. ---*/
2264
nethercote297effd2004-08-02 15:07:57 +00002265 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002266
njn25e49d8e72002-09-23 09:36:25 +00002267 /* Check stuff pertaining to the memory check system. */
2268
2269 /* Check that nobody has spuriously claimed that the first or
2270 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002271 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002272 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002273 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002274 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002275 }
njn25e49d8e72002-09-23 09:36:25 +00002276
2277 /* --- Now some more expensive checks. ---*/
2278
2279 /* Once every 25 times, check some more expensive stuff. */
2280 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002281 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002282 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002283
njn37cea302002-09-30 11:24:00 +00002284 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002285 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002286
nethercote885dd912004-08-03 23:14:00 +00002287 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002288
njn25e49d8e72002-09-23 09:36:25 +00002289# if 0
2290 { void zzzmemscan(void); zzzmemscan(); }
2291# endif
2292
nethercote297effd2004-08-02 15:07:57 +00002293 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002294 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002295
2296 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002297 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002298 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002299 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002300 }
2301 /*
nethercote297effd2004-08-02 15:07:57 +00002302 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002303 */
njn37cea302002-09-30 11:24:00 +00002304 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002305 }
2306
nethercote27fec902004-06-16 21:26:32 +00002307 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002308 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002309 /* Check sanity of the low-level memory manager. Note that bugs
2310 in the client's code can cause this to fail, so we don't do
2311 this check unless specially asked for. And because it's
2312 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002313 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002314 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002315 }
njn37cea302002-09-30 11:24:00 +00002316 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002317}
nethercote71980f02004-01-24 18:18:54 +00002318
2319
2320/*====================================================================*/
2321/*=== main() ===*/
2322/*====================================================================*/
2323
nethercotec314eba2004-07-15 12:59:41 +00002324/*
2325 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002326 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002327 loads the client executable (and the dynamic linker, if necessary)
2328 into the client part, and calls into Valgrind proper.
2329
2330 The code is careful not to allow spurious mappings to appear in the
2331 wrong parts of the address space. In particular, to make sure
2332 dlopen puts things in the right place, it will pad out the forbidden
2333 chunks of address space so that dlopen is forced to put things where
2334 we want them.
2335
2336 The memory map it creates is:
2337
2338 CLIENT_BASE +-------------------------+
2339 | client address space |
2340 : :
2341 : :
2342 | client stack |
2343 client_end +-------------------------+
2344 | redzone |
2345 shadow_base +-------------------------+
2346 | |
nethercote996901a2004-08-03 13:29:09 +00002347 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002348 | (may be 0 sized) |
2349 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002350 valgrind_base +-------------------------+
2351 | kickstart executable |
2352 | valgrind heap vvvvvvvvv| (barely used)
2353 - -
2354 | valgrind .so files |
2355 | and mappings |
2356 - -
2357 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002358 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002359 : kernel :
2360
2361 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2362 VG_(mmap)(), we need to build the segment skip-list, so we know where
2363 we can put things. However, building that structure requires
2364 allocating memory. So we need to a bootstrapping process. It's done
2365 by making VG_(arena_malloc)() have a special static superblock that's
2366 used for the first 1MB's worth of allocations. This is enough to
2367 build the segment skip-list.
2368*/
2369
nethercote31779c72004-07-30 21:50:15 +00002370static int prmap(char *start, char *end, const char *perm, off_t off,
2371 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002372 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2373 start, end, perm, maj, min, ino);
2374 return True;
2375}
2376
nethercote71980f02004-01-24 18:18:54 +00002377int main(int argc, char **argv)
2378{
2379 char **cl_argv;
2380 const char *tool = NULL;
2381 const char *exec = NULL;
2382 char *preload; /* tool-specific LD_PRELOAD .so */
2383 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002384 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002385 struct exeinfo info;
2386 ToolInfo *toolinfo = NULL;
2387 void *tool_dlhandle;
2388 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002389 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002390 UInt * client_auxv;
2391 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002392 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002393 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002394 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002395 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002396 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2397
nethercote71980f02004-01-24 18:18:54 +00002398
2399 //============================================================
2400 // Nb: startup is complex. Prerequisites are shown at every step.
2401 //
2402 // *** Be very careful when messing with the order ***
2403 //============================================================
2404
nethercotef4928da2004-06-15 10:54:40 +00002405 //============================================================
2406 // Command line argument handling order:
2407 // * If --help/--help-debug are present, show usage message
2408 // (if --tool is also present, that includes the tool-specific usage)
2409 // * Then, if --tool is missing, abort with error msg
2410 // * Then, if client is missing, abort with error msg
2411 // * Then, if any cmdline args are bad, abort with error msg
2412 //============================================================
2413
fitzhardingeb50068f2004-02-24 23:42:55 +00002414 // Get the current process datasize rlimit, and set it to zero.
2415 // This prevents any internal uses of brk() from having any effect.
2416 // We remember the old value so we can restore it on exec, so that
2417 // child processes will have a reasonable brk value.
2418 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2419 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2420 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002421
2422 // Get the current process stack rlimit.
2423 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2424
nethercote71980f02004-01-24 18:18:54 +00002425 //--------------------------------------------------------------
2426 // Check we were launched by stage1
nethercotec314eba2004-07-15 12:59:41 +00002427 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002428 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002429 {
2430 void* init_sp = argv - 1;
2431 padfile = scan_auxv(init_sp);
2432 }
nethercote71980f02004-01-24 18:18:54 +00002433
2434 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002435 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002436 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002437 }
2438
2439 //--------------------------------------------------------------
2440 // Look for alternative libdir
2441 // p: n/a
2442 //--------------------------------------------------------------
2443 { char *cp = getenv(VALGRINDLIB);
2444 if (cp != NULL)
2445 VG_(libdir) = cp;
2446 }
2447
2448 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002449 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2450 // Pre-process the command line.
2451 // p: n/a
2452 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002453 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002454 pre_process_cmd_line_options(&need_help, &tool, &exec);
2455
2456 //==============================================================
2457 // Nb: once a tool is specified, the tool.so must be loaded even if
2458 // they specified --help or didn't specify a client program.
2459 //==============================================================
2460
2461 //--------------------------------------------------------------
2462 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002463 // p: set-libdir [for VG_(libdir)]
2464 // p: pre_process_cmd_line_options() [for 'tool']
2465 //--------------------------------------------------------------
2466 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2467
2468 //==============================================================
2469 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002470 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002471 //==============================================================
2472
2473 //--------------------------------------------------------------
2474 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002475 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002476 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002477 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002478
2479 //--------------------------------------------------------------
2480 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002481 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2482 // p: layout_remaining_space [so there's space]
2483 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002484 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002485
2486 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002487 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002488 // p: layout_remaining_space() [everything must be mapped in before now]
2489 // p: load_client() [ditto]
2490 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002491 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2492 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002493
2494 //--------------------------------------------------------------
2495 // Set up client's environment
2496 // p: set-libdir [for VG_(libdir)]
2497 // p: load_tool() [for 'preload']
2498 //--------------------------------------------------------------
2499 env = fix_environment(environ, preload);
2500
2501 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002502 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002503 // p: load_client() [for 'info']
2504 // p: fix_environment() [for 'env']
2505 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002506 {
2507 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002508 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2509 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002510 }
nethercote71980f02004-01-24 18:18:54 +00002511
2512 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002513 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002514 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002515 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002516
2517 //==============================================================
2518 // Finished setting up operating environment. Now initialise
2519 // Valgrind. (This is where the old VG_(main)() started.)
2520 //==============================================================
2521
2522 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002523 // atfork
2524 // p: n/a
2525 //--------------------------------------------------------------
2526 VG_(atfork)(NULL, NULL, newpid);
2527 newpid(VG_INVALID_THREADID);
2528
2529 //--------------------------------------------------------------
2530 // setup file descriptors
2531 // p: n/a
2532 //--------------------------------------------------------------
2533 setup_file_descriptors();
2534
2535 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002536 // Read /proc/self/maps into a buffer
2537 // p: all memory layout, environment setup [so memory maps are right]
2538 //--------------------------------------------------------------
2539 VG_(read_procselfmaps)();
2540
2541 //--------------------------------------------------------------
2542 // Build segment map (Valgrind segments only)
2543 // p: read proc/self/maps
njnd2252832004-11-26 10:53:33 +00002544 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002545 //--------------------------------------------------------------
2546 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2547
2548 //==============================================================
2549 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2550 //==============================================================
2551
2552 //--------------------------------------------------------------
2553 // Init tool: pre_clo_init, process cmd line, post_clo_init
2554 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2555 // p: load_tool() [for 'tool']
2556 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2557 // p: parse_procselfmaps [so VG segments are setup so tool can
2558 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002559 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002560 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002561 VG_(tool_init_dlsym)(tool_dlhandle);
2562 VG_(sanity_check_needs)();
2563
nethercotef4928da2004-06-15 10:54:40 +00002564 // If --tool and --help/--help-debug was given, now give the core+tool
2565 // help message
nethercotef4928da2004-06-15 10:54:40 +00002566 if (need_help) {
2567 usage(/*--help-debug?*/2 == need_help);
2568 }
nethercotec314eba2004-07-15 12:59:41 +00002569 process_cmd_line_options(client_auxv, tool);
2570
njn26f02512004-11-22 18:33:15 +00002571 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002572
2573 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002574 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002575 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002576 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002577 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002578 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002579 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002580 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002581
njnca0518d2004-11-26 19:34:36 +00002582#ifdef __i386__
nethercotec314eba2004-07-15 12:59:41 +00002583 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002584 // Protect client trampoline page (which is also sysinfo stuff)
2585 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002586 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002587 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2588 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002589#endif
nethercotec314eba2004-07-15 12:59:41 +00002590
2591 //==============================================================
2592 // Can use VG_(map)() after segments set up
2593 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002594
2595 //--------------------------------------------------------------
2596 // Allow GDB attach
2597 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2598 //--------------------------------------------------------------
2599 /* Hook to delay things long enough so we can get the pid and
2600 attach GDB in another shell. */
2601 if (VG_(clo_wait_for_gdb)) {
2602 VG_(printf)("pid=%d\n", VG_(getpid)());
2603 /* do "jump *$eip" to skip this in gdb */
njnca6fef02004-11-29 16:49:18 +00002604 VG_(do_syscall0)(__NR_pause);
nethercote71980f02004-01-24 18:18:54 +00002605 }
2606
2607 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002608 // Search for file descriptors that are inherited from our parent
2609 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2610 //--------------------------------------------------------------
2611 if (VG_(clo_track_fds))
2612 VG_(init_preopened_fds)();
2613
2614 //--------------------------------------------------------------
2615 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002616 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2617 //--------------------------------------------------------------
2618 VG_(scheduler_init)();
2619
2620 //--------------------------------------------------------------
sewardj2a99cf62004-11-24 10:44:19 +00002621 // Set up state of thread 1
2622 // p: {pre,post}_clo_init() [for tool helper registration]
2623 // load_client() [for 'client_eip']
2624 // setup_client_stack() [for 'sp_at_startup']
2625 // setup_scheduler() [for the rest of state 1 stuff]
2626 //--------------------------------------------------------------
2627 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002628
2629 // Tell the tool that we just wrote to the registers.
2630 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2631 sizeof(VexGuestArchState));
2632
2633 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002634 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002635
2636 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002637 // Set up the ProxyLWP machinery
2638 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002639 //--------------------------------------------------------------
2640 VG_(proxy_init)();
2641
2642 //--------------------------------------------------------------
2643 // Initialise the signal handling subsystem
2644 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2645 // p: VG_(proxy_init)() [else breaks...]
2646 //--------------------------------------------------------------
2647 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2648 VG_(sigstartup_actions)();
2649
2650 //--------------------------------------------------------------
2651 // Perhaps we're profiling Valgrind?
2652 // p: process_cmd_line_options() [for VG_(clo_profile)]
2653 // p: others?
2654 //
2655 // XXX: this seems to be broken? It always says the tool wasn't built
2656 // for profiling; vg_profile.c's functions don't seem to be overriding
2657 // vg_dummy_profile.c's?
2658 //
2659 // XXX: want this as early as possible. Looking for --profile
2660 // in pre_process_cmd_line_options() could get it earlier.
2661 //--------------------------------------------------------------
2662 if (VG_(clo_profile))
2663 VGP_(init_profiling)();
2664
2665 VGP_PUSHCC(VgpStartup);
2666
2667 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002668 // Read suppression file
2669 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2670 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002671 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002672 VG_(load_suppressions)();
2673
2674 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002675 // Initialise translation table and translation cache
2676 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2677 // aren't identified as part of the client, which would waste
2678 // > 20M of virtual address space.]
2679 //--------------------------------------------------------------
2680 VG_(init_tt_tc)();
2681
2682 //--------------------------------------------------------------
2683 // Read debug info to find glibc entry points to intercept
2684 // p: parse_procselfmaps? [XXX for debug info?]
2685 // p: init_tt_tc? [XXX ???]
2686 //--------------------------------------------------------------
2687 VG_(setup_code_redirect_table)();
2688
2689 //--------------------------------------------------------------
2690 // Verbosity message
2691 // p: end_rdtsc_calibration [so startup message is printed first]
2692 //--------------------------------------------------------------
2693 if (VG_(clo_verbosity) == 1)
2694 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2695 if (VG_(clo_verbosity) > 0)
2696 VG_(message)(Vg_UserMsg, "");
2697
2698 //--------------------------------------------------------------
2699 // Setup pointercheck
2700 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2701 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002702 if (VG_(clo_pointercheck))
2703 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002704
nethercote71980f02004-01-24 18:18:54 +00002705 //--------------------------------------------------------------
2706 // Run!
2707 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002708 VGP_POPCC(VgpStartup);
2709 VGP_PUSHCC(VgpSched);
2710
nethercote238a3c32004-08-09 13:13:31 +00002711 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002712
nethercote238a3c32004-08-09 13:13:31 +00002713 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002714
nethercote71980f02004-01-24 18:18:54 +00002715 //--------------------------------------------------------------
2716 // Finalisation: cleanup, messages, etc. Order no so important, only
2717 // affects what order the messages come.
2718 //--------------------------------------------------------------
2719 if (VG_(clo_verbosity) > 0)
2720 VG_(message)(Vg_UserMsg, "");
2721
2722 if (src == VgSrc_Deadlock) {
2723 VG_(message)(Vg_UserMsg,
2724 "Warning: pthread scheduler exited due to deadlock");
2725 }
2726
2727 /* Print out file descriptor summary and stats. */
2728 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002729 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002730
njn95ec8702004-11-22 16:46:13 +00002731 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002732 VG_(show_all_errors)();
2733
njn26f02512004-11-22 18:33:15 +00002734 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002735
nethercote885dd912004-08-03 23:14:00 +00002736 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002737
2738 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002739 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002740
nethercote71980f02004-01-24 18:18:54 +00002741 if (VG_(clo_profile))
2742 VGP_(done_profiling)();
2743
nethercote71980f02004-01-24 18:18:54 +00002744 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2745 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002746 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2747 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002748 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2749
sewardj8b635a42004-11-22 19:01:47 +00002750 /* Print Vex storage stats */
njn383ae5e2004-11-23 17:10:15 +00002751 LibVEX_ClearTemporary( False/*show stats*/ );
sewardj8b635a42004-11-22 19:01:47 +00002752
nethercote71980f02004-01-24 18:18:54 +00002753 //--------------------------------------------------------------
2754 // Exit, according to the scheduler's return code
2755 //--------------------------------------------------------------
2756 switch (src) {
2757 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002758 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002759 VG_(proxy_shutdown)();
2760
2761 /* The thread's %EBX at the time it did __NR_exit() will hold
2762 the arg to __NR_exit(), so we just do __NR_exit() with
2763 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002764 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002765 /* NOT ALIVE HERE! */
2766 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2767 break; /* what the hell :) */
2768
2769 case VgSrc_Deadlock:
2770 /* Just exit now. No point in continuing. */
2771 VG_(proxy_shutdown)();
2772 VG_(exit)(0);
2773 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2774 break;
2775
nethercote71980f02004-01-24 18:18:54 +00002776 case VgSrc_FatalSig:
2777 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002778 vg_assert(fatal_sigNo != -1);
2779 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002780 VG_(core_panic)("main(): signal was supposed to be fatal");
2781 break;
2782
2783 default:
2784 VG_(core_panic)("main(): unexpected scheduler return code");
2785 }
2786
2787 abort();
2788}
2789
2790
sewardjde4a1d02002-03-22 01:27:54 +00002791/*--------------------------------------------------------------------*/
2792/*--- end vg_main.c ---*/
2793/*--------------------------------------------------------------------*/