blob: c924cbf4ad7db8fe5b0db87e21461519a390e4ec [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 */
njn67516132005-03-22 04:02:43 +0000327Addr VG_(get_SP) ( 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
njn67516132005-03-22 04:02:43 +0000332Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000333{
334 return INSTR_PTR( VG_(threads)[tid].arch );
335}
336
njnea4b28c2004-11-30 16:04:58 +0000337
nethercote71980f02004-01-24 18:18:54 +0000338/*====================================================================*/
339/*=== Check we were launched by stage 1 ===*/
340/*====================================================================*/
341
342/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000343static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000344{
nethercoteebf1d862004-11-01 18:22:05 +0000345 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000346 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000347
348 for (; auxv->a_type != AT_NULL; auxv++)
349 switch(auxv->a_type) {
350 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000351 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 1;
353 break;
354
355 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000356 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000357 found |= 2;
358 break;
nethercote7f390022004-10-25 17:18:24 +0000359
360 case AT_PHDR:
361 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
362 break;
nethercote71980f02004-01-24 18:18:54 +0000363 }
364
nethercote361a14e2004-07-26 11:11:56 +0000365 if ( found != (1|2) ) {
366 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000367 exit(127);
368 }
nethercote31779c72004-07-30 21:50:15 +0000369 vg_assert(padfile >= 0);
370 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000371}
372
373
374/*====================================================================*/
375/*=== Address space determination ===*/
376/*====================================================================*/
377
nethercote7f390022004-10-25 17:18:24 +0000378extern char _start[];
379
nethercote31779c72004-07-30 21:50:15 +0000380static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000381{
nethercotea3c3cf22004-11-01 18:38:00 +0000382 Int ires;
383 void* vres;
384 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000385
nethercote7f390022004-10-25 17:18:24 +0000386 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
387 // this is a workable approximation
388 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000389 VG_(valgrind_base) = PGROUNDDN(&_start);
390 }
391
nethercote820bd8c2004-09-07 23:04:49 +0000392 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote31779c72004-07-30 21:50:15 +0000394 // This gives the client the largest possible address space while
395 // taking into account the tool's shadow needs.
396 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000397 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000398 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000399 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000400 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000401 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000402 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000403
nethercote31779c72004-07-30 21:50:15 +0000404 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000405 VG_(shadow_end) = VG_(valgrind_base);
406 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000407
nethercotee2097312004-06-27 12:29:56 +0000408#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
409
nethercote71980f02004-01-24 18:18:54 +0000410 if (0)
nethercotee2097312004-06-27 12:29:56 +0000411 VG_(printf)(
412 "client_base %8x (%dMB)\n"
413 "client_mapbase %8x (%dMB)\n"
414 "client_end %8x (%dMB)\n"
415 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000416 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000417 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000418 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000419 VG_(client_base), SEGSIZE(client_base, client_mapbase),
420 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
421 VG_(client_end), SEGSIZE(client_end, shadow_base),
422 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000423 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000424 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
425 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000426 );
427
428#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000431 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000432 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000433 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000434
435 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000436 ires = munmap((void*)VG_(client_base), client_size);
437 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000438
439 // Map shadow memory.
440 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000441 if (shadow_size != 0) {
442 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000443 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000444 if ((void*)-1 == vres) {
445 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000446 "valgrind: Could not allocate address space (%p bytes)\n"
447 "valgrind: for shadow memory\n"
448 "valgrind: Possible causes:\n"
449 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
450 "valgrind: needs at least 1.5GB swap space.\n"
451 "valgrind: - Or, your virtual memory size may be limited (check\n"
452 "valgrind: with 'ulimit -v').\n"
453 "valgrind: - Or, your system may use a kernel that provides only a\n"
454 "valgrind: too-small (eg. 2GB) user address space.\n"
455 , (void*)shadow_size
456 );
nethercoted4722622004-08-30 19:36:42 +0000457 exit(1);
458 }
nethercotee567e702004-07-10 17:49:17 +0000459 }
nethercote71980f02004-01-24 18:18:54 +0000460}
461
462/*====================================================================*/
463/*=== Command line setup ===*/
464/*====================================================================*/
465
466/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
467static char* get_file_clo(char* dir)
468{
469# define FLEN 512
470 Int fd, n;
471 struct stat s1;
472 char* f_clo = NULL;
473 char filename[FLEN];
474
475 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
476 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
477 if ( fd > 0 ) {
478 if ( 0 == fstat(fd, &s1) ) {
479 f_clo = malloc(s1.st_size+1);
480 vg_assert(f_clo);
481 n = read(fd, f_clo, s1.st_size);
482 if (n == -1) n = 0;
483 f_clo[n] = '\0';
484 }
485 close(fd);
486 }
487 return f_clo;
488# undef FLEN
489}
490
nethercotee2097312004-06-27 12:29:56 +0000491#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
492
nethercote71980f02004-01-24 18:18:54 +0000493static Int count_args(char* s)
494{
495 Int n = 0;
496 if (s) {
497 char* cp = s;
498 while (True) {
499 // We have alternating sequences: blanks, non-blanks, blanks...
500 // count the non-blanks sequences.
501 while ( ISSPACE(*cp) ) cp++;
502 if ( !*cp ) break;
503 n++;
504 while ( !ISSPACE(*cp) && *cp ) cp++;
505 }
506 }
507 return n;
508}
509
510/* add args out of environment, skipping multiple spaces and -- args */
511static char** copy_args( char* s, char** to )
512{
513 if (s) {
514 char* cp = s;
515 while (True) {
516 // We have alternating sequences: blanks, non-blanks, blanks...
517 // copy the non-blanks sequences, and add terminating '\0'
518 while ( ISSPACE(*cp) ) cp++;
519 if ( !*cp ) break;
520 *to++ = cp;
521 while ( !ISSPACE(*cp) && *cp ) cp++;
522 if ( *cp ) *cp++ = '\0'; // terminate if necessary
523 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
524 }
525 }
526 return to;
527}
528
nethercotee2097312004-06-27 12:29:56 +0000529#undef ISSPACE
530
nethercote71980f02004-01-24 18:18:54 +0000531// Augment command line with arguments from environment and .valgrindrc
532// files.
533static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
534{
nethercotef6a1d502004-08-09 12:21:57 +0000535 int vg_argc0 = *vg_argc_inout;
536 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000537
538 char* env_clo = getenv(VALGRINDOPTS);
539 char* f1_clo = get_file_clo( getenv("HOME") );
540 char* f2_clo = get_file_clo(".");
541
542 /* copy any extra args from file or environment, if present */
543 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
544 /* ' ' separated extra options */
545 char **from;
546 char **to;
thughescaca0022004-09-13 10:20:34 +0000547 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
548
549 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
550
nethercote71980f02004-01-24 18:18:54 +0000551 env_arg_count = count_args(env_clo);
552 f1_arg_count = count_args(f1_clo);
553 f2_arg_count = count_args(f2_clo);
554
555 if (0)
556 printf("extra-argc=%d %d %d\n",
557 env_arg_count, f1_arg_count, f2_arg_count);
558
559 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000560 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000561 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000562 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000563 vg_assert(vg_argv0);
564 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000565
566 /* copy argv[0] */
567 *to++ = *from++;
568
569 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
570 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
571 * to override less local ones. */
572 to = copy_args(f1_clo, to);
573 to = copy_args(env_clo, to);
574 to = copy_args(f2_clo, to);
575
576 /* copy original arguments, stopping at command or -- */
577 while (*from) {
578 if (**from != '-')
579 break;
580 if (VG_STREQ(*from, "--")) {
581 from++; /* skip -- */
582 break;
583 }
584 *to++ = *from++;
585 }
586
587 /* add -- */
588 *to++ = "--";
589
nethercotef6a1d502004-08-09 12:21:57 +0000590 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000591
592 /* copy rest of original command line, then NULL */
593 while (*from) *to++ = *from++;
594 *to = NULL;
595 }
596
nethercotef6a1d502004-08-09 12:21:57 +0000597 *vg_argc_inout = vg_argc0;
598 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000599}
600
nethercotef6a1d502004-08-09 12:21:57 +0000601#define VG_CLO_SEP '\01'
602
nethercote71980f02004-01-24 18:18:54 +0000603static void get_command_line( int argc, char** argv,
604 Int* vg_argc_out, Char*** vg_argv_out,
605 char*** cl_argv_out )
606{
nethercotef6a1d502004-08-09 12:21:57 +0000607 int vg_argc0;
608 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000609 char** cl_argv;
610 char* env_clo = getenv(VALGRINDCLO);
611
612 if (env_clo != NULL && *env_clo != '\0') {
613 char *cp;
614 char **cpp;
615
nethercotef6a1d502004-08-09 12:21:57 +0000616 /* OK, VALGRINDCLO is set, which means we must be a child of another
617 Valgrind process using --trace-children, so we're getting all our
618 arguments from VALGRINDCLO, and the entire command line belongs to
619 the client (including argv[0]) */
620 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000621 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000622 if (*cp == VG_CLO_SEP)
623 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000624
nethercotef6a1d502004-08-09 12:21:57 +0000625 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
626 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000627
nethercotef6a1d502004-08-09 12:21:57 +0000628 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000629
630 *cpp++ = "valgrind"; /* nominal argv[0] */
631 *cpp++ = env_clo;
632
nethercotef6a1d502004-08-09 12:21:57 +0000633 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000634 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000635 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000636 *cp++ = '\0'; /* chop it up in place */
637 *cpp++ = cp;
638 }
639 }
640 *cpp = NULL;
641 cl_argv = argv;
642
643 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000644 Bool noaugment = False;
645
nethercote71980f02004-01-24 18:18:54 +0000646 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000647 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000648
nethercotef6a1d502004-08-09 12:21:57 +0000649 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000650 Char* arg = argv[vg_argc0];
651 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000652 break;
sewardjb5f6f512005-03-10 23:59:00 +0000653 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000654 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000655 break;
656 }
sewardjb5f6f512005-03-10 23:59:00 +0000657 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000658 }
nethercotef6a1d502004-08-09 12:21:57 +0000659 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000660
661 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000662 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000663 those extra args will already be present in VALGRINDCLO.
664 (We also don't do it when --command-line-only=yes.) */
665 if (!noaugment)
666 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000667 }
668
669 if (0) {
670 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000671 for (i = 0; i < vg_argc0; i++)
672 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000673 }
674
nethercotef6a1d502004-08-09 12:21:57 +0000675 *vg_argc_out = vg_argc0;
676 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000677 *cl_argv_out = cl_argv;
678}
679
680
681/*====================================================================*/
682/*=== Environment and stack setup ===*/
683/*====================================================================*/
684
685/* Scan a colon-separated list, and call a function on each element.
686 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000687 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000688 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000689
690 This routine will return True if (*func) returns True and False if
691 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000692*/
thughes4ad52d02004-06-27 17:37:21 +0000693static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000694{
695 char *cp, *entry;
696 int end;
697
698 if (colsep == NULL ||
699 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000700 return False;
nethercote71980f02004-01-24 18:18:54 +0000701
702 entry = cp = colsep;
703
704 do {
705 end = (*cp == '\0');
706
707 if (*cp == ':' || *cp == '\0') {
708 char save = *cp;
709
710 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000711 if ((*func)(entry)) {
712 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000713 return True;
thughes21942d92004-07-12 09:35:37 +0000714 }
nethercote71980f02004-01-24 18:18:54 +0000715 *cp = save;
716 entry = cp+1;
717 }
718 cp++;
719 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000720
721 return False;
722}
723
nethercote71980f02004-01-24 18:18:54 +0000724/* Prepare the client's environment. This is basically a copy of our
725 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000726 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000727
sewardjb5f6f512005-03-10 23:59:00 +0000728 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000729
730 Yummy. String hacking in C.
731
732 If this needs to handle any more variables it should be hacked
733 into something table driven.
734 */
735static char **fix_environment(char **origenv, const char *preload)
736{
737 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000738 static const char ld_preload[] = "LD_PRELOAD=";
739 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000740 static const int ld_preload_len = sizeof(ld_preload)-1;
741 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
742 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000743 char *inject_path;
744 int inject_path_len;
745 int vgliblen = strlen(VG_(libdir));
746 char **cpp;
747 char **ret;
748 int envc;
749 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
750
751 /* Find the vg_inject.so; also make room for the tool preload
752 library */
753 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
754 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000755 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000756
757 if (preload)
758 snprintf(inject_path, inject_path_len, "%s/%s:%s",
759 VG_(libdir), inject_so, preload);
760 else
761 snprintf(inject_path, inject_path_len, "%s/%s",
762 VG_(libdir), inject_so);
763
764 /* Count the original size of the env */
765 envc = 0; /* trailing NULL */
766 for (cpp = origenv; cpp && *cpp; cpp++)
767 envc++;
768
769 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000770 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000771 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000772
773 /* copy it over */
774 for (cpp = ret; *origenv; )
775 *cpp++ = *origenv++;
776 *cpp = NULL;
777
778 vg_assert(envc == (cpp - ret));
779
780 /* Walk over the new environment, mashing as we go */
781 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000782 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000783 int len = strlen(*cpp) + inject_path_len;
784 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000785 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000786
787 snprintf(cp, len, "%s%s:%s",
788 ld_preload, inject_path, (*cpp)+ld_preload_len);
789
790 *cpp = cp;
791
792 ld_preload_done = 1;
793 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
794 *cpp = "";
795 }
796 }
797
798 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000799 if (!ld_preload_done) {
800 int len = ld_preload_len + inject_path_len;
801 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000802 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000803
804 snprintf(cp, len, "%s%s",
805 ld_preload, inject_path);
806
807 ret[envc++] = cp;
808 }
809
sewardjb5f6f512005-03-10 23:59:00 +0000810 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000811 ret[envc] = NULL;
812
813 return ret;
814}
815
816extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000817
818/* Add a string onto the string table, and return its address */
819static char *copy_str(char **tab, const char *str)
820{
821 char *cp = *tab;
822 char *orig = cp;
823
824 while(*str)
825 *cp++ = *str++;
826 *cp++ = '\0';
827
828 if (0)
nethercote545fe672004-11-01 16:52:43 +0000829 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000830
831 *tab = cp;
832
833 return orig;
834}
835
836/*
837 This sets up the client's initial stack, containing the args,
838 environment and aux vector.
839
840 The format of the stack is:
841
842 higher address +-----------------+
843 | Trampoline code |
844 +-----------------+
845 | |
846 : string table :
847 | |
848 +-----------------+
849 | AT_NULL |
850 - -
851 | auxv |
852 +-----------------+
853 | NULL |
854 - -
855 | envp |
856 +-----------------+
857 | NULL |
858 - -
859 | argv |
860 +-----------------+
861 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000862 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000863 | undefined |
864 : :
865 */
nethercotec25c4492004-10-18 11:52:17 +0000866static Addr setup_client_stack(void* init_sp,
867 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000868 const struct exeinfo *info,
869 UInt** client_auxv)
870{
nethercotee567e702004-07-10 17:49:17 +0000871 void* res;
nethercote71980f02004-01-24 18:18:54 +0000872 char **cpp;
873 char *strtab; /* string table */
874 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000875 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000876 struct ume_auxv *auxv;
877 const struct ume_auxv *orig_auxv;
878 const struct ume_auxv *cauxv;
879 unsigned stringsize; /* total size of strings in bytes */
880 unsigned auxsize; /* total size of auxv in bytes */
881 int argc; /* total argc */
882 int envc; /* total number of env vars */
883 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000884 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000885
886 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000887 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000888
889 /* ==================== compute sizes ==================== */
890
891 /* first of all, work out how big the client stack will be */
892 stringsize = 0;
893
894 /* paste on the extra args if the loader needs them (ie, the #!
895 interpreter and its argument) */
896 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000897 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000898 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000899 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000900 }
nethercoted6a56872004-07-26 15:32:47 +0000901 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000902 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000903 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000904 }
905
906 /* now scan the args we're given... */
907 for (cpp = orig_argv; *cpp; cpp++) {
908 argc++;
909 stringsize += strlen(*cpp) + 1;
910 }
911
912 /* ...and the environment */
913 envc = 0;
914 for (cpp = orig_envp; cpp && *cpp; cpp++) {
915 envc++;
916 stringsize += strlen(*cpp) + 1;
917 }
918
919 /* now, how big is the auxv? */
920 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
921 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
922 if (cauxv->a_type == AT_PLATFORM)
923 stringsize += strlen(cauxv->u.a_ptr) + 1;
924 auxsize += sizeof(*cauxv);
925 }
926
927 /* OK, now we know how big the client stack is */
928 stacksize =
929 sizeof(int) + /* argc */
930 sizeof(char **)*argc + /* argv */
931 sizeof(char **) + /* terminal NULL */
932 sizeof(char **)*envc + /* envp */
933 sizeof(char **) + /* terminal NULL */
934 auxsize + /* auxv */
935 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000936 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000937
sewardj79048ce2005-02-18 08:28:32 +0000938 if (0) VG_(printf)("stacksize = %d\n", stacksize);
939
nethercotef84f6952004-07-15 14:58:33 +0000940 // decide where stack goes!
941 VG_(clstk_end) = VG_(client_end);
942
nethercote73b526f2004-10-31 18:48:21 +0000943 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000944
nethercote71980f02004-01-24 18:18:54 +0000945 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000946 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000947 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
948
nethercote71980f02004-01-24 18:18:54 +0000949 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000950 stringbase = strtab = (char *)(VG_(client_trampoline_code)
951 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000952
953 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000954
sewardj79048ce2005-02-18 08:28:32 +0000955 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000956 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000957 "clstk_base %p\n"
958 "clstk_end %p\n",
959 stringsize, auxsize, stacksize,
960 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000961
nethercote71980f02004-01-24 18:18:54 +0000962 /* ==================== allocate space ==================== */
963
964 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000965 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000966 PROT_READ | PROT_WRITE | PROT_EXEC,
967 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
968 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000969
970 /* ==================== copy client stack ==================== */
971
nethercotea3c3cf22004-11-01 18:38:00 +0000972 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000973
974 /* --- argc --- */
975 *ptr++ = argc; /* client argc */
976
977 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000978 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000979 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000980 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000981 }
nethercoted6a56872004-07-26 15:32:47 +0000982 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000983 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000984 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000985 }
986 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000987 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000988 }
989 *ptr++ = 0;
990
991 /* --- envp --- */
992 VG_(client_envp) = (Char **)ptr;
993 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000994 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000995 *ptr++ = 0;
996
997 /* --- auxv --- */
998 auxv = (struct ume_auxv *)ptr;
999 *client_auxv = (UInt *)auxv;
1000
1001 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1002 /* copy the entry... */
1003 *auxv = *orig_auxv;
1004
1005 /* ...and fix up the copy */
1006 switch(auxv->a_type) {
1007 case AT_PHDR:
1008 if (info->phdr == 0)
1009 auxv->a_type = AT_IGNORE;
1010 else
1011 auxv->u.a_val = info->phdr;
1012 break;
1013
1014 case AT_PHNUM:
1015 if (info->phdr == 0)
1016 auxv->a_type = AT_IGNORE;
1017 else
1018 auxv->u.a_val = info->phnum;
1019 break;
1020
1021 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001022 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001023 break;
1024
1025 case AT_PLATFORM: /* points to a platform description string */
1026 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1027 break;
1028
1029 case AT_ENTRY:
1030 auxv->u.a_val = info->entry;
1031 break;
1032
1033 case AT_IGNORE:
1034 case AT_EXECFD:
1035 case AT_PHENT:
1036 case AT_PAGESZ:
1037 case AT_FLAGS:
1038 case AT_NOTELF:
1039 case AT_UID:
1040 case AT_EUID:
1041 case AT_GID:
1042 case AT_EGID:
1043 case AT_CLKTCK:
1044 case AT_HWCAP:
1045 case AT_FPUCW:
1046 case AT_DCACHEBSIZE:
1047 case AT_ICACHEBSIZE:
1048 case AT_UCACHEBSIZE:
1049 /* All these are pointerless, so we don't need to do anything
1050 about them. */
1051 break;
1052
1053 case AT_SECURE:
1054 /* If this is 1, then it means that this program is running
1055 suid, and therefore the dynamic linker should be careful
1056 about LD_PRELOAD, etc. However, since stage1 (the thing
1057 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001058 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001059 set AT_SECURE to 0. */
1060 auxv->u.a_val = 0;
1061 break;
1062
1063 case AT_SYSINFO:
1064 /* Leave this unmolested for now, but we'll update it later
1065 when we set up the client trampoline code page */
1066 break;
1067
1068 case AT_SYSINFO_EHDR:
1069 /* Trash this, because we don't reproduce it */
1070 auxv->a_type = AT_IGNORE;
1071 break;
1072
1073 default:
1074 /* stomp out anything we don't know about */
1075 if (0)
nethercote545fe672004-11-01 16:52:43 +00001076 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001077 auxv->a_type = AT_IGNORE;
1078 break;
1079
1080 }
1081 }
1082 *auxv = *orig_auxv;
1083 vg_assert(auxv->a_type == AT_NULL);
1084
njnc6168192004-11-29 13:54:10 +00001085// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1086// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001087#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001088 /* --- trampoline page --- */
1089 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1090 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001091#endif
nethercotef84f6952004-07-15 14:58:33 +00001092
nethercote71980f02004-01-24 18:18:54 +00001093 vg_assert((strtab-stringbase) == stringsize);
1094
nethercote5ee67ca2004-06-22 14:00:09 +00001095 /* We know the initial ESP is pointing at argc/argv */
1096 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001097 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001098
sewardj79048ce2005-02-18 08:28:32 +00001099 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001100 return cl_esp;
1101}
1102
1103/*====================================================================*/
1104/*=== Find executable ===*/
1105/*====================================================================*/
1106
thughes4ad52d02004-06-27 17:37:21 +00001107static const char* executable_name;
1108
1109static Bool match_executable(const char *entry) {
1110 char buf[strlen(entry) + strlen(executable_name) + 2];
1111
1112 /* empty PATH element means . */
1113 if (*entry == '\0')
1114 entry = ".";
1115
1116 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1117
1118 if (access(buf, R_OK|X_OK) == 0) {
1119 executable_name = strdup(buf);
1120 vg_assert(NULL != executable_name);
1121 return True;
1122 }
1123 return False;
1124}
1125
nethercote71980f02004-01-24 18:18:54 +00001126static const char* find_executable(const char* exec)
1127{
1128 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001129 executable_name = exec;
1130 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001131 /* no '/' - we need to search the path */
1132 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001133 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001134 }
thughes4ad52d02004-06-27 17:37:21 +00001135 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001136}
1137
1138
1139/*====================================================================*/
1140/*=== Loading tools ===*/
1141/*====================================================================*/
1142
1143static void list_tools(void)
1144{
1145 DIR *dir = opendir(VG_(libdir));
1146 struct dirent *de;
1147 int first = 1;
1148
1149 if (dir == NULL) {
1150 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001151 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001152 return;
1153 }
1154
nethercotef4928da2004-06-15 10:54:40 +00001155 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001156 int len = strlen(de->d_name);
1157
njn063c5402004-11-22 16:58:05 +00001158 /* look for vgtool_TOOL.so names */
1159 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1160 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001161 VG_STREQ(de->d_name + len - 3, ".so")) {
1162 if (first) {
1163 fprintf(stderr, "Available tools:\n");
1164 first = 0;
1165 }
1166 de->d_name[len-3] = '\0';
1167 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001168 }
1169 }
1170
1171 closedir(dir);
1172
1173 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001174 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1175 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001176}
1177
1178
1179/* Find and load a tool, and check it looks ok. Also looks to see if there's
1180 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1181static void load_tool( const char *toolname, void** handle_out,
1182 ToolInfo** toolinfo_out, char **preloadpath_out )
1183{
1184 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001185 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001186 char buf[len];
1187 void* handle;
1188 ToolInfo* toolinfo;
1189 char* preloadpath = NULL;
1190 Int* vg_malloc_redzonep;
1191
1192 // XXX: allowing full paths for --tool option -- does it make sense?
1193 // Doesn't allow for vgpreload_<tool>.so.
1194
1195 if (strchr(toolname, '/') != 0) {
1196 /* toolname contains '/', and so must be a pathname */
1197 handle = dlopen(toolname, RTLD_NOW);
1198 } else {
1199 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001200 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001201 handle = dlopen(buf, RTLD_NOW);
1202
1203 if (handle != NULL) {
1204 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1205 if (access(buf, R_OK) == 0) {
1206 preloadpath = strdup(buf);
1207 vg_assert(NULL != preloadpath);
1208 }
1209 }
1210 }
1211
1212 ok = (NULL != handle);
1213 if (!ok) {
1214 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1215 goto bad_load;
1216 }
1217
njn26f02512004-11-22 18:33:15 +00001218 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001219 ok = (NULL != toolinfo);
1220 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001221 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001222 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1223 goto bad_load;
1224 }
1225
1226 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1227 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001228 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001229 if (!ok) {
1230 fprintf(stderr, "Error:\n"
1231 " Tool and core interface versions do not match.\n"
1232 " Interface version used by core is: %d.%d (size %d)\n"
1233 " Interface version used by tool is: %d.%d (size %d)\n"
1234 " The major version numbers must match.\n",
1235 VG_CORE_INTERFACE_MAJOR_VERSION,
1236 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001237 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001238 toolinfo->interface_major_version,
1239 toolinfo->interface_minor_version,
1240 toolinfo->sizeof_ToolInfo);
1241 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1242 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001243 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001244 else
nethercote996901a2004-08-03 13:29:09 +00001245 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001246 goto bad_load;
1247 }
1248
1249 // Set redzone size for V's allocator
1250 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1251 if ( NULL != vg_malloc_redzonep ) {
1252 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1253 }
1254
1255 vg_assert(NULL != handle && NULL != toolinfo);
1256 *handle_out = handle;
1257 *toolinfo_out = toolinfo;
1258 *preloadpath_out = preloadpath;
1259 return;
1260
1261
1262 bad_load:
1263 if (handle != NULL)
1264 dlclose(handle);
1265
nethercotef4928da2004-06-15 10:54:40 +00001266 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001267 list_tools();
1268 exit(127);
1269}
1270
nethercotef4928da2004-06-15 10:54:40 +00001271
1272/*====================================================================*/
1273/*=== Command line errors ===*/
1274/*====================================================================*/
1275
1276static void abort_msg ( void )
1277{
nethercotef8548672004-06-21 12:42:35 +00001278 VG_(clo_log_to) = VgLogTo_Fd;
1279 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001280}
1281
1282void VG_(bad_option) ( Char* opt )
1283{
1284 abort_msg();
1285 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1286 VG_(printf)("valgrind: Use --help for more information.\n");
1287 VG_(exit)(1);
1288}
1289
nethercotef4928da2004-06-15 10:54:40 +00001290static void missing_prog ( void )
1291{
1292 abort_msg();
1293 VG_(printf)("valgrind: no program specified\n");
1294 VG_(printf)("valgrind: Use --help for more information.\n");
1295 VG_(exit)(1);
1296}
1297
1298static void config_error ( Char* msg )
1299{
1300 abort_msg();
1301 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1302 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1303 VG_(exit)(1);
1304}
1305
1306
nethercote71980f02004-01-24 18:18:54 +00001307/*====================================================================*/
1308/*=== Loading the client ===*/
1309/*====================================================================*/
1310
nethercotef4928da2004-06-15 10:54:40 +00001311static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001312 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1313{
1314 // If they didn't specify an executable with --exec, and didn't specify
1315 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001316 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001317 if (cl_argv[0] == NULL ||
1318 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1319 {
nethercotef4928da2004-06-15 10:54:40 +00001320 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001321 }
1322 }
1323
1324 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001325 info->exe_base = VG_(client_base);
1326 info->exe_end = VG_(client_end);
1327 info->argv = cl_argv;
1328
nethercotef4928da2004-06-15 10:54:40 +00001329 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001330 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001331 // Totally zero 'info' before continuing.
1332 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001333 } else {
1334 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001335 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001336 ret = do_exec(exec, info);
1337 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001338 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1339 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001340 exit(127);
1341 }
1342 }
1343
1344 /* Copy necessary bits of 'info' that were filled in */
1345 *client_eip = info->init_eip;
1346 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1347}
1348
nethercote969ecf12004-10-13 17:29:01 +00001349/*====================================================================*/
1350/*=== Address space unpadding ===*/
1351/*====================================================================*/
1352
1353typedef struct {
1354 char* killpad_start;
1355 char* killpad_end;
1356 struct stat* killpad_padstat;
1357} killpad_extra;
1358
1359static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1360 int maj, int min, int ino, void* ex)
1361{
1362 killpad_extra* extra = ex;
1363 void *b, *e;
1364 int res;
1365
1366 vg_assert(NULL != extra->killpad_padstat);
1367
1368 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1369 extra->killpad_padstat->st_ino != ino)
1370 return 1;
1371
1372 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1373 return 1;
1374
1375 if (segstart <= extra->killpad_start)
1376 b = extra->killpad_start;
1377 else
1378 b = segstart;
1379
1380 if (segend >= extra->killpad_end)
1381 e = extra->killpad_end;
1382 else
1383 e = segend;
1384
1385 res = munmap(b, (char *)e-(char *)b);
1386 vg_assert(0 == res);
1387
1388 return 1;
1389}
1390
1391// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001392static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001393{
1394 static struct stat padstat;
1395 killpad_extra extra;
1396 int res;
1397
sewardjb5f6f512005-03-10 23:59:00 +00001398 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001399
1400 res = fstat(padfile, &padstat);
1401 vg_assert(0 == res);
1402 extra.killpad_padstat = &padstat;
1403 extra.killpad_start = start;
1404 extra.killpad_end = end;
1405 foreach_map(killpad, &extra);
1406}
1407
sewardj2c5ffbe2005-03-12 13:32:06 +00001408static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001409{
1410 int res = close(padfile);
1411 vg_assert(0 == res);
1412}
1413
nethercote71980f02004-01-24 18:18:54 +00001414
1415/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001416/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001417/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001418
njn25e49d8e72002-09-23 09:36:25 +00001419/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001420VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001421Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001422Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001423Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001424Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001425Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001426Int VG_(clo_verbosity) = 1;
1427Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001428Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001429
nethercotef1e5e152004-09-01 23:58:16 +00001430/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001431 fd is initially stdout, for --help, but gets moved to stderr by default
1432 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001433VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001434Int VG_(clo_log_fd) = 1;
1435Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001436
thughes6233a382004-08-21 11:10:44 +00001437Bool VG_(clo_time_stamp) = False;
1438
sewardj6024b212003-07-13 10:54:33 +00001439Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001440Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001441Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001442Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001443UChar VG_(clo_trace_flags) = 0; // 00000000b
1444UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001445Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001446Bool VG_(clo_trace_syscalls) = False;
1447Bool VG_(clo_trace_signals) = False;
1448Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001449Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001450Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001451Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001452Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001453Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001454Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001455Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001456Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001457Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001458Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001459Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001460Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001461Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001462Bool VG_(clo_show_emwarns) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001463
jsgf855d93d2003-10-13 22:26:55 +00001464static Bool VG_(clo_wait_for_gdb) = False;
1465
sewardjde4a1d02002-03-22 01:27:54 +00001466
sewardj2c5ffbe2005-03-12 13:32:06 +00001467static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001468{
njn25e49d8e72002-09-23 09:36:25 +00001469 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001470"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001471"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001472" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001473" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001474" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001475" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001476" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001477" -q --quiet run silently; only print error msgs\n"
1478" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001479" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001480" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001481" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001482"\n"
1483" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001484" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001485" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001486" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001487" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001488" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001489"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001490" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001491" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1492" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001493" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001494" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001495" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001496" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001497" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1498" --show-below-main=no|yes continue stack traces below main() [no]\n"
1499" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001500" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001501" --db-attach=no|yes start debugger when errors detected? [no]\n"
1502" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1503" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001504"\n";
njn7cf0bd32002-06-08 13:36:03 +00001505
njn25e49d8e72002-09-23 09:36:25 +00001506 Char* usage2 =
1507"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001508" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001509" --sanity-level=<number> level of sanity checking to do [1]\n"
1510" --single-step=no|yes translate each instr separately? [no]\n"
1511" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001512" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001513" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001514" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1515" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001516" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001517" --trace-syscalls=no|yes show all system calls? [no]\n"
1518" --trace-signals=no|yes show signal handling details? [no]\n"
1519" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001520" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001521" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001522#if 0
1523" --model-pthreads=yes|no model the pthreads library [no]\n"
1524#endif
1525" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001526"\n"
1527" --vex-iropt-verbosity 0 .. 9 [0]\n"
1528" --vex-iropt-level 0 .. 2 [2]\n"
1529" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001530" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1531" --vex-guest-max-insns 1 .. 100 [50]\n"
1532" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1533"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001534" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001535" 1000 0000 show conversion into IR\n"
1536" 0100 0000 show after initial opt\n"
1537" 0010 0000 show after instrumentation\n"
1538" 0001 0000 show after second opt\n"
1539" 0000 1000 show after tree building\n"
1540" 0000 0100 show selecting insns\n"
1541" 0000 0010 show after reg-alloc\n"
1542" 0000 0001 show final assembly\n"
1543"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001544" debugging options for Valgrind tools that report errors\n"
1545" --dump-error=<number> show translation for basic block associated\n"
1546" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001547"\n";
njn3e884182003-04-15 13:03:23 +00001548
1549 Char* usage3 =
1550"\n"
nethercote71980f02004-01-24 18:18:54 +00001551" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001552"\n"
njn53612422005-03-12 16:22:54 +00001553" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001554" and licensed under the GNU General Public License, version 2.\n"
1555" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001556"\n"
nethercote137bc552003-11-14 17:47:54 +00001557" Tools are copyright and licensed by their authors. See each\n"
1558" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001559"\n";
njn7cf0bd32002-06-08 13:36:03 +00001560
fitzhardinge98abfc72003-12-16 02:05:15 +00001561 VG_(printf)(usage1);
1562 if (VG_(details).name) {
1563 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001564 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001565 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001566 else
1567 VG_(printf)(" (none)\n");
1568 }
nethercote6c999f22004-01-31 22:55:15 +00001569 if (debug_help) {
1570 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001571
nethercote6c999f22004-01-31 22:55:15 +00001572 if (VG_(details).name) {
1573 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1574
1575 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001576 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001577 else
1578 VG_(printf)(" (none)\n");
1579 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001580 }
nethercote421281e2003-11-20 16:20:55 +00001581 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001582 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001583}
sewardjde4a1d02002-03-22 01:27:54 +00001584
nethercote71980f02004-01-24 18:18:54 +00001585static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001586 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001587{
nethercote71980f02004-01-24 18:18:54 +00001588 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001589
sewardj8b635a42004-11-22 19:01:47 +00001590 LibVEX_default_VexControl(& VG_(clo_vex_control));
1591
nethercote71980f02004-01-24 18:18:54 +00001592 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001593 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001594
nethercotef6a1d502004-08-09 12:21:57 +00001595 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001596 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001597 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001598
nethercotef6a1d502004-08-09 12:21:57 +00001599 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1600 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001601 *need_help = 1;
1602
nethercotef6a1d502004-08-09 12:21:57 +00001603 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001604 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001605
nethercotef6c99d72004-11-09 14:35:43 +00001606 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001607 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001608
nethercotef6a1d502004-08-09 12:21:57 +00001609 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1610 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001611 }
1612 }
nethercote71980f02004-01-24 18:18:54 +00001613}
1614
nethercote5ee67ca2004-06-22 14:00:09 +00001615static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001616{
nethercotef8548672004-06-21 12:42:35 +00001617 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001618 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001619
nethercotee1730692003-11-20 10:38:07 +00001620 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001621 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001622
sewardj19d81412002-06-03 01:10:40 +00001623 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001624 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001625 config_error("Please use absolute paths in "
1626 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001627
njnc6168192004-11-29 13:54:10 +00001628// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001629#ifdef __x86__
1630 {
sewardjb5f6f512005-03-10 23:59:00 +00001631 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001632 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1633 switch(auxp[0]) {
1634 case AT_SYSINFO:
1635 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1636 break;
1637 }
1638 }
1639 }
1640#endif
sewardjde4a1d02002-03-22 01:27:54 +00001641
nethercotef6a1d502004-08-09 12:21:57 +00001642 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001643
nethercotef6a1d502004-08-09 12:21:57 +00001644 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001645 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001646
thughes3bfd5a02004-07-18 08:05:44 +00001647 /* Look for a colon in the switch name */
1648 while (*colon && *colon != ':' && *colon != '=')
1649 colon++;
nethercote71980f02004-01-24 18:18:54 +00001650
1651 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001652 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001653 if (VG_CLO_STREQN(2, arg, "--") &&
1654 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1655 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1656 {
1657 // prefix matches, convert "--toolname:foo" to "--foo"
1658 if (0)
1659 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001660 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001661 arg[0] = '-';
1662 arg[1] = '-';
1663
1664 } else {
1665 // prefix doesn't match, skip to next arg
1666 continue;
1667 }
1668 }
1669
fitzhardinge98abfc72003-12-16 02:05:15 +00001670 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001671 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001672 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001673 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001674 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001675 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001676 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001677
nethercote71980f02004-01-24 18:18:54 +00001678 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001679 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001680
nethercote71980f02004-01-24 18:18:54 +00001681 else if (VG_CLO_STREQ(arg, "-v") ||
1682 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001683 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001684
nethercote71980f02004-01-24 18:18:54 +00001685 else if (VG_CLO_STREQ(arg, "-q") ||
1686 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001687 VG_(clo_verbosity)--;
1688
nethercote27fec902004-06-16 21:26:32 +00001689 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001690 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1691 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1692 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001693 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001694 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
sewardjb1131a82005-03-19 15:12:21 +00001695 else VG_BOOL_CLO("--show-emwarns", VG_(clo_show_emwarns))
nethercote27fec902004-06-16 21:26:32 +00001696 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1697 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1698 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001699 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001700 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1701 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1702 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1703 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1704 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001705 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001706 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001707 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001708 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001709 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001710
nethercote27fec902004-06-16 21:26:32 +00001711 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1712 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001713
nethercote27fec902004-06-16 21:26:32 +00001714 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1715 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1716 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001717 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1718 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001719
sewardj8b635a42004-11-22 19:01:47 +00001720 else VG_BNUM_CLO("--vex-iropt-verbosity",
1721 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1722 else VG_BNUM_CLO("--vex-iropt-level",
1723 VG_(clo_vex_control).iropt_level, 0, 2)
1724 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1725 VG_(clo_vex_control).iropt_precise_memory_exns)
1726 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1727 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1728 else VG_BNUM_CLO("--vex-guest-max-insns",
1729 VG_(clo_vex_control).guest_max_insns, 1, 100)
1730 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1731 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1732
nethercotef8548672004-06-21 12:42:35 +00001733 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001734 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001735 VG_(clo_log_to) = VgLogTo_Fd;
1736 VG_(clo_log_name) = NULL;
1737 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1738 }
1739 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1740 VG_(clo_log_to) = VgLogTo_Fd;
1741 VG_(clo_log_name) = NULL;
1742 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001743 }
1744
nethercotef8548672004-06-21 12:42:35 +00001745 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001746 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001747 VG_(clo_log_to) = VgLogTo_File;
1748 VG_(clo_log_name) = &arg[10];
1749 }
1750 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1751 VG_(clo_log_to) = VgLogTo_File;
1752 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001753 }
sewardj603d4102005-01-11 14:01:02 +00001754 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1755 VG_(clo_log_to) = VgLogTo_FileExactly;
1756 VG_(clo_log_name) = &arg[19];
1757 }
sewardjde4a1d02002-03-22 01:27:54 +00001758
nethercotef8548672004-06-21 12:42:35 +00001759 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001760 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001761 VG_(clo_log_to) = VgLogTo_Socket;
1762 VG_(clo_log_name) = &arg[12];
1763 }
1764 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1765 VG_(clo_log_to) = VgLogTo_Socket;
1766 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001767 }
1768
nethercote71980f02004-01-24 18:18:54 +00001769 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001770 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001771 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001772 VG_(message)(Vg_UserMsg,
1773 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001774 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001775 }
nethercote71980f02004-01-24 18:18:54 +00001776 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001777 VG_(clo_n_suppressions)++;
1778 }
sewardjde4a1d02002-03-22 01:27:54 +00001779
sewardjfa8ec112005-01-19 11:55:34 +00001780 /* "stuvwxyz" --> stuvwxyz (binary) */
1781 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1782 Int j;
1783 char* opt = & arg[14];
1784
1785 if (8 != VG_(strlen)(opt)) {
1786 VG_(message)(Vg_UserMsg,
1787 "--trace-flags argument must have 8 digits");
1788 VG_(bad_option)(arg);
1789 }
1790 for (j = 0; j < 8; j++) {
1791 if ('0' == opt[j]) { /* do nothing */ }
1792 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1793 else {
1794 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1795 "contain 0s and 1s");
1796 VG_(bad_option)(arg);
1797 }
1798 }
1799 }
1800
1801 /* "stuvwxyz" --> stuvwxyz (binary) */
1802 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001803 Int j;
nethercote71980f02004-01-24 18:18:54 +00001804 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001805
sewardj2a99cf62004-11-24 10:44:19 +00001806 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001807 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001808 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001809 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001810 }
sewardj8b635a42004-11-22 19:01:47 +00001811 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001812 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001813 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001814 else {
sewardjfa8ec112005-01-19 11:55:34 +00001815 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001816 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001817 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001818 }
1819 }
1820 }
sewardjde4a1d02002-03-22 01:27:54 +00001821
sewardjc771b292004-11-30 18:55:21 +00001822 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1823
sewardjd153fae2005-01-10 17:24:47 +00001824 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1825 VG_(clo_gen_suppressions) = 0;
1826 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1827 VG_(clo_gen_suppressions) = 1;
1828 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1829 VG_(clo_gen_suppressions) = 2;
1830
nethercote71980f02004-01-24 18:18:54 +00001831 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001832 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001833 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001834 }
njn8c0b3bb2005-03-12 21:20:39 +00001835 skip_arg:
1836 if (arg != vg_argv[i])
1837 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001838 }
1839
sewardj998d40d2004-12-06 14:24:52 +00001840 /* Make VEX control parameters sane */
1841
1842 if (VG_(clo_vex_control).guest_chase_thresh
1843 >= VG_(clo_vex_control).guest_max_insns)
1844 VG_(clo_vex_control).guest_chase_thresh
1845 = VG_(clo_vex_control).guest_max_insns - 1;
1846
1847 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1848 VG_(clo_vex_control).guest_chase_thresh = 0;
1849
1850 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001851
njnf9ebf672003-05-12 21:41:30 +00001852 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001853 VG_(clo_verbosity) = 0;
1854
nethercote04d0fbc2004-01-26 16:48:06 +00001855 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001856 VG_(message)(Vg_UserMsg, "");
1857 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001858 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001859 VG_(message)(Vg_UserMsg,
1860 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001861 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001862 }
1863
nethercotef8548672004-06-21 12:42:35 +00001864 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001865 should be connected to whatever sink has been selected, and we
1866 indiscriminately chuck stuff into it without worrying what the
1867 nature of it is. Oh the wonder of Unix streams. */
1868
nethercotee1730692003-11-20 10:38:07 +00001869 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001870 the terminal any problems to do with processing command line
1871 opts. */
nethercotef8548672004-06-21 12:42:35 +00001872 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001873 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001874
1875 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001876
sewardj4cf05692002-10-27 20:28:29 +00001877 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001878 vg_assert(VG_(clo_log_name) == NULL);
1879 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001880 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001881
sewardj4cf05692002-10-27 20:28:29 +00001882 case VgLogTo_File: {
1883 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001884 Int seq = 0;
1885 Int pid = VG_(getpid)();
1886
nethercotef8548672004-06-21 12:42:35 +00001887 vg_assert(VG_(clo_log_name) != NULL);
1888 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001889
nethercote71980f02004-01-24 18:18:54 +00001890 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001891 if (seq == 0)
1892 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001893 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001894 else
1895 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001896 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001897 seq++;
1898
nethercotef8548672004-06-21 12:42:35 +00001899 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001900 = VG_(open)(logfilename,
1901 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1902 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001903 if (eventually_log_fd >= 0) {
1904 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001905 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001906 } else {
nethercotef8548672004-06-21 12:42:35 +00001907 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001908 VG_(message)(Vg_UserMsg,
1909 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001910 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001911 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001912 "--log-file=<file> (didn't work out for some reason.)");
1913 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001914 }
1915 }
1916 }
sewardj603d4102005-01-11 14:01:02 +00001917 break; /* switch (VG_(clo_log_to)) */
1918 }
1919
1920 case VgLogTo_FileExactly: {
1921 Char logfilename[1000];
1922
1923 vg_assert(VG_(clo_log_name) != NULL);
1924 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1925 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1926
1927 eventually_log_fd
1928 = VG_(open)(logfilename,
1929 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1930 VKI_S_IRUSR|VKI_S_IWUSR);
1931 if (eventually_log_fd >= 0) {
1932 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1933 }
1934 else if (eventually_log_fd != -VKI_EEXIST) {
1935 VG_(message)(Vg_UserMsg,
1936 "Can't create/open log file `%s'; giving up!",
1937 VG_(clo_log_name));
1938 VG_(bad_option)(
1939 "--log-file-exactly=<file> (didn't work out for some reason.)");
1940 /*NOTREACHED*/
1941 }
1942 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001943 }
1944
1945 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001946 vg_assert(VG_(clo_log_name) != NULL);
1947 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1948 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1949 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001950 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001951 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001952 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001953 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001954 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001955 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001956 }
nethercotef8548672004-06-21 12:42:35 +00001957 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001958 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001959 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001960 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001961 VG_(message)(Vg_UserMsg,
1962 "Log messages will sent to stderr instead." );
1963 VG_(message)(Vg_UserMsg,
1964 "" );
1965 /* We don't change anything here. */
1966 } else {
nethercotef8548672004-06-21 12:42:35 +00001967 vg_assert(eventually_log_fd > 0);
1968 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001969 VG_(logging_to_filedes) = False;
1970 }
sewardj73cf3bc2002-11-03 03:20:15 +00001971 break;
1972 }
1973
sewardj4cf05692002-10-27 20:28:29 +00001974 }
1975
nethercotef8548672004-06-21 12:42:35 +00001976 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001977 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001978 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001979 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1980 else {
nethercotef8548672004-06-21 12:42:35 +00001981 VG_(clo_log_fd) = eventually_log_fd;
1982 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001983 }
1984
sewardj4cf05692002-10-27 20:28:29 +00001985 /* Ok, the logging sink is running now. Print a suitable preamble.
1986 If logging to file or a socket, write details of parent PID and
1987 command line args, to help people trying to interpret the
1988 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001989
sewardj83adf412002-05-01 01:25:45 +00001990 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001991 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001992 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001993 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001994 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001995 NULL == VG_(details).version
1996 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001997 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001998 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00001999
njnd04b7c62002-10-03 14:05:52 +00002000 /* Core details */
2001 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00002002 "Using LibVEX rev %s, a library for dynamic binary translation.",
2003 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00002004 VG_(message)(Vg_UserMsg,
2005 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2006 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002007 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002008 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002009 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002010 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002011 }
2012
nethercotec1e395d2003-11-10 13:26:49 +00002013 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002014 VG_(message)(Vg_UserMsg, "");
2015 VG_(message)(Vg_UserMsg,
2016 "My PID = %d, parent PID = %d. Prog and args are:",
2017 VG_(getpid)(), VG_(getppid)() );
2018 for (i = 0; i < VG_(client_argc); i++)
2019 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2020 }
2021
sewardjde4a1d02002-03-22 01:27:54 +00002022 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002023 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002024 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002025 VG_(message)(Vg_DebugMsg, "");
2026 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2027 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002028 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002029 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002030
njn1fd5eb22005-03-13 05:43:23 +00002031 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002032 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002033 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002034 }
nethercotea70f7352004-04-18 12:08:46 +00002035
njn1fd5eb22005-03-13 05:43:23 +00002036 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002037 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2038 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002039 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002040 } else {
2041 #define BUF_LEN 256
2042 Char version_buf[BUF_LEN];
2043 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2044 vg_assert(n <= 256);
2045 if (n > 0) {
2046 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002047 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002048 } else {
njn1fd5eb22005-03-13 05:43:23 +00002049 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002050 }
2051 VG_(close)(fd);
2052 #undef BUF_LEN
2053 }
sewardjde4a1d02002-03-22 01:27:54 +00002054 }
2055
fitzhardinge98abfc72003-12-16 02:05:15 +00002056 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002057 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002058 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002059 needs one, load the default */
2060 static const Char default_supp[] = "default.supp";
2061 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2062 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2063 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2064 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2065 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002066 }
sewardj4cf05692002-10-27 20:28:29 +00002067
sewardjd153fae2005-01-10 17:24:47 +00002068 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002069 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002070 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002071 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002072 VG_(message)(Vg_UserMsg,
2073 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002074 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002075 }
sewardjde4a1d02002-03-22 01:27:54 +00002076}
2077
nethercotef6a1d502004-08-09 12:21:57 +00002078// Build the string for VALGRINDCLO.
2079Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2080{
2081 /* If we're tracing the children, then we need to start it
2082 with our starter+arguments, which are copied into VALGRINDCLO,
2083 except the --exec= option is changed if present.
2084 */
2085 Int i;
2086 Char *exec;
2087 Char *cp;
2088 Char *optvar;
2089 Int optlen, execlen;
2090
2091 // All these allocated blocks are not free - because we're either
2092 // going to exec, or panic when we fail.
2093
2094 // Create --exec= option: "--exec=<exename>"
2095 exec = VG_(arena_malloc)(VG_AR_CORE,
2096 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2097 vg_assert(NULL != exec);
2098 VG_(sprintf)(exec, "--exec=%s", exename);
2099
2100 // Allocate space for optvar (may overestimate by counting --exec twice,
2101 // no matter)
2102 optlen = 1;
2103 for (i = 0; i < vg_argc; i++)
2104 optlen += VG_(strlen)(vg_argv[i]) + 1;
2105 optlen += VG_(strlen)(exec)+1;
2106 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2107
2108 // Copy all valgrind args except the old --exec (if present)
2109 // VG_CLO_SEP is the separator.
2110 cp = optvar;
2111 for (i = 1; i < vg_argc; i++) {
2112 Char *arg = vg_argv[i];
2113
2114 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2115 // don't copy existing --exec= arg
2116 } else if (VG_(strcmp)(arg, "--") == 0) {
2117 // stop at "--"
2118 break;
2119 } else {
2120 // copy non "--exec" arg
2121 Int len = VG_(strlen)(arg);
2122 VG_(memcpy)(cp, arg, len);
2123 cp += len;
2124 *cp++ = VG_CLO_SEP;
2125 }
2126 }
2127 // Add the new --exec= option
2128 execlen = VG_(strlen)(exec);
2129 VG_(memcpy)(cp, exec, execlen);
2130 cp += execlen;
2131 *cp++ = VG_CLO_SEP;
2132
2133 *cp = '\0';
2134
2135 return optvar;
2136}
2137
2138// Build "/proc/self/fd/<execfd>".
2139Char* VG_(build_child_exename)( void )
2140{
2141 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2142 vg_assert(NULL != exename);
2143 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2144 return exename;
2145}
2146
sewardjde4a1d02002-03-22 01:27:54 +00002147
nethercote71980f02004-01-24 18:18:54 +00002148/*====================================================================*/
2149/*=== File descriptor setup ===*/
2150/*====================================================================*/
2151
2152static void setup_file_descriptors(void)
2153{
2154 struct vki_rlimit rl;
2155
2156 /* Get the current file descriptor limits. */
2157 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2158 rl.rlim_cur = 1024;
2159 rl.rlim_max = 1024;
2160 }
2161
2162 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002163 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2164 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002165 } else {
2166 rl.rlim_cur = rl.rlim_max;
2167 }
2168
2169 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002170 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2171 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002172
2173 /* Update the soft limit. */
2174 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2175
nethercotef6a1d502004-08-09 12:21:57 +00002176 if (vgexecfd != -1)
2177 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002178 if (VG_(clexecfd) != -1)
2179 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2180}
2181
nethercote71980f02004-01-24 18:18:54 +00002182/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002183/*=== Initialise program data/text, etc. ===*/
2184/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002185
sewardjb5f6f512005-03-10 23:59:00 +00002186static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2187 UInt dev, UInt ino, ULong foffset,
2188 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002189{
nethercote71980f02004-01-24 18:18:54 +00002190 /* Only record valgrind mappings for now, without loading any
2191 symbols. This is so we know where the free space is before we
2192 start allocating more memory (note: heap is OK, it's just mmap
2193 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002194 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2195 if (0)
2196 VG_(printf)("init1: %p-%p prot %s\n",
2197 start, start+size, VG_(prot_str)(prot));
2198 VG_(map_file_segment)(start, size, prot,
2199 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2200 dev, ino, foffset, filename);
2201 /* update VG_(valgrind_last) if it looks wrong */
2202 if (start+size > VG_(valgrind_last))
2203 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002204 }
sewardjde4a1d02002-03-22 01:27:54 +00002205}
2206
nethercote71980f02004-01-24 18:18:54 +00002207// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002208Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002209
sewardjb5f6f512005-03-10 23:59:00 +00002210/*
2211 This second pass adds in client mappings, and loads symbol tables
2212 for all interesting mappings. The trouble is that things can
2213 change as we go, because we're calling the Tool to track memory as
2214 we find it.
2215
2216 So for Valgrind mappings, we don't replace any mappings which
2217 aren't still identical (which will include the .so mappings, so we
2218 will load their symtabs)>
2219 */
2220static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2221 UInt dev, UInt ino, ULong foffset,
2222 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002223{
nethercote71980f02004-01-24 18:18:54 +00002224 UInt flags;
2225 Bool is_stack_segment;
2226 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002227
nethercote71980f02004-01-24 18:18:54 +00002228 is_stack_segment
2229 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002230
sewardjb5f6f512005-03-10 23:59:00 +00002231 if (0)
2232 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2233 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002234
nethercote71980f02004-01-24 18:18:54 +00002235 if (is_stack_segment)
2236 flags = SF_STACK | SF_GROWDOWN;
2237 else
2238 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002239
nethercote71980f02004-01-24 18:18:54 +00002240 if (filename != NULL)
2241 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002242
sewardjb5f6f512005-03-10 23:59:00 +00002243#if 0
2244 // This needs to be fixed properly. jrs 20050307
2245 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2246 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002247
sewardjb5f6f512005-03-10 23:59:00 +00002248 /* We have to be a bit careful about inserting new mappings into
2249 the Valgrind part of the address space. We're actively
2250 changing things as we parse these mappings, particularly in
2251 shadow memory, and so we don't want to overwrite those
2252 changes. Therefore, we only insert/update a mapping if it is
2253 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002254
sewardjb5f6f512005-03-10 23:59:00 +00002255 NOTE: we're only talking about the Segment list mapping
2256 metadata; this doesn't actually mmap anything more. */
2257 if (filename || (s && s->addr == start && s->len == size)) {
2258 flags |= SF_VALGRIND;
2259 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2260 } else {
2261 /* assert range is already mapped */
2262 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2263 }
2264 } else
2265#endif
2266 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2267
2268 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2269 VG_TRACK( new_mem_startup, start, size,
2270 !!(prot & VKI_PROT_READ),
2271 !!(prot & VKI_PROT_WRITE),
2272 !!(prot & VKI_PROT_EXEC));
2273 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002274
nethercote71980f02004-01-24 18:18:54 +00002275 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002276 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002277 vg_assert(0 != r_esp);
2278 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002279 if (0) {
2280 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002281 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002282 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2283 r_esp, start+size);
2284 }
nethercote71980f02004-01-24 18:18:54 +00002285 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002286 // what's this for?
2287 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002288 }
sewardjde4a1d02002-03-22 01:27:54 +00002289}
2290
2291
nethercote71980f02004-01-24 18:18:54 +00002292/*====================================================================*/
2293/*=== Sanity check machinery (permanently engaged) ===*/
2294/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002295
2296/* A fast sanity check -- suitable for calling circa once per
2297 millisecond. */
2298
nethercote885dd912004-08-03 23:14:00 +00002299void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002300{
sewardjb5f6f512005-03-10 23:59:00 +00002301 ThreadId tid;
2302
njn37cea302002-09-30 11:24:00 +00002303 VGP_PUSHCC(VgpCoreCheapSanity);
2304
nethercote27fec902004-06-16 21:26:32 +00002305 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002306
2307 /* --- First do all the tests that we can do quickly. ---*/
2308
nethercote297effd2004-08-02 15:07:57 +00002309 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002310
njn25e49d8e72002-09-23 09:36:25 +00002311 /* Check stuff pertaining to the memory check system. */
2312
2313 /* Check that nobody has spuriously claimed that the first or
2314 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002315 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002316 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002317 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002318 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002319 }
njn25e49d8e72002-09-23 09:36:25 +00002320
2321 /* --- Now some more expensive checks. ---*/
2322
2323 /* Once every 25 times, check some more expensive stuff. */
2324 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002325 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002326 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002327
njn37cea302002-09-30 11:24:00 +00002328 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002329 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002330
2331# if 0
2332 { void zzzmemscan(void); zzzmemscan(); }
2333# endif
2334
nethercote297effd2004-08-02 15:07:57 +00002335 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002336 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002337
2338 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002339 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002340 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002341 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002342 }
sewardjb5f6f512005-03-10 23:59:00 +00002343
2344 /* Check that Segments and /proc/self/maps match up */
2345 //vg_assert(VG_(sanity_check_memory)());
2346
2347 /* Look for stack overruns. Visit all threads. */
2348 for(tid = 1; tid < VG_N_THREADS; tid++) {
2349 Int remains;
2350
2351 if (VG_(threads)[tid].status == VgTs_Empty ||
2352 VG_(threads)[tid].status == VgTs_Zombie)
2353 continue;
2354
2355 remains = VGA_(stack_unused)(tid);
2356 if (remains < VKI_PAGE_SIZE)
2357 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2358 tid, remains);
2359 }
2360
njn25e49d8e72002-09-23 09:36:25 +00002361 /*
nethercote297effd2004-08-02 15:07:57 +00002362 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002363 */
njn37cea302002-09-30 11:24:00 +00002364 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002365 }
2366
nethercote27fec902004-06-16 21:26:32 +00002367 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002368 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002369 /* Check sanity of the low-level memory manager. Note that bugs
2370 in the client's code can cause this to fail, so we don't do
2371 this check unless specially asked for. And because it's
2372 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002373 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002374 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002375 }
njn37cea302002-09-30 11:24:00 +00002376 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002377}
nethercote71980f02004-01-24 18:18:54 +00002378
2379
2380/*====================================================================*/
2381/*=== main() ===*/
2382/*====================================================================*/
2383
nethercotec314eba2004-07-15 12:59:41 +00002384/*
2385 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002386 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002387 loads the client executable (and the dynamic linker, if necessary)
2388 into the client part, and calls into Valgrind proper.
2389
2390 The code is careful not to allow spurious mappings to appear in the
2391 wrong parts of the address space. In particular, to make sure
2392 dlopen puts things in the right place, it will pad out the forbidden
2393 chunks of address space so that dlopen is forced to put things where
2394 we want them.
2395
2396 The memory map it creates is:
2397
2398 CLIENT_BASE +-------------------------+
2399 | client address space |
2400 : :
2401 : :
2402 | client stack |
2403 client_end +-------------------------+
2404 | redzone |
2405 shadow_base +-------------------------+
2406 | |
nethercote996901a2004-08-03 13:29:09 +00002407 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002408 | (may be 0 sized) |
2409 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002410 valgrind_base +-------------------------+
2411 | kickstart executable |
2412 | valgrind heap vvvvvvvvv| (barely used)
2413 - -
2414 | valgrind .so files |
2415 | and mappings |
2416 - -
2417 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002418 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002419 : kernel :
2420
2421 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2422 VG_(mmap)(), we need to build the segment skip-list, so we know where
2423 we can put things. However, building that structure requires
2424 allocating memory. So we need to a bootstrapping process. It's done
2425 by making VG_(arena_malloc)() have a special static superblock that's
2426 used for the first 1MB's worth of allocations. This is enough to
2427 build the segment skip-list.
2428*/
2429
nethercote31779c72004-07-30 21:50:15 +00002430static int prmap(char *start, char *end, const char *perm, off_t off,
2431 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002432 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2433 start, end, perm, maj, min, ino);
2434 return True;
2435}
2436
sewardjb5f6f512005-03-10 23:59:00 +00002437int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002438{
2439 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002440 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002441 const char *exec = NULL;
2442 char *preload; /* tool-specific LD_PRELOAD .so */
2443 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002444 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002445 struct exeinfo info;
2446 ToolInfo *toolinfo = NULL;
2447 void *tool_dlhandle;
2448 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002449 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002450 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002451 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002452 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002453
2454 //============================================================
2455 // Nb: startup is complex. Prerequisites are shown at every step.
2456 //
2457 // *** Be very careful when messing with the order ***
2458 //============================================================
2459
nethercotef4928da2004-06-15 10:54:40 +00002460 //============================================================
2461 // Command line argument handling order:
2462 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002463 // (including the tool-specific usage)
2464 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002465 // * Then, if client is missing, abort with error msg
2466 // * Then, if any cmdline args are bad, abort with error msg
2467 //============================================================
2468
fitzhardingeb50068f2004-02-24 23:42:55 +00002469 // Get the current process datasize rlimit, and set it to zero.
2470 // This prevents any internal uses of brk() from having any effect.
2471 // We remember the old value so we can restore it on exec, so that
2472 // child processes will have a reasonable brk value.
2473 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2474 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2475 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002476
2477 // Get the current process stack rlimit.
2478 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2479
nethercote71980f02004-01-24 18:18:54 +00002480 //--------------------------------------------------------------
2481 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002482 // p: none
nethercote71980f02004-01-24 18:18:54 +00002483 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002484 {
2485 void* init_sp = argv - 1;
2486 padfile = scan_auxv(init_sp);
2487 }
nethercote71980f02004-01-24 18:18:54 +00002488 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002489 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002490 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002491 }
2492
2493 //--------------------------------------------------------------
2494 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002495 // p: none
nethercote71980f02004-01-24 18:18:54 +00002496 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002497 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002498 if (cp != NULL)
2499 VG_(libdir) = cp;
2500 }
2501
2502 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002503 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2504 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002505 // p: none
nethercote71980f02004-01-24 18:18:54 +00002506 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002507 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002508 pre_process_cmd_line_options(&need_help, &tool, &exec);
2509
2510 //==============================================================
2511 // Nb: once a tool is specified, the tool.so must be loaded even if
2512 // they specified --help or didn't specify a client program.
2513 //==============================================================
2514
2515 //--------------------------------------------------------------
2516 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002517 // p: set-libdir [for VG_(libdir)]
2518 // p: pre_process_cmd_line_options() [for 'tool']
2519 //--------------------------------------------------------------
2520 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2521
2522 //==============================================================
2523 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002524 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002525 //==============================================================
2526
2527 //--------------------------------------------------------------
2528 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002529 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002530 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002531 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002532
2533 //--------------------------------------------------------------
2534 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002535 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2536 // p: layout_remaining_space [so there's space]
2537 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002538 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002539
2540 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002541 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002542 // p: layout_remaining_space() [everything must be mapped in before now]
2543 // p: load_client() [ditto]
2544 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002545 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2546 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002547
2548 //--------------------------------------------------------------
2549 // Set up client's environment
2550 // p: set-libdir [for VG_(libdir)]
2551 // p: load_tool() [for 'preload']
2552 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002553 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002554
2555 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002556 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002557 // p: load_client() [for 'info']
2558 // p: fix_environment() [for 'env']
2559 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002560 {
2561 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002562
nethercote4ad74312004-10-26 09:59:49 +00002563 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2564 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002565 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002566 }
nethercote71980f02004-01-24 18:18:54 +00002567
2568 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002569 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002570 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002571 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002572
2573 //==============================================================
2574 // Finished setting up operating environment. Now initialise
2575 // Valgrind. (This is where the old VG_(main)() started.)
2576 //==============================================================
2577
2578 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002579 // setup file descriptors
2580 // p: n/a
2581 //--------------------------------------------------------------
2582 setup_file_descriptors();
2583
2584 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002585 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002586 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002587 //--------------------------------------------------------------
2588 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2589
2590 //==============================================================
2591 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2592 //==============================================================
2593
2594 //--------------------------------------------------------------
2595 // Init tool: pre_clo_init, process cmd line, post_clo_init
2596 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2597 // p: load_tool() [for 'tool']
2598 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2599 // p: parse_procselfmaps [so VG segments are setup so tool can
2600 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002601 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002602 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002603 VG_(tool_init_dlsym)(tool_dlhandle);
2604 VG_(sanity_check_needs)();
2605
nethercotef4928da2004-06-15 10:54:40 +00002606 // If --tool and --help/--help-debug was given, now give the core+tool
2607 // help message
nethercotef4928da2004-06-15 10:54:40 +00002608 if (need_help) {
2609 usage(/*--help-debug?*/2 == need_help);
2610 }
nethercotec314eba2004-07-15 12:59:41 +00002611 process_cmd_line_options(client_auxv, tool);
2612
njn26f02512004-11-22 18:33:15 +00002613 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002614
2615 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002616 // Determine CPU architecture and subarchitecture
2617 // p: none
2618 //--------------------------------------------------------------
2619 { Bool ok = VGA_(getArchAndSubArch)(
2620 & VG_(vex_arch), & VG_(vex_subarch) );
2621 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002622 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002623 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002624 VG_(printf)(" Supported CPUs are:\n");
2625 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2626 "AMD Athlon or above)\n");
2627 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002628 VG_(exit)(1);
2629 }
2630 if (VG_(clo_verbosity) > 2) {
2631 VG_(message)(Vg_DebugMsg,
2632 "Host CPU: arch = %s, subarch = %s",
2633 LibVEX_ppVexArch( VG_(vex_arch) ),
2634 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2635 }
2636 }
2637
2638 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002639 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002640 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002641 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002642 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002643 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002644 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002645 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002646 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002647
sewardja4da2f32005-03-02 14:06:08 +00002648#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002649 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002650 // Protect client trampoline page (which is also sysinfo stuff)
2651 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002652 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002653 {
2654 Segment *seg;
2655 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2656 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002657#endif
sewardjb5f6f512005-03-10 23:59:00 +00002658 /* Make sure this segment isn't treated as stack */
2659 seg = VG_(find_segment)(VG_(client_trampoline_code));
2660 if (seg)
2661 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2662 }
2663
nethercotec314eba2004-07-15 12:59:41 +00002664 //==============================================================
2665 // Can use VG_(map)() after segments set up
2666 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002667
2668 //--------------------------------------------------------------
2669 // Allow GDB attach
2670 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2671 //--------------------------------------------------------------
2672 /* Hook to delay things long enough so we can get the pid and
2673 attach GDB in another shell. */
2674 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002675 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2676 /* jrs 20050206: I don't understand why this works on x86. On
2677 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2678 work. */
2679 /* do "jump *$eip" to skip this in gdb (x86) */
2680 //VG_(do_syscall0)(__NR_pause);
2681 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002682 }
2683
sewardjb5d320c2005-03-13 18:57:15 +00002684 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002685 // Search for file descriptors that are inherited from our parent
2686 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2687 //--------------------------------------------------------------
2688 if (VG_(clo_track_fds))
2689 VG_(init_preopened_fds)();
2690
2691 //--------------------------------------------------------------
2692 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002693 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2694 //--------------------------------------------------------------
2695 VG_(scheduler_init)();
2696
2697 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002698 // Initialise the pthread model
2699 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002700 // load_client() [for 'client_eip']
2701 // setup_client_stack() [for 'sp_at_startup']
2702 // setup_scheduler() [for the rest of state 1 stuff]
2703 //--------------------------------------------------------------
2704 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002705
2706 // Tell the tool that we just wrote to the registers.
2707 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2708 sizeof(VexGuestArchState));
2709
2710 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002711 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002712
2713 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002714 // Initialise the pthread model
2715 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002716 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002717 //if (VG_(clo_model_pthreads))
2718 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002719
2720 //--------------------------------------------------------------
2721 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002722 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002723 //--------------------------------------------------------------
2724 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2725 VG_(sigstartup_actions)();
2726
2727 //--------------------------------------------------------------
2728 // Perhaps we're profiling Valgrind?
2729 // p: process_cmd_line_options() [for VG_(clo_profile)]
2730 // p: others?
2731 //
2732 // XXX: this seems to be broken? It always says the tool wasn't built
2733 // for profiling; vg_profile.c's functions don't seem to be overriding
2734 // vg_dummy_profile.c's?
2735 //
2736 // XXX: want this as early as possible. Looking for --profile
2737 // in pre_process_cmd_line_options() could get it earlier.
2738 //--------------------------------------------------------------
2739 if (VG_(clo_profile))
2740 VGP_(init_profiling)();
2741
2742 VGP_PUSHCC(VgpStartup);
2743
2744 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002745 // Read suppression file
2746 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2747 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002748 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002749 VG_(load_suppressions)();
2750
2751 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002752 // Initialise translation table and translation cache
2753 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2754 // aren't identified as part of the client, which would waste
2755 // > 20M of virtual address space.]
2756 //--------------------------------------------------------------
2757 VG_(init_tt_tc)();
2758
2759 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002760 // Read debug info to find glibc entry points to intercept
2761 // p: parse_procselfmaps? [XXX for debug info?]
2762 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2763 //--------------------------------------------------------------
2764 VG_(setup_code_redirect_table)();
2765
2766 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002767 // Verbosity message
2768 // p: end_rdtsc_calibration [so startup message is printed first]
2769 //--------------------------------------------------------------
2770 if (VG_(clo_verbosity) == 1)
2771 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2772 if (VG_(clo_verbosity) > 0)
2773 VG_(message)(Vg_UserMsg, "");
2774
2775 //--------------------------------------------------------------
2776 // Setup pointercheck
2777 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2778 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002779 if (VG_(clo_pointercheck))
2780 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002781
nethercote71980f02004-01-24 18:18:54 +00002782 //--------------------------------------------------------------
2783 // Run!
2784 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002785 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002786
sewardjb5f6f512005-03-10 23:59:00 +00002787 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002788
sewardjb5f6f512005-03-10 23:59:00 +00002789 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002790
sewardjb5f6f512005-03-10 23:59:00 +00002791 abort();
2792}
2793
2794
2795/* Do everything which needs doing when the last thread exits */
2796void VG_(shutdown_actions)(ThreadId tid)
2797{
2798 vg_assert(tid == VG_(master_tid));
2799 vg_assert(VG_(is_running_thread)(tid));
2800
2801 // Wait for all other threads to exit.
2802 VGA_(reap_threads)(tid);
2803
2804 VG_(clo_model_pthreads) = False;
2805
2806 // Clean the client up before the final report
2807 VGA_(final_tidyup)(tid);
2808
2809 // OK, done
2810 VG_(exit_thread)(tid);
2811
2812 /* should be no threads left */
2813 vg_assert(VG_(count_living_threads)() == 0);
2814
2815 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002816 //--------------------------------------------------------------
2817 // Finalisation: cleanup, messages, etc. Order no so important, only
2818 // affects what order the messages come.
2819 //--------------------------------------------------------------
2820 if (VG_(clo_verbosity) > 0)
2821 VG_(message)(Vg_UserMsg, "");
2822
nethercote71980f02004-01-24 18:18:54 +00002823 /* Print out file descriptor summary and stats. */
2824 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002825 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002826
njn95ec8702004-11-22 16:46:13 +00002827 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002828 VG_(show_all_errors)();
2829
sewardjb5f6f512005-03-10 23:59:00 +00002830 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002831
nethercote885dd912004-08-03 23:14:00 +00002832 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002833
2834 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002835 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002836
nethercote71980f02004-01-24 18:18:54 +00002837 if (VG_(clo_profile))
2838 VGP_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002839 if (VG_(clo_profile_flags) > 0)
2840 VG_(show_BB_profile)();
2841
sewardj8b635a42004-11-22 19:01:47 +00002842 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002843 if (0)
2844 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002845
nethercote71980f02004-01-24 18:18:54 +00002846}
2847
sewardjde4a1d02002-03-22 01:27:54 +00002848/*--------------------------------------------------------------------*/
2849/*--- end vg_main.c ---*/
2850/*--------------------------------------------------------------------*/