blob: 41f5c0f437bdb4fbd5b3fd65e81f28f60445db51 [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
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 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
sewardjb5f6f512005-03-10 23:59:00 +000048#include "memcheck/memcheck.h"
49
thughes74b8de22004-04-22 18:12:31 +000050#ifndef AT_DCACHEBSIZE
51#define AT_DCACHEBSIZE 19
52#endif /* AT_DCACHEBSIZE */
53
54#ifndef AT_ICACHEBSIZE
55#define AT_ICACHEBSIZE 20
56#endif /* AT_ICACHEBSIZE */
57
58#ifndef AT_UCACHEBSIZE
59#define AT_UCACHEBSIZE 21
60#endif /* AT_UCACHEBSIZE */
61
nethercote71980f02004-01-24 18:18:54 +000062#ifndef AT_SYSINFO
63#define AT_SYSINFO 32
64#endif /* AT_SYSINFO */
65
66#ifndef AT_SYSINFO_EHDR
67#define AT_SYSINFO_EHDR 33
68#endif /* AT_SYSINFO_EHDR */
69
70#ifndef AT_SECURE
71#define AT_SECURE 23 /* secure mode boolean */
72#endif /* AT_SECURE */
73
nethercote71980f02004-01-24 18:18:54 +000074/* redzone gap between client address space and shadow */
75#define REDZONE_SIZE (1 * 1024*1024)
76
77/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000078#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000079
nethercotee2097312004-06-27 12:29:56 +000080/* Proportion of client space for its heap (rest is for mmaps + stack) */
81#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000082
njn14319cc2005-03-13 06:26:22 +000083/* Number of file descriptors that Valgrind tries to reserve for
84 it's own use - just a small constant. */
85#define N_RESERVED_FDS (10)
86
87/* Default debugger command. */
88#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
89
nethercote71980f02004-01-24 18:18:54 +000090/*====================================================================*/
91/*=== Global entities not referenced from generated code ===*/
92/*====================================================================*/
93
sewardjde4a1d02002-03-22 01:27:54 +000094/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000095 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000096 ------------------------------------------------------------------ */
97
nethercote71980f02004-01-24 18:18:54 +000098/* Client address space, lowest to highest (see top of ume.c) */
99Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000100Addr VG_(client_end);
101Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000102Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000103Addr VG_(clstk_base);
104Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000105
106Addr VG_(brk_base); /* start of brk */
107Addr VG_(brk_limit); /* current brk */
108
nethercote996901a2004-08-03 13:29:09 +0000109Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000110Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000111
112Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000113
nethercote820bd8c2004-09-07 23:04:49 +0000114// Note that VG_(valgrind_last) names the last byte of the section, whereas
115// the VG_(*_end) vars name the byte one past the end of the section.
116Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000117
nethercote73b526f2004-10-31 18:48:21 +0000118struct vki_rlimit VG_(client_rlimit_data);
119struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000120
fitzhardinge98abfc72003-12-16 02:05:15 +0000121/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000122static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000123
124/* client executable */
125Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000126
127/* Path to library directory */
128const Char *VG_(libdir) = VG_LIBDIR;
129
130/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000131static Int vg_argc;
132static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000133
sewardjb5f6f512005-03-10 23:59:00 +0000134/* The master thread the one which will be responsible for mopping
135 everything up at exit. Normally it is tid 1, since that's the
136 first thread created, but it may be something else after a
137 fork(). */
138ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000139
thughesad1c9562004-06-26 11:27:52 +0000140/* Application-visible file descriptor limits */
141Int VG_(fd_soft_limit) = -1;
142Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000143
nethercote4ad74312004-10-26 09:59:49 +0000144/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000145 envp[] as extracted from the client's stack at startup-time. */
146Int VG_(client_argc);
147Char** VG_(client_argv);
148Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000149
njn16de5572004-11-27 14:27:21 +0000150// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000151OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000152
sewardj51ac0872004-12-21 01:20:49 +0000153/* Indicates what arch and subarch we are running on. */
154VexArch VG_(vex_arch) = VexArch_INVALID;
155VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
156
157
sewardjde4a1d02002-03-22 01:27:54 +0000158/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000159 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000160 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000161
nethercote71980f02004-01-24 18:18:54 +0000162/* Counts downwards in VG_(run_innerloop). */
163UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000164
165/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000166ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000167
nethercote71980f02004-01-24 18:18:54 +0000168/* Tell the logging mechanism whether we are logging to a file
169 descriptor or a socket descriptor. */
170Bool VG_(logging_to_filedes) = True;
171
sewardj73cf3bc2002-11-03 03:20:15 +0000172
nethercote71980f02004-01-24 18:18:54 +0000173/*====================================================================*/
174/*=== Counters, for profiling purposes only ===*/
175/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000176
sewardjde4a1d02002-03-22 01:27:54 +0000177/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000178static UInt sanity_fast_count = 0;
179static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000180
nethercote3a42fb82004-08-03 18:08:50 +0000181static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000182{
nethercote3a42fb82004-08-03 18:08:50 +0000183 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000184 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000185 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000186 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000187
nethercote3a42fb82004-08-03 18:08:50 +0000188 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000189 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000190
nethercote71980f02004-01-24 18:18:54 +0000191 VG_(message)(Vg_DebugMsg,
192 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000193 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000194
njn9271cbc2005-03-13 05:38:25 +0000195 VG_(print_ExeContext_stats)();
196
nethercote3a42fb82004-08-03 18:08:50 +0000197 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000198 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000199 VG_(message)(Vg_DebugMsg, "");
200 VG_(message)(Vg_DebugMsg,
201 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000202 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000203 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000204 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000205 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000206 }
nethercote71980f02004-01-24 18:18:54 +0000207}
208
209
210/*====================================================================*/
211/*=== Miscellaneous global functions ===*/
212/*====================================================================*/
213
nethercotecf97ffb2004-09-09 13:40:31 +0000214static Int ptrace_setregs(Int pid, ThreadId tid)
215{
sewardj2a99cf62004-11-24 10:44:19 +0000216 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000217}
218
nethercote04d0fbc2004-01-26 16:48:06 +0000219/* Start debugger and get it to attach to this process. Called if the
220 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000221 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000222 meaningfully get the debugger to continue the program, though; to
223 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000224void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000225{
226 Int pid;
227
228 if ((pid = fork()) == 0) {
229 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000230 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000231
232 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000233 Int status;
234 Int res;
235
nethercote71980f02004-01-24 18:18:54 +0000236 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
237 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000238 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000239 kill(pid, SIGSTOP) == 0 &&
240 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000241 Char pidbuf[15];
242 Char file[30];
243 Char buf[100];
244 Char *bufptr;
245 Char *cmdptr;
246
247 VG_(sprintf)(pidbuf, "%d", pid);
248 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
249
250 bufptr = buf;
251 cmdptr = VG_(clo_db_command);
252
253 while (*cmdptr) {
254 switch (*cmdptr) {
255 case '%':
256 switch (*++cmdptr) {
257 case 'f':
258 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
259 bufptr += VG_(strlen)(file);
260 cmdptr++;
261 break;
262 case 'p':
263 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
264 bufptr += VG_(strlen)(pidbuf);
265 cmdptr++;
266 break;
267 default:
268 *bufptr++ = *cmdptr++;
269 break;
270 }
271 break;
272 default:
273 *bufptr++ = *cmdptr++;
274 break;
275 }
276 }
277
278 *bufptr++ = '\0';
279
280 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000281 res = VG_(system)(buf);
282 if (res == 0) {
283 VG_(message)(Vg_UserMsg, "");
284 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000285 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000286 } else {
287 VG_(message)(Vg_UserMsg, "Apparently failed!");
288 VG_(message)(Vg_UserMsg, "");
289 }
290 }
291
nethercote73b526f2004-10-31 18:48:21 +0000292 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000293 VG_(waitpid)(pid, &status, 0);
294 }
295}
296
297
298/* Print some helpful-ish text about unimplemented things, and give
299 up. */
300void VG_(unimplemented) ( Char* msg )
301{
302 VG_(message)(Vg_UserMsg, "");
303 VG_(message)(Vg_UserMsg,
304 "Valgrind detected that your program requires");
305 VG_(message)(Vg_UserMsg,
306 "the following unimplemented functionality:");
307 VG_(message)(Vg_UserMsg, " %s", msg);
308 VG_(message)(Vg_UserMsg,
309 "This may be because the functionality is hard to implement,");
310 VG_(message)(Vg_UserMsg,
311 "or because no reasonable program would behave this way,");
312 VG_(message)(Vg_UserMsg,
313 "or because nobody has yet needed it. In any case, let us know at");
314 VG_(message)(Vg_UserMsg,
315 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
316 VG_(message)(Vg_UserMsg,
317 "");
318 VG_(message)(Vg_UserMsg,
319 "Valgrind has to exit now. Sorry. Bye!");
320 VG_(message)(Vg_UserMsg,
321 "");
322 VG_(pp_sched_status)();
323 VG_(exit)(1);
324}
325
sewardj2a99cf62004-11-24 10:44:19 +0000326/* Get the simulated stack pointer */
327Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000328{
njncf45fd42004-11-24 16:30:22 +0000329 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000330}
331
njnea4b28c2004-11-30 16:04:58 +0000332
nethercote71980f02004-01-24 18:18:54 +0000333/*====================================================================*/
334/*=== Check we were launched by stage 1 ===*/
335/*====================================================================*/
336
337/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000338static int 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 {
sewardjb5f6f512005-03-10 23:59:00 +0000639 Bool noaugment = False;
640
nethercote71980f02004-01-24 18:18:54 +0000641 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000642 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000643
nethercotef6a1d502004-08-09 12:21:57 +0000644 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000645 Char* arg = argv[vg_argc0];
646 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000647 break;
sewardjb5f6f512005-03-10 23:59:00 +0000648 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000649 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000650 break;
651 }
sewardjb5f6f512005-03-10 23:59:00 +0000652 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000653 }
nethercotef6a1d502004-08-09 12:21:57 +0000654 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000655
656 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000657 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000658 those extra args will already be present in VALGRINDCLO.
659 (We also don't do it when --command-line-only=yes.) */
660 if (!noaugment)
661 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000662 }
663
664 if (0) {
665 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000666 for (i = 0; i < vg_argc0; i++)
667 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000668 }
669
nethercotef6a1d502004-08-09 12:21:57 +0000670 *vg_argc_out = vg_argc0;
671 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000672 *cl_argv_out = cl_argv;
673}
674
675
676/*====================================================================*/
677/*=== Environment and stack setup ===*/
678/*====================================================================*/
679
680/* Scan a colon-separated list, and call a function on each element.
681 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000682 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000683 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000684
685 This routine will return True if (*func) returns True and False if
686 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000687*/
thughes4ad52d02004-06-27 17:37:21 +0000688static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000689{
690 char *cp, *entry;
691 int end;
692
693 if (colsep == NULL ||
694 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000695 return False;
nethercote71980f02004-01-24 18:18:54 +0000696
697 entry = cp = colsep;
698
699 do {
700 end = (*cp == '\0');
701
702 if (*cp == ':' || *cp == '\0') {
703 char save = *cp;
704
705 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000706 if ((*func)(entry)) {
707 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000708 return True;
thughes21942d92004-07-12 09:35:37 +0000709 }
nethercote71980f02004-01-24 18:18:54 +0000710 *cp = save;
711 entry = cp+1;
712 }
713 cp++;
714 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000715
716 return False;
717}
718
nethercote71980f02004-01-24 18:18:54 +0000719/* Prepare the client's environment. This is basically a copy of our
720 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000721 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000722
sewardjb5f6f512005-03-10 23:59:00 +0000723 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000724
725 Yummy. String hacking in C.
726
727 If this needs to handle any more variables it should be hacked
728 into something table driven.
729 */
730static char **fix_environment(char **origenv, const char *preload)
731{
732 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000733 static const char ld_preload[] = "LD_PRELOAD=";
734 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000735 static const int ld_preload_len = sizeof(ld_preload)-1;
736 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
737 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000738 char *inject_path;
739 int inject_path_len;
740 int vgliblen = strlen(VG_(libdir));
741 char **cpp;
742 char **ret;
743 int envc;
744 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
745
746 /* Find the vg_inject.so; also make room for the tool preload
747 library */
748 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
749 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000750 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000751
752 if (preload)
753 snprintf(inject_path, inject_path_len, "%s/%s:%s",
754 VG_(libdir), inject_so, preload);
755 else
756 snprintf(inject_path, inject_path_len, "%s/%s",
757 VG_(libdir), inject_so);
758
759 /* Count the original size of the env */
760 envc = 0; /* trailing NULL */
761 for (cpp = origenv; cpp && *cpp; cpp++)
762 envc++;
763
764 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000765 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000766 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000767
768 /* copy it over */
769 for (cpp = ret; *origenv; )
770 *cpp++ = *origenv++;
771 *cpp = NULL;
772
773 vg_assert(envc == (cpp - ret));
774
775 /* Walk over the new environment, mashing as we go */
776 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000777 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000778 int len = strlen(*cpp) + inject_path_len;
779 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000780 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000781
782 snprintf(cp, len, "%s%s:%s",
783 ld_preload, inject_path, (*cpp)+ld_preload_len);
784
785 *cpp = cp;
786
787 ld_preload_done = 1;
788 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
789 *cpp = "";
790 }
791 }
792
793 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000794 if (!ld_preload_done) {
795 int len = ld_preload_len + inject_path_len;
796 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000797 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000798
799 snprintf(cp, len, "%s%s",
800 ld_preload, inject_path);
801
802 ret[envc++] = cp;
803 }
804
sewardjb5f6f512005-03-10 23:59:00 +0000805 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000806 ret[envc] = NULL;
807
808 return ret;
809}
810
811extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000812
813/* Add a string onto the string table, and return its address */
814static char *copy_str(char **tab, const char *str)
815{
816 char *cp = *tab;
817 char *orig = cp;
818
819 while(*str)
820 *cp++ = *str++;
821 *cp++ = '\0';
822
823 if (0)
nethercote545fe672004-11-01 16:52:43 +0000824 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000825
826 *tab = cp;
827
828 return orig;
829}
830
831/*
832 This sets up the client's initial stack, containing the args,
833 environment and aux vector.
834
835 The format of the stack is:
836
837 higher address +-----------------+
838 | Trampoline code |
839 +-----------------+
840 | |
841 : string table :
842 | |
843 +-----------------+
844 | AT_NULL |
845 - -
846 | auxv |
847 +-----------------+
848 | NULL |
849 - -
850 | envp |
851 +-----------------+
852 | NULL |
853 - -
854 | argv |
855 +-----------------+
856 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000857 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000858 | undefined |
859 : :
860 */
nethercotec25c4492004-10-18 11:52:17 +0000861static Addr setup_client_stack(void* init_sp,
862 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000863 const struct exeinfo *info,
864 UInt** client_auxv)
865{
nethercotee567e702004-07-10 17:49:17 +0000866 void* res;
nethercote71980f02004-01-24 18:18:54 +0000867 char **cpp;
868 char *strtab; /* string table */
869 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000870 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000871 struct ume_auxv *auxv;
872 const struct ume_auxv *orig_auxv;
873 const struct ume_auxv *cauxv;
874 unsigned stringsize; /* total size of strings in bytes */
875 unsigned auxsize; /* total size of auxv in bytes */
876 int argc; /* total argc */
877 int envc; /* total number of env vars */
878 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000879 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000880
881 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000882 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000883
884 /* ==================== compute sizes ==================== */
885
886 /* first of all, work out how big the client stack will be */
887 stringsize = 0;
888
889 /* paste on the extra args if the loader needs them (ie, the #!
890 interpreter and its argument) */
891 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000892 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000893 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000894 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000895 }
nethercoted6a56872004-07-26 15:32:47 +0000896 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000897 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000898 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000899 }
900
901 /* now scan the args we're given... */
902 for (cpp = orig_argv; *cpp; cpp++) {
903 argc++;
904 stringsize += strlen(*cpp) + 1;
905 }
906
907 /* ...and the environment */
908 envc = 0;
909 for (cpp = orig_envp; cpp && *cpp; cpp++) {
910 envc++;
911 stringsize += strlen(*cpp) + 1;
912 }
913
914 /* now, how big is the auxv? */
915 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
916 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
917 if (cauxv->a_type == AT_PLATFORM)
918 stringsize += strlen(cauxv->u.a_ptr) + 1;
919 auxsize += sizeof(*cauxv);
920 }
921
922 /* OK, now we know how big the client stack is */
923 stacksize =
924 sizeof(int) + /* argc */
925 sizeof(char **)*argc + /* argv */
926 sizeof(char **) + /* terminal NULL */
927 sizeof(char **)*envc + /* envp */
928 sizeof(char **) + /* terminal NULL */
929 auxsize + /* auxv */
930 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000931 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000932
sewardj79048ce2005-02-18 08:28:32 +0000933 if (0) VG_(printf)("stacksize = %d\n", stacksize);
934
nethercotef84f6952004-07-15 14:58:33 +0000935 // decide where stack goes!
936 VG_(clstk_end) = VG_(client_end);
937
nethercote73b526f2004-10-31 18:48:21 +0000938 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000939
nethercote71980f02004-01-24 18:18:54 +0000940 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000941 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000942 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
943
nethercote71980f02004-01-24 18:18:54 +0000944 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000945 stringbase = strtab = (char *)(VG_(client_trampoline_code)
946 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000947
948 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000949
sewardj79048ce2005-02-18 08:28:32 +0000950 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000951 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000952 "clstk_base %p\n"
953 "clstk_end %p\n",
954 stringsize, auxsize, stacksize,
955 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000956
nethercote71980f02004-01-24 18:18:54 +0000957 /* ==================== allocate space ==================== */
958
959 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000960 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000961 PROT_READ | PROT_WRITE | PROT_EXEC,
962 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
963 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000964
965 /* ==================== copy client stack ==================== */
966
nethercotea3c3cf22004-11-01 18:38:00 +0000967 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000968
969 /* --- argc --- */
970 *ptr++ = argc; /* client argc */
971
972 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000973 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000974 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000975 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000976 }
nethercoted6a56872004-07-26 15:32:47 +0000977 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000978 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000979 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000980 }
981 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000982 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000983 }
984 *ptr++ = 0;
985
986 /* --- envp --- */
987 VG_(client_envp) = (Char **)ptr;
988 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000989 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000990 *ptr++ = 0;
991
992 /* --- auxv --- */
993 auxv = (struct ume_auxv *)ptr;
994 *client_auxv = (UInt *)auxv;
995
996 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
997 /* copy the entry... */
998 *auxv = *orig_auxv;
999
1000 /* ...and fix up the copy */
1001 switch(auxv->a_type) {
1002 case AT_PHDR:
1003 if (info->phdr == 0)
1004 auxv->a_type = AT_IGNORE;
1005 else
1006 auxv->u.a_val = info->phdr;
1007 break;
1008
1009 case AT_PHNUM:
1010 if (info->phdr == 0)
1011 auxv->a_type = AT_IGNORE;
1012 else
1013 auxv->u.a_val = info->phnum;
1014 break;
1015
1016 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001017 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001018 break;
1019
1020 case AT_PLATFORM: /* points to a platform description string */
1021 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1022 break;
1023
1024 case AT_ENTRY:
1025 auxv->u.a_val = info->entry;
1026 break;
1027
1028 case AT_IGNORE:
1029 case AT_EXECFD:
1030 case AT_PHENT:
1031 case AT_PAGESZ:
1032 case AT_FLAGS:
1033 case AT_NOTELF:
1034 case AT_UID:
1035 case AT_EUID:
1036 case AT_GID:
1037 case AT_EGID:
1038 case AT_CLKTCK:
1039 case AT_HWCAP:
1040 case AT_FPUCW:
1041 case AT_DCACHEBSIZE:
1042 case AT_ICACHEBSIZE:
1043 case AT_UCACHEBSIZE:
1044 /* All these are pointerless, so we don't need to do anything
1045 about them. */
1046 break;
1047
1048 case AT_SECURE:
1049 /* If this is 1, then it means that this program is running
1050 suid, and therefore the dynamic linker should be careful
1051 about LD_PRELOAD, etc. However, since stage1 (the thing
1052 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001053 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001054 set AT_SECURE to 0. */
1055 auxv->u.a_val = 0;
1056 break;
1057
1058 case AT_SYSINFO:
1059 /* Leave this unmolested for now, but we'll update it later
1060 when we set up the client trampoline code page */
1061 break;
1062
1063 case AT_SYSINFO_EHDR:
1064 /* Trash this, because we don't reproduce it */
1065 auxv->a_type = AT_IGNORE;
1066 break;
1067
1068 default:
1069 /* stomp out anything we don't know about */
1070 if (0)
nethercote545fe672004-11-01 16:52:43 +00001071 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001072 auxv->a_type = AT_IGNORE;
1073 break;
1074
1075 }
1076 }
1077 *auxv = *orig_auxv;
1078 vg_assert(auxv->a_type == AT_NULL);
1079
njnc6168192004-11-29 13:54:10 +00001080// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1081// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001082#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001083 /* --- trampoline page --- */
1084 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1085 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001086#endif
nethercotef84f6952004-07-15 14:58:33 +00001087
nethercote71980f02004-01-24 18:18:54 +00001088 vg_assert((strtab-stringbase) == stringsize);
1089
nethercote5ee67ca2004-06-22 14:00:09 +00001090 /* We know the initial ESP is pointing at argc/argv */
1091 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001092 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001093
sewardj79048ce2005-02-18 08:28:32 +00001094 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001095 return cl_esp;
1096}
1097
1098/*====================================================================*/
1099/*=== Find executable ===*/
1100/*====================================================================*/
1101
thughes4ad52d02004-06-27 17:37:21 +00001102static const char* executable_name;
1103
1104static Bool match_executable(const char *entry) {
1105 char buf[strlen(entry) + strlen(executable_name) + 2];
1106
1107 /* empty PATH element means . */
1108 if (*entry == '\0')
1109 entry = ".";
1110
1111 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1112
1113 if (access(buf, R_OK|X_OK) == 0) {
1114 executable_name = strdup(buf);
1115 vg_assert(NULL != executable_name);
1116 return True;
1117 }
1118 return False;
1119}
1120
nethercote71980f02004-01-24 18:18:54 +00001121static const char* find_executable(const char* exec)
1122{
1123 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001124 executable_name = exec;
1125 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001126 /* no '/' - we need to search the path */
1127 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001128 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001129 }
thughes4ad52d02004-06-27 17:37:21 +00001130 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001131}
1132
1133
1134/*====================================================================*/
1135/*=== Loading tools ===*/
1136/*====================================================================*/
1137
1138static void list_tools(void)
1139{
1140 DIR *dir = opendir(VG_(libdir));
1141 struct dirent *de;
1142 int first = 1;
1143
1144 if (dir == NULL) {
1145 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001146 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001147 return;
1148 }
1149
nethercotef4928da2004-06-15 10:54:40 +00001150 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001151 int len = strlen(de->d_name);
1152
njn063c5402004-11-22 16:58:05 +00001153 /* look for vgtool_TOOL.so names */
1154 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1155 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001156 VG_STREQ(de->d_name + len - 3, ".so")) {
1157 if (first) {
1158 fprintf(stderr, "Available tools:\n");
1159 first = 0;
1160 }
1161 de->d_name[len-3] = '\0';
1162 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001163 }
1164 }
1165
1166 closedir(dir);
1167
1168 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001169 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1170 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001171}
1172
1173
1174/* Find and load a tool, and check it looks ok. Also looks to see if there's
1175 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1176static void load_tool( const char *toolname, void** handle_out,
1177 ToolInfo** toolinfo_out, char **preloadpath_out )
1178{
1179 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001180 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001181 char buf[len];
1182 void* handle;
1183 ToolInfo* toolinfo;
1184 char* preloadpath = NULL;
1185 Int* vg_malloc_redzonep;
1186
1187 // XXX: allowing full paths for --tool option -- does it make sense?
1188 // Doesn't allow for vgpreload_<tool>.so.
1189
1190 if (strchr(toolname, '/') != 0) {
1191 /* toolname contains '/', and so must be a pathname */
1192 handle = dlopen(toolname, RTLD_NOW);
1193 } else {
1194 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001195 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001196 handle = dlopen(buf, RTLD_NOW);
1197
1198 if (handle != NULL) {
1199 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1200 if (access(buf, R_OK) == 0) {
1201 preloadpath = strdup(buf);
1202 vg_assert(NULL != preloadpath);
1203 }
1204 }
1205 }
1206
1207 ok = (NULL != handle);
1208 if (!ok) {
1209 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1210 goto bad_load;
1211 }
1212
njn26f02512004-11-22 18:33:15 +00001213 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001214 ok = (NULL != toolinfo);
1215 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001216 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001217 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1218 goto bad_load;
1219 }
1220
1221 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1222 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001223 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001224 if (!ok) {
1225 fprintf(stderr, "Error:\n"
1226 " Tool and core interface versions do not match.\n"
1227 " Interface version used by core is: %d.%d (size %d)\n"
1228 " Interface version used by tool is: %d.%d (size %d)\n"
1229 " The major version numbers must match.\n",
1230 VG_CORE_INTERFACE_MAJOR_VERSION,
1231 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001232 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001233 toolinfo->interface_major_version,
1234 toolinfo->interface_minor_version,
1235 toolinfo->sizeof_ToolInfo);
1236 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1237 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001238 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001239 else
nethercote996901a2004-08-03 13:29:09 +00001240 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001241 goto bad_load;
1242 }
1243
1244 // Set redzone size for V's allocator
1245 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1246 if ( NULL != vg_malloc_redzonep ) {
1247 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1248 }
1249
1250 vg_assert(NULL != handle && NULL != toolinfo);
1251 *handle_out = handle;
1252 *toolinfo_out = toolinfo;
1253 *preloadpath_out = preloadpath;
1254 return;
1255
1256
1257 bad_load:
1258 if (handle != NULL)
1259 dlclose(handle);
1260
nethercotef4928da2004-06-15 10:54:40 +00001261 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001262 list_tools();
1263 exit(127);
1264}
1265
nethercotef4928da2004-06-15 10:54:40 +00001266
1267/*====================================================================*/
1268/*=== Command line errors ===*/
1269/*====================================================================*/
1270
1271static void abort_msg ( void )
1272{
nethercotef8548672004-06-21 12:42:35 +00001273 VG_(clo_log_to) = VgLogTo_Fd;
1274 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001275}
1276
1277void VG_(bad_option) ( Char* opt )
1278{
1279 abort_msg();
1280 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1281 VG_(printf)("valgrind: Use --help for more information.\n");
1282 VG_(exit)(1);
1283}
1284
nethercotef4928da2004-06-15 10:54:40 +00001285static void missing_prog ( void )
1286{
1287 abort_msg();
1288 VG_(printf)("valgrind: no program specified\n");
1289 VG_(printf)("valgrind: Use --help for more information.\n");
1290 VG_(exit)(1);
1291}
1292
1293static void config_error ( Char* msg )
1294{
1295 abort_msg();
1296 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1297 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1298 VG_(exit)(1);
1299}
1300
1301
nethercote71980f02004-01-24 18:18:54 +00001302/*====================================================================*/
1303/*=== Loading the client ===*/
1304/*====================================================================*/
1305
nethercotef4928da2004-06-15 10:54:40 +00001306static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001307 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1308{
1309 // If they didn't specify an executable with --exec, and didn't specify
1310 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001311 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001312 if (cl_argv[0] == NULL ||
1313 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1314 {
nethercotef4928da2004-06-15 10:54:40 +00001315 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001316 }
1317 }
1318
1319 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001320 info->exe_base = VG_(client_base);
1321 info->exe_end = VG_(client_end);
1322 info->argv = cl_argv;
1323
nethercotef4928da2004-06-15 10:54:40 +00001324 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001325 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001326 // Totally zero 'info' before continuing.
1327 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001328 } else {
1329 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001330 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001331 ret = do_exec(exec, info);
1332 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001333 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1334 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001335 exit(127);
1336 }
1337 }
1338
1339 /* Copy necessary bits of 'info' that were filled in */
1340 *client_eip = info->init_eip;
1341 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1342}
1343
nethercote969ecf12004-10-13 17:29:01 +00001344/*====================================================================*/
1345/*=== Address space unpadding ===*/
1346/*====================================================================*/
1347
1348typedef struct {
1349 char* killpad_start;
1350 char* killpad_end;
1351 struct stat* killpad_padstat;
1352} killpad_extra;
1353
1354static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1355 int maj, int min, int ino, void* ex)
1356{
1357 killpad_extra* extra = ex;
1358 void *b, *e;
1359 int res;
1360
1361 vg_assert(NULL != extra->killpad_padstat);
1362
1363 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1364 extra->killpad_padstat->st_ino != ino)
1365 return 1;
1366
1367 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1368 return 1;
1369
1370 if (segstart <= extra->killpad_start)
1371 b = extra->killpad_start;
1372 else
1373 b = segstart;
1374
1375 if (segend >= extra->killpad_end)
1376 e = extra->killpad_end;
1377 else
1378 e = segend;
1379
1380 res = munmap(b, (char *)e-(char *)b);
1381 vg_assert(0 == res);
1382
1383 return 1;
1384}
1385
1386// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001387static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001388{
1389 static struct stat padstat;
1390 killpad_extra extra;
1391 int res;
1392
sewardjb5f6f512005-03-10 23:59:00 +00001393 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001394
1395 res = fstat(padfile, &padstat);
1396 vg_assert(0 == res);
1397 extra.killpad_padstat = &padstat;
1398 extra.killpad_start = start;
1399 extra.killpad_end = end;
1400 foreach_map(killpad, &extra);
1401}
1402
sewardj2c5ffbe2005-03-12 13:32:06 +00001403static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001404{
1405 int res = close(padfile);
1406 vg_assert(0 == res);
1407}
1408
nethercote71980f02004-01-24 18:18:54 +00001409
1410/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001411/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001412/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001413
njn25e49d8e72002-09-23 09:36:25 +00001414/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001415VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001416Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001417Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001418Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001419Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001420Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001421Int VG_(clo_verbosity) = 1;
1422Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001423Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001424
nethercotef1e5e152004-09-01 23:58:16 +00001425/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001426 fd is initially stdout, for --help, but gets moved to stderr by default
1427 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001428VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001429Int VG_(clo_log_fd) = 1;
1430Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001431
thughes6233a382004-08-21 11:10:44 +00001432Bool VG_(clo_time_stamp) = False;
1433
sewardj6024b212003-07-13 10:54:33 +00001434Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001435Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001436Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001437Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001438UChar VG_(clo_trace_flags) = 0; // 00000000b
1439UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001440Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001441Bool VG_(clo_trace_syscalls) = False;
1442Bool VG_(clo_trace_signals) = False;
1443Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001444Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001445Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001446Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001447Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001448Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001449Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001450Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001451Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001452Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001453Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001454Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001455Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001456Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001457Bool VG_(clo_show_emwarns) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001458
jsgf855d93d2003-10-13 22:26:55 +00001459static Bool VG_(clo_wait_for_gdb) = False;
1460
sewardjde4a1d02002-03-22 01:27:54 +00001461
sewardj2c5ffbe2005-03-12 13:32:06 +00001462static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001463{
njn25e49d8e72002-09-23 09:36:25 +00001464 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001465"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001466"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001467" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001468" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001469" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001470" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001471" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001472" -q --quiet run silently; only print error msgs\n"
1473" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001474" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001475" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001476" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001477"\n"
1478" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001479" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001480" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001481" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001482" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001483" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001484"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001485" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001486" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1487" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001488" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001489" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001490" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001491" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001492" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1493" --show-below-main=no|yes continue stack traces below main() [no]\n"
1494" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001495" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001496" --db-attach=no|yes start debugger when errors detected? [no]\n"
1497" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1498" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001499"\n";
njn7cf0bd32002-06-08 13:36:03 +00001500
njn25e49d8e72002-09-23 09:36:25 +00001501 Char* usage2 =
1502"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001503" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001504" --sanity-level=<number> level of sanity checking to do [1]\n"
1505" --single-step=no|yes translate each instr separately? [no]\n"
1506" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001507" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001508" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001509" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1510" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001511" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001512" --trace-syscalls=no|yes show all system calls? [no]\n"
1513" --trace-signals=no|yes show signal handling details? [no]\n"
1514" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001515" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001516" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001517#if 0
1518" --model-pthreads=yes|no model the pthreads library [no]\n"
1519#endif
1520" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001521"\n"
1522" --vex-iropt-verbosity 0 .. 9 [0]\n"
1523" --vex-iropt-level 0 .. 2 [2]\n"
1524" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001525" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1526" --vex-guest-max-insns 1 .. 100 [50]\n"
1527" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1528"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001529" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001530" 1000 0000 show conversion into IR\n"
1531" 0100 0000 show after initial opt\n"
1532" 0010 0000 show after instrumentation\n"
1533" 0001 0000 show after second opt\n"
1534" 0000 1000 show after tree building\n"
1535" 0000 0100 show selecting insns\n"
1536" 0000 0010 show after reg-alloc\n"
1537" 0000 0001 show final assembly\n"
1538"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001539" debugging options for Valgrind tools that report errors\n"
1540" --dump-error=<number> show translation for basic block associated\n"
1541" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001542"\n";
njn3e884182003-04-15 13:03:23 +00001543
1544 Char* usage3 =
1545"\n"
nethercote71980f02004-01-24 18:18:54 +00001546" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001547"\n"
njn53612422005-03-12 16:22:54 +00001548" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001549" and licensed under the GNU General Public License, version 2.\n"
1550" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001551"\n"
nethercote137bc552003-11-14 17:47:54 +00001552" Tools are copyright and licensed by their authors. See each\n"
1553" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001554"\n";
njn7cf0bd32002-06-08 13:36:03 +00001555
fitzhardinge98abfc72003-12-16 02:05:15 +00001556 VG_(printf)(usage1);
1557 if (VG_(details).name) {
1558 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001559 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001560 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001561 else
1562 VG_(printf)(" (none)\n");
1563 }
nethercote6c999f22004-01-31 22:55:15 +00001564 if (debug_help) {
1565 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001566
nethercote6c999f22004-01-31 22:55:15 +00001567 if (VG_(details).name) {
1568 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1569
1570 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001571 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001572 else
1573 VG_(printf)(" (none)\n");
1574 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001575 }
nethercote421281e2003-11-20 16:20:55 +00001576 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001577 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001578}
sewardjde4a1d02002-03-22 01:27:54 +00001579
nethercote71980f02004-01-24 18:18:54 +00001580static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001581 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001582{
nethercote71980f02004-01-24 18:18:54 +00001583 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001584
sewardj8b635a42004-11-22 19:01:47 +00001585 LibVEX_default_VexControl(& VG_(clo_vex_control));
1586
nethercote71980f02004-01-24 18:18:54 +00001587 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001588 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001589
nethercotef6a1d502004-08-09 12:21:57 +00001590 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001591 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001592 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001593
nethercotef6a1d502004-08-09 12:21:57 +00001594 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1595 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001596 *need_help = 1;
1597
nethercotef6a1d502004-08-09 12:21:57 +00001598 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001599 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001600
nethercotef6c99d72004-11-09 14:35:43 +00001601 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001602 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001603
nethercotef6a1d502004-08-09 12:21:57 +00001604 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1605 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001606 }
1607 }
nethercote71980f02004-01-24 18:18:54 +00001608}
1609
nethercote5ee67ca2004-06-22 14:00:09 +00001610static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001611{
nethercotef8548672004-06-21 12:42:35 +00001612 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001613 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001614
nethercotee1730692003-11-20 10:38:07 +00001615 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001616 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001617
sewardj19d81412002-06-03 01:10:40 +00001618 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001619 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001620 config_error("Please use absolute paths in "
1621 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001622
njnc6168192004-11-29 13:54:10 +00001623// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001624#ifdef __x86__
1625 {
sewardjb5f6f512005-03-10 23:59:00 +00001626 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001627 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1628 switch(auxp[0]) {
1629 case AT_SYSINFO:
1630 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1631 break;
1632 }
1633 }
1634 }
1635#endif
sewardjde4a1d02002-03-22 01:27:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001638
nethercotef6a1d502004-08-09 12:21:57 +00001639 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001640 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001641
thughes3bfd5a02004-07-18 08:05:44 +00001642 /* Look for a colon in the switch name */
1643 while (*colon && *colon != ':' && *colon != '=')
1644 colon++;
nethercote71980f02004-01-24 18:18:54 +00001645
1646 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001647 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001648 if (VG_CLO_STREQN(2, arg, "--") &&
1649 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1650 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1651 {
1652 // prefix matches, convert "--toolname:foo" to "--foo"
1653 if (0)
1654 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001655 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001656 arg[0] = '-';
1657 arg[1] = '-';
1658
1659 } else {
1660 // prefix doesn't match, skip to next arg
1661 continue;
1662 }
1663 }
1664
fitzhardinge98abfc72003-12-16 02:05:15 +00001665 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001666 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001667 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001668 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001669 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001670 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001671 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001672
nethercote71980f02004-01-24 18:18:54 +00001673 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001674 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001675
nethercote71980f02004-01-24 18:18:54 +00001676 else if (VG_CLO_STREQ(arg, "-v") ||
1677 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001678 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001679
nethercote71980f02004-01-24 18:18:54 +00001680 else if (VG_CLO_STREQ(arg, "-q") ||
1681 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001682 VG_(clo_verbosity)--;
1683
nethercote27fec902004-06-16 21:26:32 +00001684 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001685 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1686 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1687 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001688 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001689 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
sewardjb1131a82005-03-19 15:12:21 +00001690 else VG_BOOL_CLO("--show-emwarns", VG_(clo_show_emwarns))
nethercote27fec902004-06-16 21:26:32 +00001691 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1692 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1693 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001694 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001695 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1696 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1697 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1698 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1699 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001700 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001701 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001702 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001703 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001704 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001705
nethercote27fec902004-06-16 21:26:32 +00001706 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1707 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001708
nethercote27fec902004-06-16 21:26:32 +00001709 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1710 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1711 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001712 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1713 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001714
sewardj8b635a42004-11-22 19:01:47 +00001715 else VG_BNUM_CLO("--vex-iropt-verbosity",
1716 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1717 else VG_BNUM_CLO("--vex-iropt-level",
1718 VG_(clo_vex_control).iropt_level, 0, 2)
1719 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1720 VG_(clo_vex_control).iropt_precise_memory_exns)
1721 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1722 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1723 else VG_BNUM_CLO("--vex-guest-max-insns",
1724 VG_(clo_vex_control).guest_max_insns, 1, 100)
1725 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1726 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1727
nethercotef8548672004-06-21 12:42:35 +00001728 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001729 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001730 VG_(clo_log_to) = VgLogTo_Fd;
1731 VG_(clo_log_name) = NULL;
1732 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1733 }
1734 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1735 VG_(clo_log_to) = VgLogTo_Fd;
1736 VG_(clo_log_name) = NULL;
1737 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001738 }
1739
nethercotef8548672004-06-21 12:42:35 +00001740 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001741 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001742 VG_(clo_log_to) = VgLogTo_File;
1743 VG_(clo_log_name) = &arg[10];
1744 }
1745 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1746 VG_(clo_log_to) = VgLogTo_File;
1747 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001748 }
sewardj603d4102005-01-11 14:01:02 +00001749 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1750 VG_(clo_log_to) = VgLogTo_FileExactly;
1751 VG_(clo_log_name) = &arg[19];
1752 }
sewardjde4a1d02002-03-22 01:27:54 +00001753
nethercotef8548672004-06-21 12:42:35 +00001754 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001755 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001756 VG_(clo_log_to) = VgLogTo_Socket;
1757 VG_(clo_log_name) = &arg[12];
1758 }
1759 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1760 VG_(clo_log_to) = VgLogTo_Socket;
1761 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001762 }
1763
nethercote71980f02004-01-24 18:18:54 +00001764 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001765 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001766 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001767 VG_(message)(Vg_UserMsg,
1768 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001769 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001770 }
nethercote71980f02004-01-24 18:18:54 +00001771 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001772 VG_(clo_n_suppressions)++;
1773 }
sewardjde4a1d02002-03-22 01:27:54 +00001774
sewardjfa8ec112005-01-19 11:55:34 +00001775 /* "stuvwxyz" --> stuvwxyz (binary) */
1776 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1777 Int j;
1778 char* opt = & arg[14];
1779
1780 if (8 != VG_(strlen)(opt)) {
1781 VG_(message)(Vg_UserMsg,
1782 "--trace-flags argument must have 8 digits");
1783 VG_(bad_option)(arg);
1784 }
1785 for (j = 0; j < 8; j++) {
1786 if ('0' == opt[j]) { /* do nothing */ }
1787 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1788 else {
1789 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1790 "contain 0s and 1s");
1791 VG_(bad_option)(arg);
1792 }
1793 }
1794 }
1795
1796 /* "stuvwxyz" --> stuvwxyz (binary) */
1797 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001798 Int j;
nethercote71980f02004-01-24 18:18:54 +00001799 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001800
sewardj2a99cf62004-11-24 10:44:19 +00001801 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001802 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001803 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001804 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001805 }
sewardj8b635a42004-11-22 19:01:47 +00001806 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001807 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001808 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001809 else {
sewardjfa8ec112005-01-19 11:55:34 +00001810 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001811 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001812 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001813 }
1814 }
1815 }
sewardjde4a1d02002-03-22 01:27:54 +00001816
sewardjc771b292004-11-30 18:55:21 +00001817 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1818
sewardjd153fae2005-01-10 17:24:47 +00001819 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1820 VG_(clo_gen_suppressions) = 0;
1821 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1822 VG_(clo_gen_suppressions) = 1;
1823 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1824 VG_(clo_gen_suppressions) = 2;
1825
nethercote71980f02004-01-24 18:18:54 +00001826 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001827 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001828 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001829 }
njn8c0b3bb2005-03-12 21:20:39 +00001830 skip_arg:
1831 if (arg != vg_argv[i])
1832 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001833 }
1834
sewardj998d40d2004-12-06 14:24:52 +00001835 /* Make VEX control parameters sane */
1836
1837 if (VG_(clo_vex_control).guest_chase_thresh
1838 >= VG_(clo_vex_control).guest_max_insns)
1839 VG_(clo_vex_control).guest_chase_thresh
1840 = VG_(clo_vex_control).guest_max_insns - 1;
1841
1842 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1843 VG_(clo_vex_control).guest_chase_thresh = 0;
1844
1845 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001846
njnf9ebf672003-05-12 21:41:30 +00001847 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001848 VG_(clo_verbosity) = 0;
1849
nethercote04d0fbc2004-01-26 16:48:06 +00001850 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001851 VG_(message)(Vg_UserMsg, "");
1852 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001853 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001854 VG_(message)(Vg_UserMsg,
1855 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001856 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001857 }
1858
nethercotef8548672004-06-21 12:42:35 +00001859 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001860 should be connected to whatever sink has been selected, and we
1861 indiscriminately chuck stuff into it without worrying what the
1862 nature of it is. Oh the wonder of Unix streams. */
1863
nethercotee1730692003-11-20 10:38:07 +00001864 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001865 the terminal any problems to do with processing command line
1866 opts. */
nethercotef8548672004-06-21 12:42:35 +00001867 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001868 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001869
1870 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001871
sewardj4cf05692002-10-27 20:28:29 +00001872 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001873 vg_assert(VG_(clo_log_name) == NULL);
1874 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001875 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001876
sewardj4cf05692002-10-27 20:28:29 +00001877 case VgLogTo_File: {
1878 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001879 Int seq = 0;
1880 Int pid = VG_(getpid)();
1881
nethercotef8548672004-06-21 12:42:35 +00001882 vg_assert(VG_(clo_log_name) != NULL);
1883 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001884
nethercote71980f02004-01-24 18:18:54 +00001885 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001886 if (seq == 0)
1887 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001888 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001889 else
1890 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001891 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001892 seq++;
1893
nethercotef8548672004-06-21 12:42:35 +00001894 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001895 = VG_(open)(logfilename,
1896 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1897 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001898 if (eventually_log_fd >= 0) {
1899 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001900 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001901 } else {
nethercotef8548672004-06-21 12:42:35 +00001902 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001903 VG_(message)(Vg_UserMsg,
1904 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001905 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001906 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001907 "--log-file=<file> (didn't work out for some reason.)");
1908 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001909 }
1910 }
1911 }
sewardj603d4102005-01-11 14:01:02 +00001912 break; /* switch (VG_(clo_log_to)) */
1913 }
1914
1915 case VgLogTo_FileExactly: {
1916 Char logfilename[1000];
1917
1918 vg_assert(VG_(clo_log_name) != NULL);
1919 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1920 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1921
1922 eventually_log_fd
1923 = VG_(open)(logfilename,
1924 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1925 VKI_S_IRUSR|VKI_S_IWUSR);
1926 if (eventually_log_fd >= 0) {
1927 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1928 }
1929 else if (eventually_log_fd != -VKI_EEXIST) {
1930 VG_(message)(Vg_UserMsg,
1931 "Can't create/open log file `%s'; giving up!",
1932 VG_(clo_log_name));
1933 VG_(bad_option)(
1934 "--log-file-exactly=<file> (didn't work out for some reason.)");
1935 /*NOTREACHED*/
1936 }
1937 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001938 }
1939
1940 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001941 vg_assert(VG_(clo_log_name) != NULL);
1942 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1943 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1944 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001945 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001946 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001947 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001948 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001949 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001950 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001951 }
nethercotef8548672004-06-21 12:42:35 +00001952 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001953 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001954 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001955 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001956 VG_(message)(Vg_UserMsg,
1957 "Log messages will sent to stderr instead." );
1958 VG_(message)(Vg_UserMsg,
1959 "" );
1960 /* We don't change anything here. */
1961 } else {
nethercotef8548672004-06-21 12:42:35 +00001962 vg_assert(eventually_log_fd > 0);
1963 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001964 VG_(logging_to_filedes) = False;
1965 }
sewardj73cf3bc2002-11-03 03:20:15 +00001966 break;
1967 }
1968
sewardj4cf05692002-10-27 20:28:29 +00001969 }
1970
nethercotef8548672004-06-21 12:42:35 +00001971 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001972 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001973 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001974 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1975 else {
nethercotef8548672004-06-21 12:42:35 +00001976 VG_(clo_log_fd) = eventually_log_fd;
1977 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001978 }
1979
sewardj4cf05692002-10-27 20:28:29 +00001980 /* Ok, the logging sink is running now. Print a suitable preamble.
1981 If logging to file or a socket, write details of parent PID and
1982 command line args, to help people trying to interpret the
1983 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001984
sewardj83adf412002-05-01 01:25:45 +00001985 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001986 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001987 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001988 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001989 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001990 NULL == VG_(details).version
1991 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001992 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001993 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001994
njnd04b7c62002-10-03 14:05:52 +00001995 /* Core details */
1996 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001997 "Using LibVEX rev %s, a library for dynamic binary translation.",
1998 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001999 VG_(message)(Vg_UserMsg,
2000 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2001 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002002 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002003 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002004 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002005 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002006 }
2007
nethercotec1e395d2003-11-10 13:26:49 +00002008 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002009 VG_(message)(Vg_UserMsg, "");
2010 VG_(message)(Vg_UserMsg,
2011 "My PID = %d, parent PID = %d. Prog and args are:",
2012 VG_(getpid)(), VG_(getppid)() );
2013 for (i = 0; i < VG_(client_argc); i++)
2014 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2015 }
2016
sewardjde4a1d02002-03-22 01:27:54 +00002017 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002018 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002019 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002020 VG_(message)(Vg_DebugMsg, "");
2021 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2022 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002023 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002024 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002025
njn1fd5eb22005-03-13 05:43:23 +00002026 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002027 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002028 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002029 }
nethercotea70f7352004-04-18 12:08:46 +00002030
njn1fd5eb22005-03-13 05:43:23 +00002031 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002032 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2033 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002034 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002035 } else {
2036 #define BUF_LEN 256
2037 Char version_buf[BUF_LEN];
2038 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2039 vg_assert(n <= 256);
2040 if (n > 0) {
2041 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002042 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002043 } else {
njn1fd5eb22005-03-13 05:43:23 +00002044 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002045 }
2046 VG_(close)(fd);
2047 #undef BUF_LEN
2048 }
sewardjde4a1d02002-03-22 01:27:54 +00002049 }
2050
fitzhardinge98abfc72003-12-16 02:05:15 +00002051 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002052 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002053 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002054 needs one, load the default */
2055 static const Char default_supp[] = "default.supp";
2056 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2057 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2058 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2059 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2060 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002061 }
sewardj4cf05692002-10-27 20:28:29 +00002062
sewardjd153fae2005-01-10 17:24:47 +00002063 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002064 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002065 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002066 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002067 VG_(message)(Vg_UserMsg,
2068 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002069 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002070 }
sewardjde4a1d02002-03-22 01:27:54 +00002071}
2072
nethercotef6a1d502004-08-09 12:21:57 +00002073// Build the string for VALGRINDCLO.
2074Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2075{
2076 /* If we're tracing the children, then we need to start it
2077 with our starter+arguments, which are copied into VALGRINDCLO,
2078 except the --exec= option is changed if present.
2079 */
2080 Int i;
2081 Char *exec;
2082 Char *cp;
2083 Char *optvar;
2084 Int optlen, execlen;
2085
2086 // All these allocated blocks are not free - because we're either
2087 // going to exec, or panic when we fail.
2088
2089 // Create --exec= option: "--exec=<exename>"
2090 exec = VG_(arena_malloc)(VG_AR_CORE,
2091 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2092 vg_assert(NULL != exec);
2093 VG_(sprintf)(exec, "--exec=%s", exename);
2094
2095 // Allocate space for optvar (may overestimate by counting --exec twice,
2096 // no matter)
2097 optlen = 1;
2098 for (i = 0; i < vg_argc; i++)
2099 optlen += VG_(strlen)(vg_argv[i]) + 1;
2100 optlen += VG_(strlen)(exec)+1;
2101 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2102
2103 // Copy all valgrind args except the old --exec (if present)
2104 // VG_CLO_SEP is the separator.
2105 cp = optvar;
2106 for (i = 1; i < vg_argc; i++) {
2107 Char *arg = vg_argv[i];
2108
2109 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2110 // don't copy existing --exec= arg
2111 } else if (VG_(strcmp)(arg, "--") == 0) {
2112 // stop at "--"
2113 break;
2114 } else {
2115 // copy non "--exec" arg
2116 Int len = VG_(strlen)(arg);
2117 VG_(memcpy)(cp, arg, len);
2118 cp += len;
2119 *cp++ = VG_CLO_SEP;
2120 }
2121 }
2122 // Add the new --exec= option
2123 execlen = VG_(strlen)(exec);
2124 VG_(memcpy)(cp, exec, execlen);
2125 cp += execlen;
2126 *cp++ = VG_CLO_SEP;
2127
2128 *cp = '\0';
2129
2130 return optvar;
2131}
2132
2133// Build "/proc/self/fd/<execfd>".
2134Char* VG_(build_child_exename)( void )
2135{
2136 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2137 vg_assert(NULL != exename);
2138 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2139 return exename;
2140}
2141
sewardjde4a1d02002-03-22 01:27:54 +00002142
nethercote71980f02004-01-24 18:18:54 +00002143/*====================================================================*/
2144/*=== File descriptor setup ===*/
2145/*====================================================================*/
2146
2147static void setup_file_descriptors(void)
2148{
2149 struct vki_rlimit rl;
2150
2151 /* Get the current file descriptor limits. */
2152 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2153 rl.rlim_cur = 1024;
2154 rl.rlim_max = 1024;
2155 }
2156
2157 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002158 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2159 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002160 } else {
2161 rl.rlim_cur = rl.rlim_max;
2162 }
2163
2164 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002165 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2166 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002167
2168 /* Update the soft limit. */
2169 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2170
nethercotef6a1d502004-08-09 12:21:57 +00002171 if (vgexecfd != -1)
2172 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002173 if (VG_(clexecfd) != -1)
2174 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2175}
2176
nethercote71980f02004-01-24 18:18:54 +00002177/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002178/*=== Initialise program data/text, etc. ===*/
2179/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002180
sewardjb5f6f512005-03-10 23:59:00 +00002181static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2182 UInt dev, UInt ino, ULong foffset,
2183 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002184{
nethercote71980f02004-01-24 18:18:54 +00002185 /* Only record valgrind mappings for now, without loading any
2186 symbols. This is so we know where the free space is before we
2187 start allocating more memory (note: heap is OK, it's just mmap
2188 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002189 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2190 if (0)
2191 VG_(printf)("init1: %p-%p prot %s\n",
2192 start, start+size, VG_(prot_str)(prot));
2193 VG_(map_file_segment)(start, size, prot,
2194 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2195 dev, ino, foffset, filename);
2196 /* update VG_(valgrind_last) if it looks wrong */
2197 if (start+size > VG_(valgrind_last))
2198 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002199 }
sewardjde4a1d02002-03-22 01:27:54 +00002200}
2201
nethercote71980f02004-01-24 18:18:54 +00002202// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002203Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002204
sewardjb5f6f512005-03-10 23:59:00 +00002205/*
2206 This second pass adds in client mappings, and loads symbol tables
2207 for all interesting mappings. The trouble is that things can
2208 change as we go, because we're calling the Tool to track memory as
2209 we find it.
2210
2211 So for Valgrind mappings, we don't replace any mappings which
2212 aren't still identical (which will include the .so mappings, so we
2213 will load their symtabs)>
2214 */
2215static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2216 UInt dev, UInt ino, ULong foffset,
2217 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002218{
nethercote71980f02004-01-24 18:18:54 +00002219 UInt flags;
2220 Bool is_stack_segment;
2221 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002222
nethercote71980f02004-01-24 18:18:54 +00002223 is_stack_segment
2224 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002225
sewardjb5f6f512005-03-10 23:59:00 +00002226 if (0)
2227 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2228 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002229
nethercote71980f02004-01-24 18:18:54 +00002230 if (is_stack_segment)
2231 flags = SF_STACK | SF_GROWDOWN;
2232 else
2233 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002234
nethercote71980f02004-01-24 18:18:54 +00002235 if (filename != NULL)
2236 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002237
sewardjb5f6f512005-03-10 23:59:00 +00002238#if 0
2239 // This needs to be fixed properly. jrs 20050307
2240 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2241 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002242
sewardjb5f6f512005-03-10 23:59:00 +00002243 /* We have to be a bit careful about inserting new mappings into
2244 the Valgrind part of the address space. We're actively
2245 changing things as we parse these mappings, particularly in
2246 shadow memory, and so we don't want to overwrite those
2247 changes. Therefore, we only insert/update a mapping if it is
2248 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002249
sewardjb5f6f512005-03-10 23:59:00 +00002250 NOTE: we're only talking about the Segment list mapping
2251 metadata; this doesn't actually mmap anything more. */
2252 if (filename || (s && s->addr == start && s->len == size)) {
2253 flags |= SF_VALGRIND;
2254 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2255 } else {
2256 /* assert range is already mapped */
2257 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2258 }
2259 } else
2260#endif
2261 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2262
2263 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2264 VG_TRACK( new_mem_startup, start, size,
2265 !!(prot & VKI_PROT_READ),
2266 !!(prot & VKI_PROT_WRITE),
2267 !!(prot & VKI_PROT_EXEC));
2268 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002269
nethercote71980f02004-01-24 18:18:54 +00002270 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002271 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002272 vg_assert(0 != r_esp);
2273 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002274 if (0) {
2275 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002276 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002277 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2278 r_esp, start+size);
2279 }
nethercote71980f02004-01-24 18:18:54 +00002280 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002281 // what's this for?
2282 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002283 }
sewardjde4a1d02002-03-22 01:27:54 +00002284}
2285
2286
nethercote71980f02004-01-24 18:18:54 +00002287/*====================================================================*/
2288/*=== Sanity check machinery (permanently engaged) ===*/
2289/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002290
2291/* A fast sanity check -- suitable for calling circa once per
2292 millisecond. */
2293
nethercote885dd912004-08-03 23:14:00 +00002294void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002295{
sewardjb5f6f512005-03-10 23:59:00 +00002296 ThreadId tid;
2297
njn37cea302002-09-30 11:24:00 +00002298 VGP_PUSHCC(VgpCoreCheapSanity);
2299
nethercote27fec902004-06-16 21:26:32 +00002300 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002301
2302 /* --- First do all the tests that we can do quickly. ---*/
2303
nethercote297effd2004-08-02 15:07:57 +00002304 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002305
njn25e49d8e72002-09-23 09:36:25 +00002306 /* Check stuff pertaining to the memory check system. */
2307
2308 /* Check that nobody has spuriously claimed that the first or
2309 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002310 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002311 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002312 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002313 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002314 }
njn25e49d8e72002-09-23 09:36:25 +00002315
2316 /* --- Now some more expensive checks. ---*/
2317
2318 /* Once every 25 times, check some more expensive stuff. */
2319 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002320 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002321 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002322
njn37cea302002-09-30 11:24:00 +00002323 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002324 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002325
2326# if 0
2327 { void zzzmemscan(void); zzzmemscan(); }
2328# endif
2329
nethercote297effd2004-08-02 15:07:57 +00002330 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002331 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002332
2333 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002334 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002335 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002336 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002337 }
sewardjb5f6f512005-03-10 23:59:00 +00002338
2339 /* Check that Segments and /proc/self/maps match up */
2340 //vg_assert(VG_(sanity_check_memory)());
2341
2342 /* Look for stack overruns. Visit all threads. */
2343 for(tid = 1; tid < VG_N_THREADS; tid++) {
2344 Int remains;
2345
2346 if (VG_(threads)[tid].status == VgTs_Empty ||
2347 VG_(threads)[tid].status == VgTs_Zombie)
2348 continue;
2349
2350 remains = VGA_(stack_unused)(tid);
2351 if (remains < VKI_PAGE_SIZE)
2352 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2353 tid, remains);
2354 }
2355
njn25e49d8e72002-09-23 09:36:25 +00002356 /*
nethercote297effd2004-08-02 15:07:57 +00002357 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002358 */
njn37cea302002-09-30 11:24:00 +00002359 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002360 }
2361
nethercote27fec902004-06-16 21:26:32 +00002362 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002363 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002364 /* Check sanity of the low-level memory manager. Note that bugs
2365 in the client's code can cause this to fail, so we don't do
2366 this check unless specially asked for. And because it's
2367 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002368 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002369 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002370 }
njn37cea302002-09-30 11:24:00 +00002371 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002372}
nethercote71980f02004-01-24 18:18:54 +00002373
2374
2375/*====================================================================*/
2376/*=== main() ===*/
2377/*====================================================================*/
2378
nethercotec314eba2004-07-15 12:59:41 +00002379/*
2380 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002381 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002382 loads the client executable (and the dynamic linker, if necessary)
2383 into the client part, and calls into Valgrind proper.
2384
2385 The code is careful not to allow spurious mappings to appear in the
2386 wrong parts of the address space. In particular, to make sure
2387 dlopen puts things in the right place, it will pad out the forbidden
2388 chunks of address space so that dlopen is forced to put things where
2389 we want them.
2390
2391 The memory map it creates is:
2392
2393 CLIENT_BASE +-------------------------+
2394 | client address space |
2395 : :
2396 : :
2397 | client stack |
2398 client_end +-------------------------+
2399 | redzone |
2400 shadow_base +-------------------------+
2401 | |
nethercote996901a2004-08-03 13:29:09 +00002402 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002403 | (may be 0 sized) |
2404 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002405 valgrind_base +-------------------------+
2406 | kickstart executable |
2407 | valgrind heap vvvvvvvvv| (barely used)
2408 - -
2409 | valgrind .so files |
2410 | and mappings |
2411 - -
2412 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002413 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002414 : kernel :
2415
2416 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2417 VG_(mmap)(), we need to build the segment skip-list, so we know where
2418 we can put things. However, building that structure requires
2419 allocating memory. So we need to a bootstrapping process. It's done
2420 by making VG_(arena_malloc)() have a special static superblock that's
2421 used for the first 1MB's worth of allocations. This is enough to
2422 build the segment skip-list.
2423*/
2424
nethercote31779c72004-07-30 21:50:15 +00002425static int prmap(char *start, char *end, const char *perm, off_t off,
2426 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002427 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2428 start, end, perm, maj, min, ino);
2429 return True;
2430}
2431
sewardjb5f6f512005-03-10 23:59:00 +00002432int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002433{
2434 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002435 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002436 const char *exec = NULL;
2437 char *preload; /* tool-specific LD_PRELOAD .so */
2438 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002439 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002440 struct exeinfo info;
2441 ToolInfo *toolinfo = NULL;
2442 void *tool_dlhandle;
2443 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002444 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002445 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002446 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002447 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002448
2449 //============================================================
2450 // Nb: startup is complex. Prerequisites are shown at every step.
2451 //
2452 // *** Be very careful when messing with the order ***
2453 //============================================================
2454
nethercotef4928da2004-06-15 10:54:40 +00002455 //============================================================
2456 // Command line argument handling order:
2457 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002458 // (including the tool-specific usage)
2459 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002460 // * Then, if client is missing, abort with error msg
2461 // * Then, if any cmdline args are bad, abort with error msg
2462 //============================================================
2463
fitzhardingeb50068f2004-02-24 23:42:55 +00002464 // Get the current process datasize rlimit, and set it to zero.
2465 // This prevents any internal uses of brk() from having any effect.
2466 // We remember the old value so we can restore it on exec, so that
2467 // child processes will have a reasonable brk value.
2468 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2469 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2470 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002471
2472 // Get the current process stack rlimit.
2473 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2474
nethercote71980f02004-01-24 18:18:54 +00002475 //--------------------------------------------------------------
2476 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002477 // p: none
nethercote71980f02004-01-24 18:18:54 +00002478 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002479 {
2480 void* init_sp = argv - 1;
2481 padfile = scan_auxv(init_sp);
2482 }
nethercote71980f02004-01-24 18:18:54 +00002483 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002484 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002485 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002486 }
2487
2488 //--------------------------------------------------------------
2489 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002490 // p: none
nethercote71980f02004-01-24 18:18:54 +00002491 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002492 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002493 if (cp != NULL)
2494 VG_(libdir) = cp;
2495 }
2496
2497 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002498 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2499 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002500 // p: none
nethercote71980f02004-01-24 18:18:54 +00002501 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002502 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002503 pre_process_cmd_line_options(&need_help, &tool, &exec);
2504
2505 //==============================================================
2506 // Nb: once a tool is specified, the tool.so must be loaded even if
2507 // they specified --help or didn't specify a client program.
2508 //==============================================================
2509
2510 //--------------------------------------------------------------
2511 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002512 // p: set-libdir [for VG_(libdir)]
2513 // p: pre_process_cmd_line_options() [for 'tool']
2514 //--------------------------------------------------------------
2515 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2516
2517 //==============================================================
2518 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002519 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002520 //==============================================================
2521
2522 //--------------------------------------------------------------
2523 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002524 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002525 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002526 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002527
2528 //--------------------------------------------------------------
2529 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002530 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2531 // p: layout_remaining_space [so there's space]
2532 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002533 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002534
2535 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002536 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002537 // p: layout_remaining_space() [everything must be mapped in before now]
2538 // p: load_client() [ditto]
2539 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002540 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2541 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002542
2543 //--------------------------------------------------------------
2544 // Set up client's environment
2545 // p: set-libdir [for VG_(libdir)]
2546 // p: load_tool() [for 'preload']
2547 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002548 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002549
2550 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002551 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002552 // p: load_client() [for 'info']
2553 // p: fix_environment() [for 'env']
2554 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002555 {
2556 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002557
nethercote4ad74312004-10-26 09:59:49 +00002558 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2559 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002560 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002561 }
nethercote71980f02004-01-24 18:18:54 +00002562
2563 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002564 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002565 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002566 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002567
2568 //==============================================================
2569 // Finished setting up operating environment. Now initialise
2570 // Valgrind. (This is where the old VG_(main)() started.)
2571 //==============================================================
2572
2573 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002574 // setup file descriptors
2575 // p: n/a
2576 //--------------------------------------------------------------
2577 setup_file_descriptors();
2578
2579 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002580 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002581 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002582 //--------------------------------------------------------------
2583 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2584
2585 //==============================================================
2586 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2587 //==============================================================
2588
2589 //--------------------------------------------------------------
2590 // Init tool: pre_clo_init, process cmd line, post_clo_init
2591 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2592 // p: load_tool() [for 'tool']
2593 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2594 // p: parse_procselfmaps [so VG segments are setup so tool can
2595 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002596 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002597 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002598 VG_(tool_init_dlsym)(tool_dlhandle);
2599 VG_(sanity_check_needs)();
2600
nethercotef4928da2004-06-15 10:54:40 +00002601 // If --tool and --help/--help-debug was given, now give the core+tool
2602 // help message
nethercotef4928da2004-06-15 10:54:40 +00002603 if (need_help) {
2604 usage(/*--help-debug?*/2 == need_help);
2605 }
nethercotec314eba2004-07-15 12:59:41 +00002606 process_cmd_line_options(client_auxv, tool);
2607
njn26f02512004-11-22 18:33:15 +00002608 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002609
2610 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002611 // Determine CPU architecture and subarchitecture
2612 // p: none
2613 //--------------------------------------------------------------
2614 { Bool ok = VGA_(getArchAndSubArch)(
2615 & VG_(vex_arch), & VG_(vex_subarch) );
2616 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002617 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002618 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002619 VG_(printf)(" Supported CPUs are:\n");
2620 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2621 "AMD Athlon or above)\n");
2622 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002623 VG_(exit)(1);
2624 }
2625 if (VG_(clo_verbosity) > 2) {
2626 VG_(message)(Vg_DebugMsg,
2627 "Host CPU: arch = %s, subarch = %s",
2628 LibVEX_ppVexArch( VG_(vex_arch) ),
2629 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2630 }
2631 }
2632
2633 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002634 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002635 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002636 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002637 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002638 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002639 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002640 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002641 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002642
sewardja4da2f32005-03-02 14:06:08 +00002643#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002644 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002645 // Protect client trampoline page (which is also sysinfo stuff)
2646 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002647 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002648 {
2649 Segment *seg;
2650 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2651 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002652#endif
sewardjb5f6f512005-03-10 23:59:00 +00002653 /* Make sure this segment isn't treated as stack */
2654 seg = VG_(find_segment)(VG_(client_trampoline_code));
2655 if (seg)
2656 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2657 }
2658
nethercotec314eba2004-07-15 12:59:41 +00002659 //==============================================================
2660 // Can use VG_(map)() after segments set up
2661 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002662
2663 //--------------------------------------------------------------
2664 // Allow GDB attach
2665 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2666 //--------------------------------------------------------------
2667 /* Hook to delay things long enough so we can get the pid and
2668 attach GDB in another shell. */
2669 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002670 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2671 /* jrs 20050206: I don't understand why this works on x86. On
2672 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2673 work. */
2674 /* do "jump *$eip" to skip this in gdb (x86) */
2675 //VG_(do_syscall0)(__NR_pause);
2676 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002677 }
2678
sewardjb5d320c2005-03-13 18:57:15 +00002679 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002680 // Search for file descriptors that are inherited from our parent
2681 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2682 //--------------------------------------------------------------
2683 if (VG_(clo_track_fds))
2684 VG_(init_preopened_fds)();
2685
2686 //--------------------------------------------------------------
2687 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002688 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2689 //--------------------------------------------------------------
2690 VG_(scheduler_init)();
2691
2692 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002693 // Initialise the pthread model
2694 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002695 // load_client() [for 'client_eip']
2696 // setup_client_stack() [for 'sp_at_startup']
2697 // setup_scheduler() [for the rest of state 1 stuff]
2698 //--------------------------------------------------------------
2699 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002700
2701 // Tell the tool that we just wrote to the registers.
2702 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2703 sizeof(VexGuestArchState));
2704
2705 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002706 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002707
2708 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002709 // Initialise the pthread model
2710 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002711 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002712 //if (VG_(clo_model_pthreads))
2713 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002714
2715 //--------------------------------------------------------------
2716 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002717 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002718 //--------------------------------------------------------------
2719 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2720 VG_(sigstartup_actions)();
2721
2722 //--------------------------------------------------------------
2723 // Perhaps we're profiling Valgrind?
2724 // p: process_cmd_line_options() [for VG_(clo_profile)]
2725 // p: others?
2726 //
2727 // XXX: this seems to be broken? It always says the tool wasn't built
2728 // for profiling; vg_profile.c's functions don't seem to be overriding
2729 // vg_dummy_profile.c's?
2730 //
2731 // XXX: want this as early as possible. Looking for --profile
2732 // in pre_process_cmd_line_options() could get it earlier.
2733 //--------------------------------------------------------------
2734 if (VG_(clo_profile))
2735 VGP_(init_profiling)();
2736
2737 VGP_PUSHCC(VgpStartup);
2738
2739 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002740 // Read suppression file
2741 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2742 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002743 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002744 VG_(load_suppressions)();
2745
2746 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002747 // Initialise translation table and translation cache
2748 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2749 // aren't identified as part of the client, which would waste
2750 // > 20M of virtual address space.]
2751 //--------------------------------------------------------------
2752 VG_(init_tt_tc)();
2753
2754 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002755 // Read debug info to find glibc entry points to intercept
2756 // p: parse_procselfmaps? [XXX for debug info?]
2757 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2758 //--------------------------------------------------------------
2759 VG_(setup_code_redirect_table)();
2760
2761 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002762 // Verbosity message
2763 // p: end_rdtsc_calibration [so startup message is printed first]
2764 //--------------------------------------------------------------
2765 if (VG_(clo_verbosity) == 1)
2766 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2767 if (VG_(clo_verbosity) > 0)
2768 VG_(message)(Vg_UserMsg, "");
2769
2770 //--------------------------------------------------------------
2771 // Setup pointercheck
2772 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2773 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002774 if (VG_(clo_pointercheck))
2775 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002776
nethercote71980f02004-01-24 18:18:54 +00002777 //--------------------------------------------------------------
2778 // Run!
2779 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002780 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002781
sewardjb5f6f512005-03-10 23:59:00 +00002782 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002783
sewardjb5f6f512005-03-10 23:59:00 +00002784 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002785
sewardjb5f6f512005-03-10 23:59:00 +00002786 abort();
2787}
2788
2789
2790/* Do everything which needs doing when the last thread exits */
2791void VG_(shutdown_actions)(ThreadId tid)
2792{
2793 vg_assert(tid == VG_(master_tid));
2794 vg_assert(VG_(is_running_thread)(tid));
2795
2796 // Wait for all other threads to exit.
2797 VGA_(reap_threads)(tid);
2798
2799 VG_(clo_model_pthreads) = False;
2800
2801 // Clean the client up before the final report
2802 VGA_(final_tidyup)(tid);
2803
2804 // OK, done
2805 VG_(exit_thread)(tid);
2806
2807 /* should be no threads left */
2808 vg_assert(VG_(count_living_threads)() == 0);
2809
2810 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002811 //--------------------------------------------------------------
2812 // Finalisation: cleanup, messages, etc. Order no so important, only
2813 // affects what order the messages come.
2814 //--------------------------------------------------------------
2815 if (VG_(clo_verbosity) > 0)
2816 VG_(message)(Vg_UserMsg, "");
2817
nethercote71980f02004-01-24 18:18:54 +00002818 /* Print out file descriptor summary and stats. */
2819 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002820 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002821
njn95ec8702004-11-22 16:46:13 +00002822 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002823 VG_(show_all_errors)();
2824
sewardjb5f6f512005-03-10 23:59:00 +00002825 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002826
nethercote885dd912004-08-03 23:14:00 +00002827 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002828
2829 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002830 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002831
nethercote71980f02004-01-24 18:18:54 +00002832 if (VG_(clo_profile))
2833 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002834 if (VG_(clo_profile_flags) > 0)
2835 VG_(show_BB_profile)();
2836
sewardj8b635a42004-11-22 19:01:47 +00002837 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002838 if (0)
2839 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002840
nethercote71980f02004-01-24 18:18:54 +00002841}
2842
sewardjde4a1d02002-03-22 01:27:54 +00002843/*--------------------------------------------------------------------*/
2844/*--- end vg_main.c ---*/
2845/*--------------------------------------------------------------------*/