blob: b81ba751027af4b7e62e62602a109ac4ae2c37d8 [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;
sewardj2370f3b2002-11-30 15:01:01 +00001457
jsgf855d93d2003-10-13 22:26:55 +00001458static Bool VG_(clo_wait_for_gdb) = False;
1459
sewardjde4a1d02002-03-22 01:27:54 +00001460
sewardj2c5ffbe2005-03-12 13:32:06 +00001461static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001462{
njn25e49d8e72002-09-23 09:36:25 +00001463 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001464"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001465"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001466" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001467" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001468" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001469" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001470" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001471" -q --quiet run silently; only print error msgs\n"
1472" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001473" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001474" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001475" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001476"\n"
1477" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001478" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001479" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001480" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001481" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001482"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001484" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1485" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001486" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001487" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001488" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001489" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001490" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1491" --show-below-main=no|yes continue stack traces below main() [no]\n"
1492" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001493" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001494" --db-attach=no|yes start debugger when errors detected? [no]\n"
1495" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1496" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001497"\n";
njn7cf0bd32002-06-08 13:36:03 +00001498
njn25e49d8e72002-09-23 09:36:25 +00001499 Char* usage2 =
1500"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001501" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001502" --sanity-level=<number> level of sanity checking to do [1]\n"
1503" --single-step=no|yes translate each instr separately? [no]\n"
1504" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001505" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001506" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001507" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1508" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001509" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001510" --trace-syscalls=no|yes show all system calls? [no]\n"
1511" --trace-signals=no|yes show signal handling details? [no]\n"
1512" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001513" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001514" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001515#if 0
1516" --model-pthreads=yes|no model the pthreads library [no]\n"
1517#endif
1518" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001519"\n"
1520" --vex-iropt-verbosity 0 .. 9 [0]\n"
1521" --vex-iropt-level 0 .. 2 [2]\n"
1522" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001523" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1524" --vex-guest-max-insns 1 .. 100 [50]\n"
1525" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1526"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001527" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001528" 1000 0000 show conversion into IR\n"
1529" 0100 0000 show after initial opt\n"
1530" 0010 0000 show after instrumentation\n"
1531" 0001 0000 show after second opt\n"
1532" 0000 1000 show after tree building\n"
1533" 0000 0100 show selecting insns\n"
1534" 0000 0010 show after reg-alloc\n"
1535" 0000 0001 show final assembly\n"
1536"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001537" debugging options for Valgrind tools that report errors\n"
1538" --dump-error=<number> show translation for basic block associated\n"
1539" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001540"\n";
njn3e884182003-04-15 13:03:23 +00001541
1542 Char* usage3 =
1543"\n"
nethercote71980f02004-01-24 18:18:54 +00001544" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001545"\n"
njn53612422005-03-12 16:22:54 +00001546" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001547" and licensed under the GNU General Public License, version 2.\n"
1548" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001549"\n"
nethercote137bc552003-11-14 17:47:54 +00001550" Tools are copyright and licensed by their authors. See each\n"
1551" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001552"\n";
njn7cf0bd32002-06-08 13:36:03 +00001553
fitzhardinge98abfc72003-12-16 02:05:15 +00001554 VG_(printf)(usage1);
1555 if (VG_(details).name) {
1556 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001557 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001558 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001559 else
1560 VG_(printf)(" (none)\n");
1561 }
nethercote6c999f22004-01-31 22:55:15 +00001562 if (debug_help) {
1563 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001564
nethercote6c999f22004-01-31 22:55:15 +00001565 if (VG_(details).name) {
1566 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1567
1568 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001569 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001570 else
1571 VG_(printf)(" (none)\n");
1572 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001573 }
nethercote421281e2003-11-20 16:20:55 +00001574 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001575 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001576}
sewardjde4a1d02002-03-22 01:27:54 +00001577
nethercote71980f02004-01-24 18:18:54 +00001578static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001579 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001580{
nethercote71980f02004-01-24 18:18:54 +00001581 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001582
sewardj8b635a42004-11-22 19:01:47 +00001583 LibVEX_default_VexControl(& VG_(clo_vex_control));
1584
nethercote71980f02004-01-24 18:18:54 +00001585 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001586 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001587
nethercotef6a1d502004-08-09 12:21:57 +00001588 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001589 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001590 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001591
nethercotef6a1d502004-08-09 12:21:57 +00001592 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1593 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001594 *need_help = 1;
1595
nethercotef6a1d502004-08-09 12:21:57 +00001596 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001597 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001598
nethercotef6c99d72004-11-09 14:35:43 +00001599 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001600 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001601
nethercotef6a1d502004-08-09 12:21:57 +00001602 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1603 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001604 }
1605 }
nethercote71980f02004-01-24 18:18:54 +00001606}
1607
nethercote5ee67ca2004-06-22 14:00:09 +00001608static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001609{
nethercotef8548672004-06-21 12:42:35 +00001610 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001611 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001612
nethercotee1730692003-11-20 10:38:07 +00001613 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001614 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001615
sewardj19d81412002-06-03 01:10:40 +00001616 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001618 config_error("Please use absolute paths in "
1619 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001620
njnc6168192004-11-29 13:54:10 +00001621// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001622#ifdef __x86__
1623 {
sewardjb5f6f512005-03-10 23:59:00 +00001624 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001625 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1626 switch(auxp[0]) {
1627 case AT_SYSINFO:
1628 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1629 break;
1630 }
1631 }
1632 }
1633#endif
sewardjde4a1d02002-03-22 01:27:54 +00001634
nethercotef6a1d502004-08-09 12:21:57 +00001635 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001636
nethercotef6a1d502004-08-09 12:21:57 +00001637 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001638 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001639
thughes3bfd5a02004-07-18 08:05:44 +00001640 /* Look for a colon in the switch name */
1641 while (*colon && *colon != ':' && *colon != '=')
1642 colon++;
nethercote71980f02004-01-24 18:18:54 +00001643
1644 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001645 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001646 if (VG_CLO_STREQN(2, arg, "--") &&
1647 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1648 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1649 {
1650 // prefix matches, convert "--toolname:foo" to "--foo"
1651 if (0)
1652 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001653 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001654 arg[0] = '-';
1655 arg[1] = '-';
1656
1657 } else {
1658 // prefix doesn't match, skip to next arg
1659 continue;
1660 }
1661 }
1662
fitzhardinge98abfc72003-12-16 02:05:15 +00001663 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001664 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001665 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001666 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001667 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001668 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001669 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001670
nethercote71980f02004-01-24 18:18:54 +00001671 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001672 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001673
nethercote71980f02004-01-24 18:18:54 +00001674 else if (VG_CLO_STREQ(arg, "-v") ||
1675 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001676 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 else if (VG_CLO_STREQ(arg, "-q") ||
1679 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001680 VG_(clo_verbosity)--;
1681
nethercote27fec902004-06-16 21:26:32 +00001682 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001683 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1684 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1685 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001686 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001687 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
nethercote27fec902004-06-16 21:26:32 +00001688 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1689 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1690 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001691 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001692 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1693 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1694 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1695 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1696 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001697 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001698 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001699 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001700 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001701 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001702
nethercote27fec902004-06-16 21:26:32 +00001703 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1704 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001705
nethercote27fec902004-06-16 21:26:32 +00001706 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1707 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1708 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001709 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1710 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001711
sewardj8b635a42004-11-22 19:01:47 +00001712 else VG_BNUM_CLO("--vex-iropt-verbosity",
1713 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1714 else VG_BNUM_CLO("--vex-iropt-level",
1715 VG_(clo_vex_control).iropt_level, 0, 2)
1716 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1717 VG_(clo_vex_control).iropt_precise_memory_exns)
1718 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1719 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1720 else VG_BNUM_CLO("--vex-guest-max-insns",
1721 VG_(clo_vex_control).guest_max_insns, 1, 100)
1722 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1723 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1724
nethercotef8548672004-06-21 12:42:35 +00001725 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001726 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001727 VG_(clo_log_to) = VgLogTo_Fd;
1728 VG_(clo_log_name) = NULL;
1729 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1730 }
1731 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1732 VG_(clo_log_to) = VgLogTo_Fd;
1733 VG_(clo_log_name) = NULL;
1734 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001735 }
1736
nethercotef8548672004-06-21 12:42:35 +00001737 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001738 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001739 VG_(clo_log_to) = VgLogTo_File;
1740 VG_(clo_log_name) = &arg[10];
1741 }
1742 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1743 VG_(clo_log_to) = VgLogTo_File;
1744 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001745 }
sewardj603d4102005-01-11 14:01:02 +00001746 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1747 VG_(clo_log_to) = VgLogTo_FileExactly;
1748 VG_(clo_log_name) = &arg[19];
1749 }
sewardjde4a1d02002-03-22 01:27:54 +00001750
nethercotef8548672004-06-21 12:42:35 +00001751 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001752 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001753 VG_(clo_log_to) = VgLogTo_Socket;
1754 VG_(clo_log_name) = &arg[12];
1755 }
1756 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1757 VG_(clo_log_to) = VgLogTo_Socket;
1758 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001759 }
1760
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001762 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001763 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001764 VG_(message)(Vg_UserMsg,
1765 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001766 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001767 }
nethercote71980f02004-01-24 18:18:54 +00001768 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001769 VG_(clo_n_suppressions)++;
1770 }
sewardjde4a1d02002-03-22 01:27:54 +00001771
sewardjfa8ec112005-01-19 11:55:34 +00001772 /* "stuvwxyz" --> stuvwxyz (binary) */
1773 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1774 Int j;
1775 char* opt = & arg[14];
1776
1777 if (8 != VG_(strlen)(opt)) {
1778 VG_(message)(Vg_UserMsg,
1779 "--trace-flags argument must have 8 digits");
1780 VG_(bad_option)(arg);
1781 }
1782 for (j = 0; j < 8; j++) {
1783 if ('0' == opt[j]) { /* do nothing */ }
1784 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1785 else {
1786 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1787 "contain 0s and 1s");
1788 VG_(bad_option)(arg);
1789 }
1790 }
1791 }
1792
1793 /* "stuvwxyz" --> stuvwxyz (binary) */
1794 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001795 Int j;
nethercote71980f02004-01-24 18:18:54 +00001796 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001797
sewardj2a99cf62004-11-24 10:44:19 +00001798 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001799 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001800 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001801 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001802 }
sewardj8b635a42004-11-22 19:01:47 +00001803 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001804 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001805 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001806 else {
sewardjfa8ec112005-01-19 11:55:34 +00001807 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001808 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
1811 }
1812 }
sewardjde4a1d02002-03-22 01:27:54 +00001813
sewardjc771b292004-11-30 18:55:21 +00001814 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1815
sewardjd153fae2005-01-10 17:24:47 +00001816 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1817 VG_(clo_gen_suppressions) = 0;
1818 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1819 VG_(clo_gen_suppressions) = 1;
1820 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1821 VG_(clo_gen_suppressions) = 2;
1822
nethercote71980f02004-01-24 18:18:54 +00001823 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001824 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001825 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001826 }
njn8c0b3bb2005-03-12 21:20:39 +00001827 skip_arg:
1828 if (arg != vg_argv[i])
1829 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001830 }
1831
sewardj998d40d2004-12-06 14:24:52 +00001832 /* Make VEX control parameters sane */
1833
1834 if (VG_(clo_vex_control).guest_chase_thresh
1835 >= VG_(clo_vex_control).guest_max_insns)
1836 VG_(clo_vex_control).guest_chase_thresh
1837 = VG_(clo_vex_control).guest_max_insns - 1;
1838
1839 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1840 VG_(clo_vex_control).guest_chase_thresh = 0;
1841
1842 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001843
njnf9ebf672003-05-12 21:41:30 +00001844 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001845 VG_(clo_verbosity) = 0;
1846
nethercote04d0fbc2004-01-26 16:48:06 +00001847 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001848 VG_(message)(Vg_UserMsg, "");
1849 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001850 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001851 VG_(message)(Vg_UserMsg,
1852 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001853 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001854 }
1855
nethercotef8548672004-06-21 12:42:35 +00001856 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001857 should be connected to whatever sink has been selected, and we
1858 indiscriminately chuck stuff into it without worrying what the
1859 nature of it is. Oh the wonder of Unix streams. */
1860
nethercotee1730692003-11-20 10:38:07 +00001861 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001862 the terminal any problems to do with processing command line
1863 opts. */
nethercotef8548672004-06-21 12:42:35 +00001864 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001865 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001866
1867 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001868
sewardj4cf05692002-10-27 20:28:29 +00001869 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001870 vg_assert(VG_(clo_log_name) == NULL);
1871 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001872 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001873
sewardj4cf05692002-10-27 20:28:29 +00001874 case VgLogTo_File: {
1875 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001876 Int seq = 0;
1877 Int pid = VG_(getpid)();
1878
nethercotef8548672004-06-21 12:42:35 +00001879 vg_assert(VG_(clo_log_name) != NULL);
1880 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001881
nethercote71980f02004-01-24 18:18:54 +00001882 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001883 if (seq == 0)
1884 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001885 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001886 else
1887 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001888 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001889 seq++;
1890
nethercotef8548672004-06-21 12:42:35 +00001891 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001892 = VG_(open)(logfilename,
1893 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1894 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001895 if (eventually_log_fd >= 0) {
1896 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001897 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001898 } else {
nethercotef8548672004-06-21 12:42:35 +00001899 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001900 VG_(message)(Vg_UserMsg,
1901 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001902 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001903 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001904 "--log-file=<file> (didn't work out for some reason.)");
1905 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001906 }
1907 }
1908 }
sewardj603d4102005-01-11 14:01:02 +00001909 break; /* switch (VG_(clo_log_to)) */
1910 }
1911
1912 case VgLogTo_FileExactly: {
1913 Char logfilename[1000];
1914
1915 vg_assert(VG_(clo_log_name) != NULL);
1916 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1917 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1918
1919 eventually_log_fd
1920 = VG_(open)(logfilename,
1921 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1922 VKI_S_IRUSR|VKI_S_IWUSR);
1923 if (eventually_log_fd >= 0) {
1924 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1925 }
1926 else if (eventually_log_fd != -VKI_EEXIST) {
1927 VG_(message)(Vg_UserMsg,
1928 "Can't create/open log file `%s'; giving up!",
1929 VG_(clo_log_name));
1930 VG_(bad_option)(
1931 "--log-file-exactly=<file> (didn't work out for some reason.)");
1932 /*NOTREACHED*/
1933 }
1934 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001935 }
1936
1937 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001938 vg_assert(VG_(clo_log_name) != NULL);
1939 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1940 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1941 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001942 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001943 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001944 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001945 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001946 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001947 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001948 }
nethercotef8548672004-06-21 12:42:35 +00001949 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001950 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001951 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001952 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001953 VG_(message)(Vg_UserMsg,
1954 "Log messages will sent to stderr instead." );
1955 VG_(message)(Vg_UserMsg,
1956 "" );
1957 /* We don't change anything here. */
1958 } else {
nethercotef8548672004-06-21 12:42:35 +00001959 vg_assert(eventually_log_fd > 0);
1960 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001961 VG_(logging_to_filedes) = False;
1962 }
sewardj73cf3bc2002-11-03 03:20:15 +00001963 break;
1964 }
1965
sewardj4cf05692002-10-27 20:28:29 +00001966 }
1967
nethercotef8548672004-06-21 12:42:35 +00001968 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001969 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001970 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001971 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1972 else {
nethercotef8548672004-06-21 12:42:35 +00001973 VG_(clo_log_fd) = eventually_log_fd;
1974 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001975 }
1976
sewardj4cf05692002-10-27 20:28:29 +00001977 /* Ok, the logging sink is running now. Print a suitable preamble.
1978 If logging to file or a socket, write details of parent PID and
1979 command line args, to help people trying to interpret the
1980 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001981
sewardj83adf412002-05-01 01:25:45 +00001982 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001983 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001984 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001985 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001986 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001987 NULL == VG_(details).version
1988 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001989 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001990 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001991
njnd04b7c62002-10-03 14:05:52 +00001992 /* Core details */
1993 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00001994 "Using LibVEX rev %s, a library for dynamic binary translation.",
1995 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00001996 VG_(message)(Vg_UserMsg,
1997 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
1998 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00001999 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002000 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002001 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002002 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002003 }
2004
nethercotec1e395d2003-11-10 13:26:49 +00002005 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002006 VG_(message)(Vg_UserMsg, "");
2007 VG_(message)(Vg_UserMsg,
2008 "My PID = %d, parent PID = %d. Prog and args are:",
2009 VG_(getpid)(), VG_(getppid)() );
2010 for (i = 0; i < VG_(client_argc); i++)
2011 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2012 }
2013
sewardjde4a1d02002-03-22 01:27:54 +00002014 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002015 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002016 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002017 VG_(message)(Vg_DebugMsg, "");
2018 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2019 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002020 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002021 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002022
njn1fd5eb22005-03-13 05:43:23 +00002023 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002024 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002025 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002026 }
nethercotea70f7352004-04-18 12:08:46 +00002027
njn1fd5eb22005-03-13 05:43:23 +00002028 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002029 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2030 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002031 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002032 } else {
2033 #define BUF_LEN 256
2034 Char version_buf[BUF_LEN];
2035 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2036 vg_assert(n <= 256);
2037 if (n > 0) {
2038 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002039 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002040 } else {
njn1fd5eb22005-03-13 05:43:23 +00002041 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002042 }
2043 VG_(close)(fd);
2044 #undef BUF_LEN
2045 }
sewardjde4a1d02002-03-22 01:27:54 +00002046 }
2047
fitzhardinge98abfc72003-12-16 02:05:15 +00002048 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002049 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002050 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002051 needs one, load the default */
2052 static const Char default_supp[] = "default.supp";
2053 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2054 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2055 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2056 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2057 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002058 }
sewardj4cf05692002-10-27 20:28:29 +00002059
sewardjd153fae2005-01-10 17:24:47 +00002060 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002061 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002062 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002063 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002064 VG_(message)(Vg_UserMsg,
2065 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002066 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002067 }
sewardjde4a1d02002-03-22 01:27:54 +00002068}
2069
nethercotef6a1d502004-08-09 12:21:57 +00002070// Build the string for VALGRINDCLO.
2071Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2072{
2073 /* If we're tracing the children, then we need to start it
2074 with our starter+arguments, which are copied into VALGRINDCLO,
2075 except the --exec= option is changed if present.
2076 */
2077 Int i;
2078 Char *exec;
2079 Char *cp;
2080 Char *optvar;
2081 Int optlen, execlen;
2082
2083 // All these allocated blocks are not free - because we're either
2084 // going to exec, or panic when we fail.
2085
2086 // Create --exec= option: "--exec=<exename>"
2087 exec = VG_(arena_malloc)(VG_AR_CORE,
2088 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2089 vg_assert(NULL != exec);
2090 VG_(sprintf)(exec, "--exec=%s", exename);
2091
2092 // Allocate space for optvar (may overestimate by counting --exec twice,
2093 // no matter)
2094 optlen = 1;
2095 for (i = 0; i < vg_argc; i++)
2096 optlen += VG_(strlen)(vg_argv[i]) + 1;
2097 optlen += VG_(strlen)(exec)+1;
2098 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2099
2100 // Copy all valgrind args except the old --exec (if present)
2101 // VG_CLO_SEP is the separator.
2102 cp = optvar;
2103 for (i = 1; i < vg_argc; i++) {
2104 Char *arg = vg_argv[i];
2105
2106 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2107 // don't copy existing --exec= arg
2108 } else if (VG_(strcmp)(arg, "--") == 0) {
2109 // stop at "--"
2110 break;
2111 } else {
2112 // copy non "--exec" arg
2113 Int len = VG_(strlen)(arg);
2114 VG_(memcpy)(cp, arg, len);
2115 cp += len;
2116 *cp++ = VG_CLO_SEP;
2117 }
2118 }
2119 // Add the new --exec= option
2120 execlen = VG_(strlen)(exec);
2121 VG_(memcpy)(cp, exec, execlen);
2122 cp += execlen;
2123 *cp++ = VG_CLO_SEP;
2124
2125 *cp = '\0';
2126
2127 return optvar;
2128}
2129
2130// Build "/proc/self/fd/<execfd>".
2131Char* VG_(build_child_exename)( void )
2132{
2133 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2134 vg_assert(NULL != exename);
2135 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2136 return exename;
2137}
2138
sewardjde4a1d02002-03-22 01:27:54 +00002139
nethercote71980f02004-01-24 18:18:54 +00002140/*====================================================================*/
2141/*=== File descriptor setup ===*/
2142/*====================================================================*/
2143
2144static void setup_file_descriptors(void)
2145{
2146 struct vki_rlimit rl;
2147
2148 /* Get the current file descriptor limits. */
2149 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2150 rl.rlim_cur = 1024;
2151 rl.rlim_max = 1024;
2152 }
2153
2154 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002155 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2156 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002157 } else {
2158 rl.rlim_cur = rl.rlim_max;
2159 }
2160
2161 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002162 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2163 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002164
2165 /* Update the soft limit. */
2166 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2167
nethercotef6a1d502004-08-09 12:21:57 +00002168 if (vgexecfd != -1)
2169 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002170 if (VG_(clexecfd) != -1)
2171 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2172}
2173
nethercote71980f02004-01-24 18:18:54 +00002174/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002175/*=== Initialise program data/text, etc. ===*/
2176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002177
sewardjb5f6f512005-03-10 23:59:00 +00002178static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2179 UInt dev, UInt ino, ULong foffset,
2180 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002181{
nethercote71980f02004-01-24 18:18:54 +00002182 /* Only record valgrind mappings for now, without loading any
2183 symbols. This is so we know where the free space is before we
2184 start allocating more memory (note: heap is OK, it's just mmap
2185 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002186 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2187 if (0)
2188 VG_(printf)("init1: %p-%p prot %s\n",
2189 start, start+size, VG_(prot_str)(prot));
2190 VG_(map_file_segment)(start, size, prot,
2191 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2192 dev, ino, foffset, filename);
2193 /* update VG_(valgrind_last) if it looks wrong */
2194 if (start+size > VG_(valgrind_last))
2195 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002196 }
sewardjde4a1d02002-03-22 01:27:54 +00002197}
2198
nethercote71980f02004-01-24 18:18:54 +00002199// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002200Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002201
sewardjb5f6f512005-03-10 23:59:00 +00002202/*
2203 This second pass adds in client mappings, and loads symbol tables
2204 for all interesting mappings. The trouble is that things can
2205 change as we go, because we're calling the Tool to track memory as
2206 we find it.
2207
2208 So for Valgrind mappings, we don't replace any mappings which
2209 aren't still identical (which will include the .so mappings, so we
2210 will load their symtabs)>
2211 */
2212static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2213 UInt dev, UInt ino, ULong foffset,
2214 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002215{
nethercote71980f02004-01-24 18:18:54 +00002216 UInt flags;
2217 Bool is_stack_segment;
2218 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002219
nethercote71980f02004-01-24 18:18:54 +00002220 is_stack_segment
2221 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002222
sewardjb5f6f512005-03-10 23:59:00 +00002223 if (0)
2224 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2225 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002226
nethercote71980f02004-01-24 18:18:54 +00002227 if (is_stack_segment)
2228 flags = SF_STACK | SF_GROWDOWN;
2229 else
2230 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
nethercote71980f02004-01-24 18:18:54 +00002232 if (filename != NULL)
2233 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002234
sewardjb5f6f512005-03-10 23:59:00 +00002235#if 0
2236 // This needs to be fixed properly. jrs 20050307
2237 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2238 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002239
sewardjb5f6f512005-03-10 23:59:00 +00002240 /* We have to be a bit careful about inserting new mappings into
2241 the Valgrind part of the address space. We're actively
2242 changing things as we parse these mappings, particularly in
2243 shadow memory, and so we don't want to overwrite those
2244 changes. Therefore, we only insert/update a mapping if it is
2245 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002246
sewardjb5f6f512005-03-10 23:59:00 +00002247 NOTE: we're only talking about the Segment list mapping
2248 metadata; this doesn't actually mmap anything more. */
2249 if (filename || (s && s->addr == start && s->len == size)) {
2250 flags |= SF_VALGRIND;
2251 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2252 } else {
2253 /* assert range is already mapped */
2254 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2255 }
2256 } else
2257#endif
2258 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2259
2260 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2261 VG_TRACK( new_mem_startup, start, size,
2262 !!(prot & VKI_PROT_READ),
2263 !!(prot & VKI_PROT_WRITE),
2264 !!(prot & VKI_PROT_EXEC));
2265 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002266
nethercote71980f02004-01-24 18:18:54 +00002267 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002268 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002269 vg_assert(0 != r_esp);
2270 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002271 if (0) {
2272 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002273 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002274 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2275 r_esp, start+size);
2276 }
nethercote71980f02004-01-24 18:18:54 +00002277 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002278 // what's this for?
2279 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002280 }
sewardjde4a1d02002-03-22 01:27:54 +00002281}
2282
2283
nethercote71980f02004-01-24 18:18:54 +00002284/*====================================================================*/
2285/*=== Sanity check machinery (permanently engaged) ===*/
2286/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002287
2288/* A fast sanity check -- suitable for calling circa once per
2289 millisecond. */
2290
nethercote885dd912004-08-03 23:14:00 +00002291void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002292{
sewardjb5f6f512005-03-10 23:59:00 +00002293 ThreadId tid;
2294
njn37cea302002-09-30 11:24:00 +00002295 VGP_PUSHCC(VgpCoreCheapSanity);
2296
nethercote27fec902004-06-16 21:26:32 +00002297 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002298
2299 /* --- First do all the tests that we can do quickly. ---*/
2300
nethercote297effd2004-08-02 15:07:57 +00002301 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002302
njn25e49d8e72002-09-23 09:36:25 +00002303 /* Check stuff pertaining to the memory check system. */
2304
2305 /* Check that nobody has spuriously claimed that the first or
2306 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002307 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002308 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002309 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002310 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002311 }
njn25e49d8e72002-09-23 09:36:25 +00002312
2313 /* --- Now some more expensive checks. ---*/
2314
2315 /* Once every 25 times, check some more expensive stuff. */
2316 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002317 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002318 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002319
njn37cea302002-09-30 11:24:00 +00002320 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002321 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002322
2323# if 0
2324 { void zzzmemscan(void); zzzmemscan(); }
2325# endif
2326
nethercote297effd2004-08-02 15:07:57 +00002327 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002328 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002329
2330 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002331 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002332 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002333 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002334 }
sewardjb5f6f512005-03-10 23:59:00 +00002335
2336 /* Check that Segments and /proc/self/maps match up */
2337 //vg_assert(VG_(sanity_check_memory)());
2338
2339 /* Look for stack overruns. Visit all threads. */
2340 for(tid = 1; tid < VG_N_THREADS; tid++) {
2341 Int remains;
2342
2343 if (VG_(threads)[tid].status == VgTs_Empty ||
2344 VG_(threads)[tid].status == VgTs_Zombie)
2345 continue;
2346
2347 remains = VGA_(stack_unused)(tid);
2348 if (remains < VKI_PAGE_SIZE)
2349 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2350 tid, remains);
2351 }
2352
njn25e49d8e72002-09-23 09:36:25 +00002353 /*
nethercote297effd2004-08-02 15:07:57 +00002354 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002355 */
njn37cea302002-09-30 11:24:00 +00002356 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002357 }
2358
nethercote27fec902004-06-16 21:26:32 +00002359 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002360 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002361 /* Check sanity of the low-level memory manager. Note that bugs
2362 in the client's code can cause this to fail, so we don't do
2363 this check unless specially asked for. And because it's
2364 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002365 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002366 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002367 }
njn37cea302002-09-30 11:24:00 +00002368 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002369}
nethercote71980f02004-01-24 18:18:54 +00002370
2371
2372/*====================================================================*/
2373/*=== main() ===*/
2374/*====================================================================*/
2375
nethercotec314eba2004-07-15 12:59:41 +00002376/*
2377 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002378 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002379 loads the client executable (and the dynamic linker, if necessary)
2380 into the client part, and calls into Valgrind proper.
2381
2382 The code is careful not to allow spurious mappings to appear in the
2383 wrong parts of the address space. In particular, to make sure
2384 dlopen puts things in the right place, it will pad out the forbidden
2385 chunks of address space so that dlopen is forced to put things where
2386 we want them.
2387
2388 The memory map it creates is:
2389
2390 CLIENT_BASE +-------------------------+
2391 | client address space |
2392 : :
2393 : :
2394 | client stack |
2395 client_end +-------------------------+
2396 | redzone |
2397 shadow_base +-------------------------+
2398 | |
nethercote996901a2004-08-03 13:29:09 +00002399 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002400 | (may be 0 sized) |
2401 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002402 valgrind_base +-------------------------+
2403 | kickstart executable |
2404 | valgrind heap vvvvvvvvv| (barely used)
2405 - -
2406 | valgrind .so files |
2407 | and mappings |
2408 - -
2409 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002410 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002411 : kernel :
2412
2413 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2414 VG_(mmap)(), we need to build the segment skip-list, so we know where
2415 we can put things. However, building that structure requires
2416 allocating memory. So we need to a bootstrapping process. It's done
2417 by making VG_(arena_malloc)() have a special static superblock that's
2418 used for the first 1MB's worth of allocations. This is enough to
2419 build the segment skip-list.
2420*/
2421
nethercote31779c72004-07-30 21:50:15 +00002422static int prmap(char *start, char *end, const char *perm, off_t off,
2423 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002424 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2425 start, end, perm, maj, min, ino);
2426 return True;
2427}
2428
sewardjb5f6f512005-03-10 23:59:00 +00002429int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002430{
2431 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002432 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002433 const char *exec = NULL;
2434 char *preload; /* tool-specific LD_PRELOAD .so */
2435 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002436 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002437 struct exeinfo info;
2438 ToolInfo *toolinfo = NULL;
2439 void *tool_dlhandle;
2440 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002441 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002442 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002443 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002444 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002445
2446 //============================================================
2447 // Nb: startup is complex. Prerequisites are shown at every step.
2448 //
2449 // *** Be very careful when messing with the order ***
2450 //============================================================
2451
nethercotef4928da2004-06-15 10:54:40 +00002452 //============================================================
2453 // Command line argument handling order:
2454 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002455 // (including the tool-specific usage)
2456 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002457 // * Then, if client is missing, abort with error msg
2458 // * Then, if any cmdline args are bad, abort with error msg
2459 //============================================================
2460
fitzhardingeb50068f2004-02-24 23:42:55 +00002461 // Get the current process datasize rlimit, and set it to zero.
2462 // This prevents any internal uses of brk() from having any effect.
2463 // We remember the old value so we can restore it on exec, so that
2464 // child processes will have a reasonable brk value.
2465 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2466 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2467 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002468
2469 // Get the current process stack rlimit.
2470 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2471
nethercote71980f02004-01-24 18:18:54 +00002472 //--------------------------------------------------------------
2473 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002474 // p: none
nethercote71980f02004-01-24 18:18:54 +00002475 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002476 {
2477 void* init_sp = argv - 1;
2478 padfile = scan_auxv(init_sp);
2479 }
nethercote71980f02004-01-24 18:18:54 +00002480 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002481 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002482 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002483 }
2484
2485 //--------------------------------------------------------------
2486 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002487 // p: none
nethercote71980f02004-01-24 18:18:54 +00002488 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002489 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002490 if (cp != NULL)
2491 VG_(libdir) = cp;
2492 }
2493
2494 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002495 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2496 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002497 // p: none
nethercote71980f02004-01-24 18:18:54 +00002498 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002499 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002500 pre_process_cmd_line_options(&need_help, &tool, &exec);
2501
2502 //==============================================================
2503 // Nb: once a tool is specified, the tool.so must be loaded even if
2504 // they specified --help or didn't specify a client program.
2505 //==============================================================
2506
2507 //--------------------------------------------------------------
2508 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002509 // p: set-libdir [for VG_(libdir)]
2510 // p: pre_process_cmd_line_options() [for 'tool']
2511 //--------------------------------------------------------------
2512 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2513
2514 //==============================================================
2515 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002516 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002517 //==============================================================
2518
2519 //--------------------------------------------------------------
2520 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002521 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002522 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002523 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002524
2525 //--------------------------------------------------------------
2526 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002527 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2528 // p: layout_remaining_space [so there's space]
2529 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002530 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002531
2532 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002533 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002534 // p: layout_remaining_space() [everything must be mapped in before now]
2535 // p: load_client() [ditto]
2536 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002537 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2538 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002539
2540 //--------------------------------------------------------------
2541 // Set up client's environment
2542 // p: set-libdir [for VG_(libdir)]
2543 // p: load_tool() [for 'preload']
2544 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002545 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002546
2547 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002548 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002549 // p: load_client() [for 'info']
2550 // p: fix_environment() [for 'env']
2551 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002552 {
2553 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002554
nethercote4ad74312004-10-26 09:59:49 +00002555 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2556 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002557 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002558 }
nethercote71980f02004-01-24 18:18:54 +00002559
2560 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002561 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002562 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002563 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002564
2565 //==============================================================
2566 // Finished setting up operating environment. Now initialise
2567 // Valgrind. (This is where the old VG_(main)() started.)
2568 //==============================================================
2569
2570 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002571 // setup file descriptors
2572 // p: n/a
2573 //--------------------------------------------------------------
2574 setup_file_descriptors();
2575
2576 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002577 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002578 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002579 //--------------------------------------------------------------
2580 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2581
2582 //==============================================================
2583 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2584 //==============================================================
2585
2586 //--------------------------------------------------------------
2587 // Init tool: pre_clo_init, process cmd line, post_clo_init
2588 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2589 // p: load_tool() [for 'tool']
2590 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2591 // p: parse_procselfmaps [so VG segments are setup so tool can
2592 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002593 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002594 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002595 VG_(tool_init_dlsym)(tool_dlhandle);
2596 VG_(sanity_check_needs)();
2597
nethercotef4928da2004-06-15 10:54:40 +00002598 // If --tool and --help/--help-debug was given, now give the core+tool
2599 // help message
nethercotef4928da2004-06-15 10:54:40 +00002600 if (need_help) {
2601 usage(/*--help-debug?*/2 == need_help);
2602 }
nethercotec314eba2004-07-15 12:59:41 +00002603 process_cmd_line_options(client_auxv, tool);
2604
njn26f02512004-11-22 18:33:15 +00002605 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002606
2607 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002608 // Determine CPU architecture and subarchitecture
2609 // p: none
2610 //--------------------------------------------------------------
2611 { Bool ok = VGA_(getArchAndSubArch)(
2612 & VG_(vex_arch), & VG_(vex_subarch) );
2613 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002614 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002615 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002616 VG_(printf)(" Supported CPUs are:\n");
2617 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2618 "AMD Athlon or above)\n");
2619 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002620 VG_(exit)(1);
2621 }
2622 if (VG_(clo_verbosity) > 2) {
2623 VG_(message)(Vg_DebugMsg,
2624 "Host CPU: arch = %s, subarch = %s",
2625 LibVEX_ppVexArch( VG_(vex_arch) ),
2626 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2627 }
2628 }
2629
2630 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002631 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002632 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002633 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002634 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002635 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002636 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002637 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002638 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002639
sewardja4da2f32005-03-02 14:06:08 +00002640#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002641 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002642 // Protect client trampoline page (which is also sysinfo stuff)
2643 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002644 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002645 {
2646 Segment *seg;
2647 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2648 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002649#endif
nethercotec314eba2004-07-15 12:59:41 +00002650
sewardjb5f6f512005-03-10 23:59:00 +00002651 /* Make sure this segment isn't treated as stack */
2652 seg = VG_(find_segment)(VG_(client_trampoline_code));
2653 if (seg)
2654 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2655 }
2656
nethercotec314eba2004-07-15 12:59:41 +00002657 //==============================================================
2658 // Can use VG_(map)() after segments set up
2659 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002660
2661 //--------------------------------------------------------------
2662 // Allow GDB attach
2663 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2664 //--------------------------------------------------------------
2665 /* Hook to delay things long enough so we can get the pid and
2666 attach GDB in another shell. */
2667 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002668 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2669 /* jrs 20050206: I don't understand why this works on x86. On
2670 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2671 work. */
2672 /* do "jump *$eip" to skip this in gdb (x86) */
2673 //VG_(do_syscall0)(__NR_pause);
2674 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002675 }
2676
nethercote71980f02004-01-24 18:18:54 +00002677 // Search for file descriptors that are inherited from our parent
2678 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2679 //--------------------------------------------------------------
2680 if (VG_(clo_track_fds))
2681 VG_(init_preopened_fds)();
2682
2683 //--------------------------------------------------------------
2684 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002685 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2686 //--------------------------------------------------------------
2687 VG_(scheduler_init)();
2688
2689 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002690 // Initialise the pthread model
2691 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002692 // load_client() [for 'client_eip']
2693 // setup_client_stack() [for 'sp_at_startup']
2694 // setup_scheduler() [for the rest of state 1 stuff]
2695 //--------------------------------------------------------------
2696 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002697
2698 // Tell the tool that we just wrote to the registers.
2699 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2700 sizeof(VexGuestArchState));
2701
2702 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002703 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002704
2705 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002706 // Initialise the pthread model
2707 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002708 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002709 //if (VG_(clo_model_pthreads))
2710 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002711
2712 //--------------------------------------------------------------
2713 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002714 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002715 //--------------------------------------------------------------
2716 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2717 VG_(sigstartup_actions)();
2718
2719 //--------------------------------------------------------------
2720 // Perhaps we're profiling Valgrind?
2721 // p: process_cmd_line_options() [for VG_(clo_profile)]
2722 // p: others?
2723 //
2724 // XXX: this seems to be broken? It always says the tool wasn't built
2725 // for profiling; vg_profile.c's functions don't seem to be overriding
2726 // vg_dummy_profile.c's?
2727 //
2728 // XXX: want this as early as possible. Looking for --profile
2729 // in pre_process_cmd_line_options() could get it earlier.
2730 //--------------------------------------------------------------
2731 if (VG_(clo_profile))
2732 VGP_(init_profiling)();
2733
2734 VGP_PUSHCC(VgpStartup);
2735
2736 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002737 // Read suppression file
2738 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2739 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002740 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002741 VG_(load_suppressions)();
2742
2743 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002744 // Initialise translation table and translation cache
2745 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2746 // aren't identified as part of the client, which would waste
2747 // > 20M of virtual address space.]
2748 //--------------------------------------------------------------
2749 VG_(init_tt_tc)();
2750
2751 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002752 // Verbosity message
2753 // p: end_rdtsc_calibration [so startup message is printed first]
2754 //--------------------------------------------------------------
2755 if (VG_(clo_verbosity) == 1)
2756 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2757 if (VG_(clo_verbosity) > 0)
2758 VG_(message)(Vg_UserMsg, "");
2759
2760 //--------------------------------------------------------------
2761 // Setup pointercheck
2762 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2763 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002764 if (VG_(clo_pointercheck))
2765 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002766
nethercote71980f02004-01-24 18:18:54 +00002767 //--------------------------------------------------------------
2768 // Run!
2769 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002770 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002771
sewardjb5f6f512005-03-10 23:59:00 +00002772 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002773
sewardjb5f6f512005-03-10 23:59:00 +00002774 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002775
sewardjb5f6f512005-03-10 23:59:00 +00002776 abort();
2777}
2778
2779
2780/* Do everything which needs doing when the last thread exits */
2781void VG_(shutdown_actions)(ThreadId tid)
2782{
2783 vg_assert(tid == VG_(master_tid));
2784 vg_assert(VG_(is_running_thread)(tid));
2785
2786 // Wait for all other threads to exit.
2787 VGA_(reap_threads)(tid);
2788
2789 VG_(clo_model_pthreads) = False;
2790
2791 // Clean the client up before the final report
2792 VGA_(final_tidyup)(tid);
2793
2794 // OK, done
2795 VG_(exit_thread)(tid);
2796
2797 /* should be no threads left */
2798 vg_assert(VG_(count_living_threads)() == 0);
2799
2800 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002801 //--------------------------------------------------------------
2802 // Finalisation: cleanup, messages, etc. Order no so important, only
2803 // affects what order the messages come.
2804 //--------------------------------------------------------------
2805 if (VG_(clo_verbosity) > 0)
2806 VG_(message)(Vg_UserMsg, "");
2807
nethercote71980f02004-01-24 18:18:54 +00002808 /* Print out file descriptor summary and stats. */
2809 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002810 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002811
njn95ec8702004-11-22 16:46:13 +00002812 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002813 VG_(show_all_errors)();
2814
sewardjb5f6f512005-03-10 23:59:00 +00002815 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002816
nethercote885dd912004-08-03 23:14:00 +00002817 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002818
2819 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002820 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002821
nethercote71980f02004-01-24 18:18:54 +00002822 if (VG_(clo_profile))
2823 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002824 if (VG_(clo_profile_flags) > 0)
2825 VG_(show_BB_profile)();
2826
sewardj8b635a42004-11-22 19:01:47 +00002827 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002828 if (0)
2829 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002830
nethercote71980f02004-01-24 18:18:54 +00002831}
2832
sewardjde4a1d02002-03-22 01:27:54 +00002833/*--------------------------------------------------------------------*/
2834/*--- end vg_main.c ---*/
2835/*--------------------------------------------------------------------*/