blob: 31c465b32bd2fc8c0935b66a4cfa0fa2ffe28c7e [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"
njnd01fef72005-03-25 23:35:48 +000035#include "pub_core_execontext.h"
nethercote71980f02004-01-24 18:18:54 +000036
37#include <dirent.h>
38#include <dlfcn.h>
39#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000040#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000041#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000042#include <string.h>
43#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000044#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000046#include <sys/wait.h>
47#include <unistd.h>
48
sewardjb5f6f512005-03-10 23:59:00 +000049#include "memcheck/memcheck.h"
50
thughes74b8de22004-04-22 18:12:31 +000051#ifndef AT_DCACHEBSIZE
52#define AT_DCACHEBSIZE 19
53#endif /* AT_DCACHEBSIZE */
54
55#ifndef AT_ICACHEBSIZE
56#define AT_ICACHEBSIZE 20
57#endif /* AT_ICACHEBSIZE */
58
59#ifndef AT_UCACHEBSIZE
60#define AT_UCACHEBSIZE 21
61#endif /* AT_UCACHEBSIZE */
62
nethercote71980f02004-01-24 18:18:54 +000063#ifndef AT_SYSINFO
64#define AT_SYSINFO 32
65#endif /* AT_SYSINFO */
66
67#ifndef AT_SYSINFO_EHDR
68#define AT_SYSINFO_EHDR 33
69#endif /* AT_SYSINFO_EHDR */
70
71#ifndef AT_SECURE
72#define AT_SECURE 23 /* secure mode boolean */
73#endif /* AT_SECURE */
74
nethercote71980f02004-01-24 18:18:54 +000075/* redzone gap between client address space and shadow */
76#define REDZONE_SIZE (1 * 1024*1024)
77
78/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000079#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000080
nethercotee2097312004-06-27 12:29:56 +000081/* Proportion of client space for its heap (rest is for mmaps + stack) */
82#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000083
njn14319cc2005-03-13 06:26:22 +000084/* Number of file descriptors that Valgrind tries to reserve for
85 it's own use - just a small constant. */
86#define N_RESERVED_FDS (10)
87
88/* Default debugger command. */
89#define CLO_DEFAULT_DBCOMMAND GDB_PATH " -nw %f %p"
90
nethercote71980f02004-01-24 18:18:54 +000091/*====================================================================*/
92/*=== Global entities not referenced from generated code ===*/
93/*====================================================================*/
94
sewardjde4a1d02002-03-22 01:27:54 +000095/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000096 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000097 ------------------------------------------------------------------ */
98
nethercote71980f02004-01-24 18:18:54 +000099/* Client address space, lowest to highest (see top of ume.c) */
100Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(client_end);
102Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +0000103Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +0000104Addr VG_(clstk_base);
105Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +0000106
107Addr VG_(brk_base); /* start of brk */
108Addr VG_(brk_limit); /* current brk */
109
nethercote996901a2004-08-03 13:29:09 +0000110Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000111Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000112
113Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000114
nethercote820bd8c2004-09-07 23:04:49 +0000115// Note that VG_(valgrind_last) names the last byte of the section, whereas
116// the VG_(*_end) vars name the byte one past the end of the section.
117Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000118
nethercote73b526f2004-10-31 18:48:21 +0000119struct vki_rlimit VG_(client_rlimit_data);
120struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000121
fitzhardinge98abfc72003-12-16 02:05:15 +0000122/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000123static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000124
125/* client executable */
126Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000127
128/* Path to library directory */
129const Char *VG_(libdir) = VG_LIBDIR;
130
131/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000132static Int vg_argc;
133static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000134
sewardjb5f6f512005-03-10 23:59:00 +0000135/* The master thread the one which will be responsible for mopping
136 everything up at exit. Normally it is tid 1, since that's the
137 first thread created, but it may be something else after a
138 fork(). */
139ThreadId VG_(master_tid) = VG_INVALID_THREADID;
njn25e49d8e72002-09-23 09:36:25 +0000140
thughesad1c9562004-06-26 11:27:52 +0000141/* Application-visible file descriptor limits */
142Int VG_(fd_soft_limit) = -1;
143Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000144
nethercote4ad74312004-10-26 09:59:49 +0000145/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000146 envp[] as extracted from the client's stack at startup-time. */
147Int VG_(client_argc);
148Char** VG_(client_argv);
149Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000150
njn16de5572004-11-27 14:27:21 +0000151// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000152OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000153
sewardj51ac0872004-12-21 01:20:49 +0000154/* Indicates what arch and subarch we are running on. */
155VexArch VG_(vex_arch) = VexArch_INVALID;
156VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
157
158
sewardjde4a1d02002-03-22 01:27:54 +0000159/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000160 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000161 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000162
nethercote71980f02004-01-24 18:18:54 +0000163/* Counts downwards in VG_(run_innerloop). */
164UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000165
166/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000167ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000168
nethercote71980f02004-01-24 18:18:54 +0000169/* Tell the logging mechanism whether we are logging to a file
170 descriptor or a socket descriptor. */
171Bool VG_(logging_to_filedes) = True;
172
sewardj73cf3bc2002-11-03 03:20:15 +0000173
nethercote71980f02004-01-24 18:18:54 +0000174/*====================================================================*/
175/*=== Counters, for profiling purposes only ===*/
176/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000177
sewardjde4a1d02002-03-22 01:27:54 +0000178/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000179static UInt sanity_fast_count = 0;
180static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000181
nethercote3a42fb82004-08-03 18:08:50 +0000182static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000183{
nethercote3a42fb82004-08-03 18:08:50 +0000184 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000185 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000186 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000187 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000188
nethercote3a42fb82004-08-03 18:08:50 +0000189 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000190 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000191
nethercote71980f02004-01-24 18:18:54 +0000192 VG_(message)(Vg_DebugMsg,
193 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000194 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000195
njn9271cbc2005-03-13 05:38:25 +0000196 VG_(print_ExeContext_stats)();
197
nethercote3a42fb82004-08-03 18:08:50 +0000198 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000199 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000200 VG_(message)(Vg_DebugMsg, "");
201 VG_(message)(Vg_DebugMsg,
202 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000203 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000204 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000205 VG_(message)(Vg_DebugMsg, "");
sewardjb5f6f512005-03-10 23:59:00 +0000206 //VG_(print_shadow_stats)();
nethercote3a42fb82004-08-03 18:08:50 +0000207 }
nethercote71980f02004-01-24 18:18:54 +0000208}
209
210
211/*====================================================================*/
212/*=== Miscellaneous global functions ===*/
213/*====================================================================*/
214
nethercotecf97ffb2004-09-09 13:40:31 +0000215static Int ptrace_setregs(Int pid, ThreadId tid)
216{
sewardj2a99cf62004-11-24 10:44:19 +0000217 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000218}
219
nethercote04d0fbc2004-01-26 16:48:06 +0000220/* Start debugger and get it to attach to this process. Called if the
221 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000222 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000223 meaningfully get the debugger to continue the program, though; to
224 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000225void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000226{
227 Int pid;
228
229 if ((pid = fork()) == 0) {
230 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000231 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000232
233 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000234 Int status;
235 Int res;
236
nethercote71980f02004-01-24 18:18:54 +0000237 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
238 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000239 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000240 kill(pid, SIGSTOP) == 0 &&
241 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000242 Char pidbuf[15];
243 Char file[30];
244 Char buf[100];
245 Char *bufptr;
246 Char *cmdptr;
247
248 VG_(sprintf)(pidbuf, "%d", pid);
249 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
250
251 bufptr = buf;
252 cmdptr = VG_(clo_db_command);
253
254 while (*cmdptr) {
255 switch (*cmdptr) {
256 case '%':
257 switch (*++cmdptr) {
258 case 'f':
259 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
260 bufptr += VG_(strlen)(file);
261 cmdptr++;
262 break;
263 case 'p':
264 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
265 bufptr += VG_(strlen)(pidbuf);
266 cmdptr++;
267 break;
268 default:
269 *bufptr++ = *cmdptr++;
270 break;
271 }
272 break;
273 default:
274 *bufptr++ = *cmdptr++;
275 break;
276 }
277 }
278
279 *bufptr++ = '\0';
280
281 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000282 res = VG_(system)(buf);
283 if (res == 0) {
284 VG_(message)(Vg_UserMsg, "");
285 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000286 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000287 } else {
288 VG_(message)(Vg_UserMsg, "Apparently failed!");
289 VG_(message)(Vg_UserMsg, "");
290 }
291 }
292
nethercote73b526f2004-10-31 18:48:21 +0000293 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000294 VG_(waitpid)(pid, &status, 0);
295 }
296}
297
298
299/* Print some helpful-ish text about unimplemented things, and give
300 up. */
301void VG_(unimplemented) ( Char* msg )
302{
303 VG_(message)(Vg_UserMsg, "");
304 VG_(message)(Vg_UserMsg,
305 "Valgrind detected that your program requires");
306 VG_(message)(Vg_UserMsg,
307 "the following unimplemented functionality:");
308 VG_(message)(Vg_UserMsg, " %s", msg);
309 VG_(message)(Vg_UserMsg,
310 "This may be because the functionality is hard to implement,");
311 VG_(message)(Vg_UserMsg,
312 "or because no reasonable program would behave this way,");
313 VG_(message)(Vg_UserMsg,
314 "or because nobody has yet needed it. In any case, let us know at");
315 VG_(message)(Vg_UserMsg,
316 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
317 VG_(message)(Vg_UserMsg,
318 "");
319 VG_(message)(Vg_UserMsg,
320 "Valgrind has to exit now. Sorry. Bye!");
321 VG_(message)(Vg_UserMsg,
322 "");
323 VG_(pp_sched_status)();
324 VG_(exit)(1);
325}
326
sewardj2a99cf62004-11-24 10:44:19 +0000327/* Get the simulated stack pointer */
njn67516132005-03-22 04:02:43 +0000328Addr VG_(get_SP) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000329{
njncf45fd42004-11-24 16:30:22 +0000330 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000331}
332
njn67516132005-03-22 04:02:43 +0000333Addr VG_(get_IP) ( ThreadId tid )
njn1cb50b22005-03-21 00:01:36 +0000334{
335 return INSTR_PTR( VG_(threads)[tid].arch );
336}
337
njnea4b28c2004-11-30 16:04:58 +0000338
nethercote71980f02004-01-24 18:18:54 +0000339/*====================================================================*/
340/*=== Check we were launched by stage 1 ===*/
341/*====================================================================*/
342
343/* Look for our AUXV table */
sewardjb5f6f512005-03-10 23:59:00 +0000344static int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000345{
nethercoteebf1d862004-11-01 18:22:05 +0000346 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000347 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000348
349 for (; auxv->a_type != AT_NULL; auxv++)
350 switch(auxv->a_type) {
351 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000352 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000353 found |= 1;
354 break;
355
356 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000357 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000358 found |= 2;
359 break;
nethercote7f390022004-10-25 17:18:24 +0000360
361 case AT_PHDR:
362 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
363 break;
nethercote71980f02004-01-24 18:18:54 +0000364 }
365
nethercote361a14e2004-07-26 11:11:56 +0000366 if ( found != (1|2) ) {
367 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000368 exit(127);
369 }
nethercote31779c72004-07-30 21:50:15 +0000370 vg_assert(padfile >= 0);
371 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000372}
373
374
375/*====================================================================*/
376/*=== Address space determination ===*/
377/*====================================================================*/
378
nethercote7f390022004-10-25 17:18:24 +0000379extern char _start[];
380
nethercote31779c72004-07-30 21:50:15 +0000381static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000382{
nethercotea3c3cf22004-11-01 18:38:00 +0000383 Int ires;
384 void* vres;
385 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000386
nethercote7f390022004-10-25 17:18:24 +0000387 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
388 // this is a workable approximation
389 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000390 VG_(valgrind_base) = PGROUNDDN(&_start);
391 }
392
nethercote820bd8c2004-09-07 23:04:49 +0000393 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000394
nethercote31779c72004-07-30 21:50:15 +0000395 // This gives the client the largest possible address space while
396 // taking into account the tool's shadow needs.
397 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000398 CLIENT_SIZE_MULTIPLE);
njn80950732005-03-26 00:18:45 +0000399 VG_(client_base) = VGA_CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000400 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000401 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000402 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000403 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000404
nethercote31779c72004-07-30 21:50:15 +0000405 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000406 VG_(shadow_end) = VG_(valgrind_base);
407 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000408
nethercotee2097312004-06-27 12:29:56 +0000409#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
410
nethercote71980f02004-01-24 18:18:54 +0000411 if (0)
nethercotee2097312004-06-27 12:29:56 +0000412 VG_(printf)(
413 "client_base %8x (%dMB)\n"
414 "client_mapbase %8x (%dMB)\n"
415 "client_end %8x (%dMB)\n"
416 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000417 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000418 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000419 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000420 VG_(client_base), SEGSIZE(client_base, client_mapbase),
421 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
422 VG_(client_end), SEGSIZE(client_end, shadow_base),
423 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000424 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000425 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
426 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000427 );
428
429#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000430
431 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000432 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000433 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000434 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000435
436 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000437 ires = munmap((void*)VG_(client_base), client_size);
438 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000439
440 // Map shadow memory.
441 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000442 if (shadow_size != 0) {
443 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000444 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000445 if ((void*)-1 == vres) {
446 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000447 "valgrind: Could not allocate address space (%p bytes)\n"
448 "valgrind: for shadow memory\n"
449 "valgrind: Possible causes:\n"
450 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
451 "valgrind: needs at least 1.5GB swap space.\n"
452 "valgrind: - Or, your virtual memory size may be limited (check\n"
453 "valgrind: with 'ulimit -v').\n"
454 "valgrind: - Or, your system may use a kernel that provides only a\n"
455 "valgrind: too-small (eg. 2GB) user address space.\n"
456 , (void*)shadow_size
457 );
nethercoted4722622004-08-30 19:36:42 +0000458 exit(1);
459 }
nethercotee567e702004-07-10 17:49:17 +0000460 }
nethercote71980f02004-01-24 18:18:54 +0000461}
462
463/*====================================================================*/
464/*=== Command line setup ===*/
465/*====================================================================*/
466
467/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
468static char* get_file_clo(char* dir)
469{
470# define FLEN 512
471 Int fd, n;
472 struct stat s1;
473 char* f_clo = NULL;
474 char filename[FLEN];
475
476 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
477 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
478 if ( fd > 0 ) {
479 if ( 0 == fstat(fd, &s1) ) {
480 f_clo = malloc(s1.st_size+1);
481 vg_assert(f_clo);
482 n = read(fd, f_clo, s1.st_size);
483 if (n == -1) n = 0;
484 f_clo[n] = '\0';
485 }
486 close(fd);
487 }
488 return f_clo;
489# undef FLEN
490}
491
nethercotee2097312004-06-27 12:29:56 +0000492#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
493
nethercote71980f02004-01-24 18:18:54 +0000494static Int count_args(char* s)
495{
496 Int n = 0;
497 if (s) {
498 char* cp = s;
499 while (True) {
500 // We have alternating sequences: blanks, non-blanks, blanks...
501 // count the non-blanks sequences.
502 while ( ISSPACE(*cp) ) cp++;
503 if ( !*cp ) break;
504 n++;
505 while ( !ISSPACE(*cp) && *cp ) cp++;
506 }
507 }
508 return n;
509}
510
511/* add args out of environment, skipping multiple spaces and -- args */
512static char** copy_args( char* s, char** to )
513{
514 if (s) {
515 char* cp = s;
516 while (True) {
517 // We have alternating sequences: blanks, non-blanks, blanks...
518 // copy the non-blanks sequences, and add terminating '\0'
519 while ( ISSPACE(*cp) ) cp++;
520 if ( !*cp ) break;
521 *to++ = cp;
522 while ( !ISSPACE(*cp) && *cp ) cp++;
523 if ( *cp ) *cp++ = '\0'; // terminate if necessary
524 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
525 }
526 }
527 return to;
528}
529
nethercotee2097312004-06-27 12:29:56 +0000530#undef ISSPACE
531
nethercote71980f02004-01-24 18:18:54 +0000532// Augment command line with arguments from environment and .valgrindrc
533// files.
534static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
535{
nethercotef6a1d502004-08-09 12:21:57 +0000536 int vg_argc0 = *vg_argc_inout;
537 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000538
539 char* env_clo = getenv(VALGRINDOPTS);
540 char* f1_clo = get_file_clo( getenv("HOME") );
541 char* f2_clo = get_file_clo(".");
542
543 /* copy any extra args from file or environment, if present */
544 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
545 /* ' ' separated extra options */
546 char **from;
547 char **to;
thughescaca0022004-09-13 10:20:34 +0000548 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
549
550 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
551
nethercote71980f02004-01-24 18:18:54 +0000552 env_arg_count = count_args(env_clo);
553 f1_arg_count = count_args(f1_clo);
554 f2_arg_count = count_args(f2_clo);
555
556 if (0)
557 printf("extra-argc=%d %d %d\n",
558 env_arg_count, f1_arg_count, f2_arg_count);
559
560 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000561 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000562 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000563 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000564 vg_assert(vg_argv0);
565 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000566
567 /* copy argv[0] */
568 *to++ = *from++;
569
570 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
571 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
572 * to override less local ones. */
573 to = copy_args(f1_clo, to);
574 to = copy_args(env_clo, to);
575 to = copy_args(f2_clo, to);
576
577 /* copy original arguments, stopping at command or -- */
578 while (*from) {
579 if (**from != '-')
580 break;
581 if (VG_STREQ(*from, "--")) {
582 from++; /* skip -- */
583 break;
584 }
585 *to++ = *from++;
586 }
587
588 /* add -- */
589 *to++ = "--";
590
nethercotef6a1d502004-08-09 12:21:57 +0000591 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000592
593 /* copy rest of original command line, then NULL */
594 while (*from) *to++ = *from++;
595 *to = NULL;
596 }
597
nethercotef6a1d502004-08-09 12:21:57 +0000598 *vg_argc_inout = vg_argc0;
599 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000600}
601
nethercotef6a1d502004-08-09 12:21:57 +0000602#define VG_CLO_SEP '\01'
603
nethercote71980f02004-01-24 18:18:54 +0000604static void get_command_line( int argc, char** argv,
605 Int* vg_argc_out, Char*** vg_argv_out,
606 char*** cl_argv_out )
607{
nethercotef6a1d502004-08-09 12:21:57 +0000608 int vg_argc0;
609 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000610 char** cl_argv;
611 char* env_clo = getenv(VALGRINDCLO);
612
613 if (env_clo != NULL && *env_clo != '\0') {
614 char *cp;
615 char **cpp;
616
nethercotef6a1d502004-08-09 12:21:57 +0000617 /* OK, VALGRINDCLO is set, which means we must be a child of another
618 Valgrind process using --trace-children, so we're getting all our
619 arguments from VALGRINDCLO, and the entire command line belongs to
620 the client (including argv[0]) */
621 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000622 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000623 if (*cp == VG_CLO_SEP)
624 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000625
nethercotef6a1d502004-08-09 12:21:57 +0000626 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
627 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000628
nethercotef6a1d502004-08-09 12:21:57 +0000629 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000630
631 *cpp++ = "valgrind"; /* nominal argv[0] */
632 *cpp++ = env_clo;
633
nethercotef6a1d502004-08-09 12:21:57 +0000634 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000635 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000636 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000637 *cp++ = '\0'; /* chop it up in place */
638 *cpp++ = cp;
639 }
640 }
641 *cpp = NULL;
642 cl_argv = argv;
643
644 } else {
sewardjb5f6f512005-03-10 23:59:00 +0000645 Bool noaugment = False;
646
nethercote71980f02004-01-24 18:18:54 +0000647 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000648 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000649
nethercotef6a1d502004-08-09 12:21:57 +0000650 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
sewardjb5f6f512005-03-10 23:59:00 +0000651 Char* arg = argv[vg_argc0];
652 if (arg[0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000653 break;
sewardjb5f6f512005-03-10 23:59:00 +0000654 if (VG_STREQ(arg, "--")) { /* dummy arg */
nethercotef6a1d502004-08-09 12:21:57 +0000655 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000656 break;
657 }
sewardjb5f6f512005-03-10 23:59:00 +0000658 VG_BOOL_CLO("--command-line-only", noaugment)
nethercote71980f02004-01-24 18:18:54 +0000659 }
nethercotef6a1d502004-08-09 12:21:57 +0000660 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000661
662 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000663 Note we don't do this if getting args from VALGRINDCLO, as
sewardjb5f6f512005-03-10 23:59:00 +0000664 those extra args will already be present in VALGRINDCLO.
665 (We also don't do it when --command-line-only=yes.) */
666 if (!noaugment)
667 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000668 }
669
670 if (0) {
671 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000672 for (i = 0; i < vg_argc0; i++)
673 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000674 }
675
nethercotef6a1d502004-08-09 12:21:57 +0000676 *vg_argc_out = vg_argc0;
677 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000678 *cl_argv_out = cl_argv;
679}
680
681
682/*====================================================================*/
683/*=== Environment and stack setup ===*/
684/*====================================================================*/
685
686/* Scan a colon-separated list, and call a function on each element.
687 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000688 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000689 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000690
691 This routine will return True if (*func) returns True and False if
692 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000693*/
thughes4ad52d02004-06-27 17:37:21 +0000694static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000695{
696 char *cp, *entry;
697 int end;
698
699 if (colsep == NULL ||
700 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000701 return False;
nethercote71980f02004-01-24 18:18:54 +0000702
703 entry = cp = colsep;
704
705 do {
706 end = (*cp == '\0');
707
708 if (*cp == ':' || *cp == '\0') {
709 char save = *cp;
710
711 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000712 if ((*func)(entry)) {
713 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000714 return True;
thughes21942d92004-07-12 09:35:37 +0000715 }
nethercote71980f02004-01-24 18:18:54 +0000716 *cp = save;
717 entry = cp+1;
718 }
719 cp++;
720 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000721
722 return False;
723}
724
nethercote71980f02004-01-24 18:18:54 +0000725/* Prepare the client's environment. This is basically a copy of our
726 environment, except:
sewardjb5f6f512005-03-10 23:59:00 +0000727 LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
nethercote71980f02004-01-24 18:18:54 +0000728
sewardjb5f6f512005-03-10 23:59:00 +0000729 If this is missing, then it is added.
nethercote71980f02004-01-24 18:18:54 +0000730
731 Yummy. String hacking in C.
732
733 If this needs to handle any more variables it should be hacked
734 into something table driven.
735 */
736static char **fix_environment(char **origenv, const char *preload)
737{
738 static const char inject_so[] = "vg_inject.so";
nethercote71980f02004-01-24 18:18:54 +0000739 static const char ld_preload[] = "LD_PRELOAD=";
740 static const char valgrind_clo[] = VALGRINDCLO "=";
nethercote71980f02004-01-24 18:18:54 +0000741 static const int ld_preload_len = sizeof(ld_preload)-1;
742 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
743 int ld_preload_done = 0;
nethercote71980f02004-01-24 18:18:54 +0000744 char *inject_path;
745 int inject_path_len;
746 int vgliblen = strlen(VG_(libdir));
747 char **cpp;
748 char **ret;
749 int envc;
750 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
751
752 /* Find the vg_inject.so; also make room for the tool preload
753 library */
754 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
755 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000756 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000757
758 if (preload)
759 snprintf(inject_path, inject_path_len, "%s/%s:%s",
760 VG_(libdir), inject_so, preload);
761 else
762 snprintf(inject_path, inject_path_len, "%s/%s",
763 VG_(libdir), inject_so);
764
765 /* Count the original size of the env */
766 envc = 0; /* trailing NULL */
767 for (cpp = origenv; cpp && *cpp; cpp++)
768 envc++;
769
770 /* Allocate a new space */
sewardjb5f6f512005-03-10 23:59:00 +0000771 ret = malloc(sizeof(char *) * (envc+1+1)); /* 1 new entry + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000772 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000773
774 /* copy it over */
775 for (cpp = ret; *origenv; )
776 *cpp++ = *origenv++;
777 *cpp = NULL;
778
779 vg_assert(envc == (cpp - ret));
780
781 /* Walk over the new environment, mashing as we go */
782 for (cpp = ret; cpp && *cpp; cpp++) {
sewardjb5f6f512005-03-10 23:59:00 +0000783 if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000784 int len = strlen(*cpp) + inject_path_len;
785 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000786 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000787
788 snprintf(cp, len, "%s%s:%s",
789 ld_preload, inject_path, (*cpp)+ld_preload_len);
790
791 *cpp = cp;
792
793 ld_preload_done = 1;
794 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
795 *cpp = "";
796 }
797 }
798
799 /* Add the missing bits */
nethercote71980f02004-01-24 18:18:54 +0000800 if (!ld_preload_done) {
801 int len = ld_preload_len + inject_path_len;
802 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000803 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000804
805 snprintf(cp, len, "%s%s",
806 ld_preload, inject_path);
807
808 ret[envc++] = cp;
809 }
810
sewardjb5f6f512005-03-10 23:59:00 +0000811 free(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000812 ret[envc] = NULL;
813
814 return ret;
815}
816
817extern char **environ; /* our environment */
nethercote71980f02004-01-24 18:18:54 +0000818
819/* Add a string onto the string table, and return its address */
820static char *copy_str(char **tab, const char *str)
821{
822 char *cp = *tab;
823 char *orig = cp;
824
825 while(*str)
826 *cp++ = *str++;
827 *cp++ = '\0';
828
829 if (0)
nethercote545fe672004-11-01 16:52:43 +0000830 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000831
832 *tab = cp;
833
834 return orig;
835}
836
837/*
838 This sets up the client's initial stack, containing the args,
839 environment and aux vector.
840
841 The format of the stack is:
842
843 higher address +-----------------+
844 | Trampoline code |
845 +-----------------+
846 | |
847 : string table :
848 | |
849 +-----------------+
850 | AT_NULL |
851 - -
852 | auxv |
853 +-----------------+
854 | NULL |
855 - -
856 | envp |
857 +-----------------+
858 | NULL |
859 - -
860 | argv |
861 +-----------------+
862 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000863 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000864 | undefined |
865 : :
866 */
nethercotec25c4492004-10-18 11:52:17 +0000867static Addr setup_client_stack(void* init_sp,
868 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000869 const struct exeinfo *info,
870 UInt** client_auxv)
871{
nethercotee567e702004-07-10 17:49:17 +0000872 void* res;
nethercote71980f02004-01-24 18:18:54 +0000873 char **cpp;
874 char *strtab; /* string table */
875 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000876 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000877 struct ume_auxv *auxv;
878 const struct ume_auxv *orig_auxv;
879 const struct ume_auxv *cauxv;
880 unsigned stringsize; /* total size of strings in bytes */
881 unsigned auxsize; /* total size of auxv in bytes */
882 int argc; /* total argc */
883 int envc; /* total number of env vars */
884 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000885 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000886
887 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000888 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000889
890 /* ==================== compute sizes ==================== */
891
892 /* first of all, work out how big the client stack will be */
893 stringsize = 0;
894
895 /* paste on the extra args if the loader needs them (ie, the #!
896 interpreter and its argument) */
897 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000898 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000899 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000900 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000901 }
nethercoted6a56872004-07-26 15:32:47 +0000902 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000903 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000904 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000905 }
906
907 /* now scan the args we're given... */
908 for (cpp = orig_argv; *cpp; cpp++) {
909 argc++;
910 stringsize += strlen(*cpp) + 1;
911 }
912
913 /* ...and the environment */
914 envc = 0;
915 for (cpp = orig_envp; cpp && *cpp; cpp++) {
916 envc++;
917 stringsize += strlen(*cpp) + 1;
918 }
919
920 /* now, how big is the auxv? */
921 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
922 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
923 if (cauxv->a_type == AT_PLATFORM)
924 stringsize += strlen(cauxv->u.a_ptr) + 1;
925 auxsize += sizeof(*cauxv);
926 }
927
928 /* OK, now we know how big the client stack is */
929 stacksize =
sewardj9d9cdea2005-03-23 03:06:30 +0000930 sizeof(Word) + /* argc */
nethercote71980f02004-01-24 18:18:54 +0000931 sizeof(char **)*argc + /* argv */
932 sizeof(char **) + /* terminal NULL */
933 sizeof(char **)*envc + /* envp */
934 sizeof(char **) + /* terminal NULL */
935 auxsize + /* auxv */
sewardj9d9cdea2005-03-23 03:06:30 +0000936 ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000937 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000938
sewardj79048ce2005-02-18 08:28:32 +0000939 if (0) VG_(printf)("stacksize = %d\n", stacksize);
940
nethercotef84f6952004-07-15 14:58:33 +0000941 // decide where stack goes!
942 VG_(clstk_end) = VG_(client_end);
943
nethercote73b526f2004-10-31 18:48:21 +0000944 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000945
nethercote71980f02004-01-24 18:18:54 +0000946 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000947 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000948 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
949
nethercote71980f02004-01-24 18:18:54 +0000950 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000951 stringbase = strtab = (char *)(VG_(client_trampoline_code)
952 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000953
954 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000955
sewardj79048ce2005-02-18 08:28:32 +0000956 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000957 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000958 "clstk_base %p\n"
959 "clstk_end %p\n",
960 stringsize, auxsize, stacksize,
961 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000962
nethercote71980f02004-01-24 18:18:54 +0000963 /* ==================== allocate space ==================== */
964
965 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000966 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +0000967 PROT_READ | PROT_WRITE | PROT_EXEC,
968 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
969 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +0000970
971 /* ==================== copy client stack ==================== */
972
nethercotea3c3cf22004-11-01 18:38:00 +0000973 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +0000974
975 /* --- argc --- */
976 *ptr++ = argc; /* client argc */
977
978 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +0000979 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +0000980 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +0000981 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +0000982 }
nethercoted6a56872004-07-26 15:32:47 +0000983 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +0000984 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +0000985 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +0000986 }
987 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +0000988 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000989 }
990 *ptr++ = 0;
991
992 /* --- envp --- */
993 VG_(client_envp) = (Char **)ptr;
994 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +0000995 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +0000996 *ptr++ = 0;
997
998 /* --- auxv --- */
999 auxv = (struct ume_auxv *)ptr;
1000 *client_auxv = (UInt *)auxv;
1001
1002 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1003 /* copy the entry... */
1004 *auxv = *orig_auxv;
1005
1006 /* ...and fix up the copy */
1007 switch(auxv->a_type) {
1008 case AT_PHDR:
1009 if (info->phdr == 0)
1010 auxv->a_type = AT_IGNORE;
1011 else
1012 auxv->u.a_val = info->phdr;
1013 break;
1014
1015 case AT_PHNUM:
1016 if (info->phdr == 0)
1017 auxv->a_type = AT_IGNORE;
1018 else
1019 auxv->u.a_val = info->phnum;
1020 break;
1021
1022 case AT_BASE:
sewardjb5f6f512005-03-10 23:59:00 +00001023 auxv->u.a_val = info->interp_base;
nethercote71980f02004-01-24 18:18:54 +00001024 break;
1025
1026 case AT_PLATFORM: /* points to a platform description string */
1027 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1028 break;
1029
1030 case AT_ENTRY:
1031 auxv->u.a_val = info->entry;
1032 break;
1033
1034 case AT_IGNORE:
1035 case AT_EXECFD:
1036 case AT_PHENT:
1037 case AT_PAGESZ:
1038 case AT_FLAGS:
1039 case AT_NOTELF:
1040 case AT_UID:
1041 case AT_EUID:
1042 case AT_GID:
1043 case AT_EGID:
1044 case AT_CLKTCK:
1045 case AT_HWCAP:
1046 case AT_FPUCW:
1047 case AT_DCACHEBSIZE:
1048 case AT_ICACHEBSIZE:
1049 case AT_UCACHEBSIZE:
1050 /* All these are pointerless, so we don't need to do anything
1051 about them. */
1052 break;
1053
1054 case AT_SECURE:
1055 /* If this is 1, then it means that this program is running
1056 suid, and therefore the dynamic linker should be careful
1057 about LD_PRELOAD, etc. However, since stage1 (the thing
1058 the kernel actually execve's) should never be SUID, and we
sewardjb5f6f512005-03-10 23:59:00 +00001059 need LD_PRELOAD to work for the client, we
nethercote71980f02004-01-24 18:18:54 +00001060 set AT_SECURE to 0. */
1061 auxv->u.a_val = 0;
1062 break;
1063
1064 case AT_SYSINFO:
1065 /* Leave this unmolested for now, but we'll update it later
1066 when we set up the client trampoline code page */
1067 break;
1068
1069 case AT_SYSINFO_EHDR:
1070 /* Trash this, because we don't reproduce it */
1071 auxv->a_type = AT_IGNORE;
1072 break;
1073
1074 default:
1075 /* stomp out anything we don't know about */
1076 if (0)
nethercote545fe672004-11-01 16:52:43 +00001077 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001078 auxv->a_type = AT_IGNORE;
1079 break;
1080
1081 }
1082 }
1083 *auxv = *orig_auxv;
1084 vg_assert(auxv->a_type == AT_NULL);
1085
njnc6168192004-11-29 13:54:10 +00001086// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1087// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
sewardja4da2f32005-03-02 14:06:08 +00001088#if defined(__i386__) || defined(__amd64__)
nethercotef84f6952004-07-15 14:58:33 +00001089 /* --- trampoline page --- */
1090 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1091 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001092#endif
nethercotef84f6952004-07-15 14:58:33 +00001093
nethercote71980f02004-01-24 18:18:54 +00001094 vg_assert((strtab-stringbase) == stringsize);
1095
nethercote5ee67ca2004-06-22 14:00:09 +00001096 /* We know the initial ESP is pointing at argc/argv */
1097 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001098 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001099
sewardj79048ce2005-02-18 08:28:32 +00001100 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001101 return cl_esp;
1102}
1103
1104/*====================================================================*/
1105/*=== Find executable ===*/
1106/*====================================================================*/
1107
thughes4ad52d02004-06-27 17:37:21 +00001108static const char* executable_name;
1109
1110static Bool match_executable(const char *entry) {
1111 char buf[strlen(entry) + strlen(executable_name) + 2];
1112
1113 /* empty PATH element means . */
1114 if (*entry == '\0')
1115 entry = ".";
1116
1117 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1118
1119 if (access(buf, R_OK|X_OK) == 0) {
1120 executable_name = strdup(buf);
1121 vg_assert(NULL != executable_name);
1122 return True;
1123 }
1124 return False;
1125}
1126
nethercote71980f02004-01-24 18:18:54 +00001127static const char* find_executable(const char* exec)
1128{
1129 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001130 executable_name = exec;
1131 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001132 /* no '/' - we need to search the path */
1133 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001134 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001135 }
thughes4ad52d02004-06-27 17:37:21 +00001136 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001137}
1138
1139
1140/*====================================================================*/
1141/*=== Loading tools ===*/
1142/*====================================================================*/
1143
1144static void list_tools(void)
1145{
1146 DIR *dir = opendir(VG_(libdir));
1147 struct dirent *de;
1148 int first = 1;
1149
1150 if (dir == NULL) {
1151 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001152 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001153 return;
1154 }
1155
nethercotef4928da2004-06-15 10:54:40 +00001156 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001157 int len = strlen(de->d_name);
1158
njn063c5402004-11-22 16:58:05 +00001159 /* look for vgtool_TOOL.so names */
1160 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1161 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001162 VG_STREQ(de->d_name + len - 3, ".so")) {
1163 if (first) {
1164 fprintf(stderr, "Available tools:\n");
1165 first = 0;
1166 }
1167 de->d_name[len-3] = '\0';
1168 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001169 }
1170 }
1171
1172 closedir(dir);
1173
1174 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001175 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1176 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001177}
1178
1179
1180/* Find and load a tool, and check it looks ok. Also looks to see if there's
1181 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1182static void load_tool( const char *toolname, void** handle_out,
1183 ToolInfo** toolinfo_out, char **preloadpath_out )
1184{
1185 Bool ok;
sewardjb5f6f512005-03-10 23:59:00 +00001186 int len = strlen(VG_(libdir)) + strlen(toolname) + 16;
nethercote71980f02004-01-24 18:18:54 +00001187 char buf[len];
1188 void* handle;
1189 ToolInfo* toolinfo;
1190 char* preloadpath = NULL;
1191 Int* vg_malloc_redzonep;
1192
1193 // XXX: allowing full paths for --tool option -- does it make sense?
1194 // Doesn't allow for vgpreload_<tool>.so.
1195
1196 if (strchr(toolname, '/') != 0) {
1197 /* toolname contains '/', and so must be a pathname */
1198 handle = dlopen(toolname, RTLD_NOW);
1199 } else {
1200 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001201 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001202 handle = dlopen(buf, RTLD_NOW);
1203
1204 if (handle != NULL) {
1205 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1206 if (access(buf, R_OK) == 0) {
1207 preloadpath = strdup(buf);
1208 vg_assert(NULL != preloadpath);
1209 }
1210 }
1211 }
1212
1213 ok = (NULL != handle);
1214 if (!ok) {
1215 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1216 goto bad_load;
1217 }
1218
njn26f02512004-11-22 18:33:15 +00001219 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001220 ok = (NULL != toolinfo);
1221 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001222 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001223 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1224 goto bad_load;
1225 }
1226
1227 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1228 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001229 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001230 if (!ok) {
1231 fprintf(stderr, "Error:\n"
1232 " Tool and core interface versions do not match.\n"
1233 " Interface version used by core is: %d.%d (size %d)\n"
1234 " Interface version used by tool is: %d.%d (size %d)\n"
1235 " The major version numbers must match.\n",
1236 VG_CORE_INTERFACE_MAJOR_VERSION,
1237 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001238 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001239 toolinfo->interface_major_version,
1240 toolinfo->interface_minor_version,
1241 toolinfo->sizeof_ToolInfo);
1242 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1243 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001244 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001245 else
nethercote996901a2004-08-03 13:29:09 +00001246 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001247 goto bad_load;
1248 }
1249
1250 // Set redzone size for V's allocator
1251 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1252 if ( NULL != vg_malloc_redzonep ) {
1253 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1254 }
1255
1256 vg_assert(NULL != handle && NULL != toolinfo);
1257 *handle_out = handle;
1258 *toolinfo_out = toolinfo;
1259 *preloadpath_out = preloadpath;
1260 return;
1261
1262
1263 bad_load:
1264 if (handle != NULL)
1265 dlclose(handle);
1266
nethercotef4928da2004-06-15 10:54:40 +00001267 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001268 list_tools();
1269 exit(127);
1270}
1271
nethercotef4928da2004-06-15 10:54:40 +00001272
1273/*====================================================================*/
1274/*=== Command line errors ===*/
1275/*====================================================================*/
1276
1277static void abort_msg ( void )
1278{
nethercotef8548672004-06-21 12:42:35 +00001279 VG_(clo_log_to) = VgLogTo_Fd;
1280 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001281}
1282
1283void VG_(bad_option) ( Char* opt )
1284{
1285 abort_msg();
1286 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1287 VG_(printf)("valgrind: Use --help for more information.\n");
1288 VG_(exit)(1);
1289}
1290
nethercotef4928da2004-06-15 10:54:40 +00001291static void missing_prog ( void )
1292{
1293 abort_msg();
1294 VG_(printf)("valgrind: no program specified\n");
1295 VG_(printf)("valgrind: Use --help for more information.\n");
1296 VG_(exit)(1);
1297}
1298
1299static void config_error ( Char* msg )
1300{
1301 abort_msg();
1302 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1303 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1304 VG_(exit)(1);
1305}
1306
1307
nethercote71980f02004-01-24 18:18:54 +00001308/*====================================================================*/
1309/*=== Loading the client ===*/
1310/*====================================================================*/
1311
nethercotef4928da2004-06-15 10:54:40 +00001312static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001313 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1314{
1315 // If they didn't specify an executable with --exec, and didn't specify
1316 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001317 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001318 if (cl_argv[0] == NULL ||
1319 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1320 {
nethercotef4928da2004-06-15 10:54:40 +00001321 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001322 }
1323 }
1324
1325 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001326 info->exe_base = VG_(client_base);
1327 info->exe_end = VG_(client_end);
1328 info->argv = cl_argv;
1329
nethercotef4928da2004-06-15 10:54:40 +00001330 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001331 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001332 // Totally zero 'info' before continuing.
1333 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001334 } else {
1335 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001336 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001337 ret = do_exec(exec, info);
1338 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001339 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1340 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001341 exit(127);
1342 }
1343 }
1344
1345 /* Copy necessary bits of 'info' that were filled in */
1346 *client_eip = info->init_eip;
1347 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1348}
1349
nethercote969ecf12004-10-13 17:29:01 +00001350/*====================================================================*/
1351/*=== Address space unpadding ===*/
1352/*====================================================================*/
1353
1354typedef struct {
1355 char* killpad_start;
1356 char* killpad_end;
1357 struct stat* killpad_padstat;
1358} killpad_extra;
1359
1360static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1361 int maj, int min, int ino, void* ex)
1362{
1363 killpad_extra* extra = ex;
1364 void *b, *e;
1365 int res;
1366
1367 vg_assert(NULL != extra->killpad_padstat);
1368
1369 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1370 extra->killpad_padstat->st_ino != ino)
1371 return 1;
1372
1373 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1374 return 1;
1375
1376 if (segstart <= extra->killpad_start)
1377 b = extra->killpad_start;
1378 else
1379 b = segstart;
1380
1381 if (segend >= extra->killpad_end)
1382 e = extra->killpad_end;
1383 else
1384 e = segend;
1385
1386 res = munmap(b, (char *)e-(char *)b);
1387 vg_assert(0 == res);
1388
1389 return 1;
1390}
1391
1392// Remove padding of 'padfile' from a range of address space.
sewardj2c5ffbe2005-03-12 13:32:06 +00001393static void as_unpad(void *start, void *end, int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001394{
1395 static struct stat padstat;
1396 killpad_extra extra;
1397 int res;
1398
sewardjb5f6f512005-03-10 23:59:00 +00001399 vg_assert(padfile >= 0);
nethercote969ecf12004-10-13 17:29:01 +00001400
1401 res = fstat(padfile, &padstat);
1402 vg_assert(0 == res);
1403 extra.killpad_padstat = &padstat;
1404 extra.killpad_start = start;
1405 extra.killpad_end = end;
1406 foreach_map(killpad, &extra);
1407}
1408
sewardj2c5ffbe2005-03-12 13:32:06 +00001409static void as_closepadfile(int padfile)
nethercote969ecf12004-10-13 17:29:01 +00001410{
1411 int res = close(padfile);
1412 vg_assert(0 == res);
1413}
1414
nethercote71980f02004-01-24 18:18:54 +00001415
1416/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001417/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001418/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001419
njn25e49d8e72002-09-23 09:36:25 +00001420/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001421VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001422Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001423Bool VG_(clo_db_attach) = False;
njn14319cc2005-03-13 06:26:22 +00001424Char* VG_(clo_db_command) = CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001425Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001426Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001427Int VG_(clo_verbosity) = 1;
1428Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001429Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001430
nethercotef1e5e152004-09-01 23:58:16 +00001431/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001432 fd is initially stdout, for --help, but gets moved to stderr by default
1433 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001434VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001435Int VG_(clo_log_fd) = 1;
1436Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001437
thughes6233a382004-08-21 11:10:44 +00001438Bool VG_(clo_time_stamp) = False;
1439
sewardj6024b212003-07-13 10:54:33 +00001440Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001441Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001442Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001443Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001444UChar VG_(clo_trace_flags) = 0; // 00000000b
1445UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001446Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001447Bool VG_(clo_trace_syscalls) = False;
1448Bool VG_(clo_trace_signals) = False;
1449Bool VG_(clo_trace_symtab) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001450Bool VG_(clo_trace_redir) = False;
njn25e49d8e72002-09-23 09:36:25 +00001451Bool VG_(clo_trace_sched) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001452Bool VG_(clo_trace_pthreads) = False;
njn25e49d8e72002-09-23 09:36:25 +00001453Int VG_(clo_dump_error) = 0;
sewardjb5f6f512005-03-10 23:59:00 +00001454Int VG_(clo_backtrace_size) = 12;
njn25e49d8e72002-09-23 09:36:25 +00001455Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001456Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001457Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001458Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001459Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001460Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001461Bool VG_(clo_branchpred) = False;
sewardjb5f6f512005-03-10 23:59:00 +00001462Bool VG_(clo_model_pthreads) = False;
sewardjb1131a82005-03-19 15:12:21 +00001463Bool VG_(clo_show_emwarns) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001464
jsgf855d93d2003-10-13 22:26:55 +00001465static Bool VG_(clo_wait_for_gdb) = False;
1466
sewardjde4a1d02002-03-22 01:27:54 +00001467
sewardj2c5ffbe2005-03-12 13:32:06 +00001468static void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001469{
njn25e49d8e72002-09-23 09:36:25 +00001470 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001471"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001472"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001473" common user options for all Valgrind tools, with defaults in [ ]:\n"
sewardjb5f6f512005-03-10 23:59:00 +00001474" --tool=<name> use the Valgrind tool named <name> [memcheck]\n"
nethercotea76368b2004-06-16 11:56:29 +00001475" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001476" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001477" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001478" -q --quiet run silently; only print error msgs\n"
1479" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001480" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001481" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001482" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001483"\n"
1484" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001485" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
sewardjb5f6f512005-03-10 23:59:00 +00001486" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls,ioctl-mmap [none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001487" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001488" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
sewardjb1131a82005-03-19 15:12:21 +00001489" --show-emwarns=no|yes show warnings about emulation limits? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001490"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001491" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001492" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1493" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001494" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001495" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001496" --demangle=no|yes automatically demangle C++ names? [yes]\n"
njncc6cc142005-03-12 20:59:29 +00001497" --num-callers=<number> show <num> callers in stack traces [12]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001498" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1499" --show-below-main=no|yes continue stack traces below main() [no]\n"
1500" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001501" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001502" --db-attach=no|yes start debugger when errors detected? [no]\n"
1503" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1504" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001505"\n";
njn7cf0bd32002-06-08 13:36:03 +00001506
njn25e49d8e72002-09-23 09:36:25 +00001507 Char* usage2 =
1508"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001509" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001510" --sanity-level=<number> level of sanity checking to do [1]\n"
1511" --single-step=no|yes translate each instr separately? [no]\n"
1512" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001513" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001514" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001515" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1516" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001517" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001518" --trace-syscalls=no|yes show all system calls? [no]\n"
1519" --trace-signals=no|yes show signal handling details? [no]\n"
1520" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001521" --trace-sched=no|yes show thread scheduler details? [no]\n"
jsgf855d93d2003-10-13 22:26:55 +00001522" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
sewardjb5f6f512005-03-10 23:59:00 +00001523#if 0
1524" --model-pthreads=yes|no model the pthreads library [no]\n"
1525#endif
1526" --command-line-only=no|yes only use command line options [no]\n"
njn613812e2005-03-11 04:57:30 +00001527"\n"
1528" --vex-iropt-verbosity 0 .. 9 [0]\n"
1529" --vex-iropt-level 0 .. 2 [2]\n"
1530" --vex-iropt-precise-memory-exns [no]\n"
sewardj8b635a42004-11-22 19:01:47 +00001531" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1532" --vex-guest-max-insns 1 .. 100 [50]\n"
1533" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1534"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001535" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001536" 1000 0000 show conversion into IR\n"
1537" 0100 0000 show after initial opt\n"
1538" 0010 0000 show after instrumentation\n"
1539" 0001 0000 show after second opt\n"
1540" 0000 1000 show after tree building\n"
1541" 0000 0100 show selecting insns\n"
1542" 0000 0010 show after reg-alloc\n"
1543" 0000 0001 show final assembly\n"
1544"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001545" debugging options for Valgrind tools that report errors\n"
1546" --dump-error=<number> show translation for basic block associated\n"
1547" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001548"\n";
njn3e884182003-04-15 13:03:23 +00001549
1550 Char* usage3 =
1551"\n"
nethercote71980f02004-01-24 18:18:54 +00001552" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001553"\n"
njn53612422005-03-12 16:22:54 +00001554" Valgrind is Copyright (C) 2000-2005 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001555" and licensed under the GNU General Public License, version 2.\n"
1556" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001557"\n"
nethercote137bc552003-11-14 17:47:54 +00001558" Tools are copyright and licensed by their authors. See each\n"
1559" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001560"\n";
njn7cf0bd32002-06-08 13:36:03 +00001561
fitzhardinge98abfc72003-12-16 02:05:15 +00001562 VG_(printf)(usage1);
1563 if (VG_(details).name) {
1564 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001565 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001566 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001567 else
1568 VG_(printf)(" (none)\n");
1569 }
nethercote6c999f22004-01-31 22:55:15 +00001570 if (debug_help) {
1571 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001572
nethercote6c999f22004-01-31 22:55:15 +00001573 if (VG_(details).name) {
1574 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1575
1576 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001577 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001578 else
1579 VG_(printf)(" (none)\n");
1580 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001581 }
nethercote421281e2003-11-20 16:20:55 +00001582 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001583 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001584}
sewardjde4a1d02002-03-22 01:27:54 +00001585
nethercote71980f02004-01-24 18:18:54 +00001586static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001587 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001588{
nethercote71980f02004-01-24 18:18:54 +00001589 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001590
sewardj8b635a42004-11-22 19:01:47 +00001591 LibVEX_default_VexControl(& VG_(clo_vex_control));
1592
nethercote71980f02004-01-24 18:18:54 +00001593 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001594 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001595
nethercotef6a1d502004-08-09 12:21:57 +00001596 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001597 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001598 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001599
nethercotef6a1d502004-08-09 12:21:57 +00001600 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1601 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001602 *need_help = 1;
1603
nethercotef6a1d502004-08-09 12:21:57 +00001604 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001605 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001606
nethercotef6c99d72004-11-09 14:35:43 +00001607 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001608 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001609
nethercotef6a1d502004-08-09 12:21:57 +00001610 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1611 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001612 }
1613 }
nethercote71980f02004-01-24 18:18:54 +00001614}
1615
nethercote5ee67ca2004-06-22 14:00:09 +00001616static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001617{
nethercotef8548672004-06-21 12:42:35 +00001618 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001619 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001620
nethercotee1730692003-11-20 10:38:07 +00001621 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001622 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001623
sewardj19d81412002-06-03 01:10:40 +00001624 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001625 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001626 config_error("Please use absolute paths in "
1627 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001628
njnc6168192004-11-29 13:54:10 +00001629// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001630#ifdef __x86__
1631 {
sewardjb5f6f512005-03-10 23:59:00 +00001632 UInt* auxp;
njnca0518d2004-11-26 19:34:36 +00001633 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1634 switch(auxp[0]) {
1635 case AT_SYSINFO:
1636 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1637 break;
1638 }
1639 }
1640 }
1641#endif
sewardjde4a1d02002-03-22 01:27:54 +00001642
nethercotef6a1d502004-08-09 12:21:57 +00001643 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001644
nethercotef6a1d502004-08-09 12:21:57 +00001645 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001646 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001647
thughes3bfd5a02004-07-18 08:05:44 +00001648 /* Look for a colon in the switch name */
1649 while (*colon && *colon != ':' && *colon != '=')
1650 colon++;
nethercote71980f02004-01-24 18:18:54 +00001651
1652 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001653 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001654 if (VG_CLO_STREQN(2, arg, "--") &&
1655 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1656 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1657 {
1658 // prefix matches, convert "--toolname:foo" to "--foo"
1659 if (0)
1660 VG_(printf)("tool-specific arg: %s\n", arg);
njn8c0b3bb2005-03-12 21:20:39 +00001661 arg = strdup(arg + toolname_len + 1);
nethercote71980f02004-01-24 18:18:54 +00001662 arg[0] = '-';
1663 arg[1] = '-';
1664
1665 } else {
1666 // prefix doesn't match, skip to next arg
1667 continue;
1668 }
1669 }
1670
fitzhardinge98abfc72003-12-16 02:05:15 +00001671 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001672 if (VG_CLO_STREQN(7, arg, "--tool="))
njn8c0b3bb2005-03-12 21:20:39 +00001673 goto skip_arg;
nethercote71980f02004-01-24 18:18:54 +00001674 if (VG_CLO_STREQN(7, arg, "--exec="))
njn8c0b3bb2005-03-12 21:20:39 +00001675 goto skip_arg;
sewardjb5f6f512005-03-10 23:59:00 +00001676 if (VG_CLO_STREQN(20, arg, "--command-line-only="))
njn8c0b3bb2005-03-12 21:20:39 +00001677 goto skip_arg;
fitzhardinge98abfc72003-12-16 02:05:15 +00001678
nethercote71980f02004-01-24 18:18:54 +00001679 if ( VG_CLO_STREQ(arg, "--"))
njn8c0b3bb2005-03-12 21:20:39 +00001680 goto skip_arg;
nethercote27fec902004-06-16 21:26:32 +00001681
nethercote71980f02004-01-24 18:18:54 +00001682 else if (VG_CLO_STREQ(arg, "-v") ||
1683 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001684 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001685
nethercote71980f02004-01-24 18:18:54 +00001686 else if (VG_CLO_STREQ(arg, "-q") ||
1687 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001688 VG_(clo_verbosity)--;
1689
nethercote27fec902004-06-16 21:26:32 +00001690 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001691 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1692 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1693 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001694 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001695 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
sewardjb1131a82005-03-19 15:12:21 +00001696 else VG_BOOL_CLO("--show-emwarns", VG_(clo_show_emwarns))
nethercote27fec902004-06-16 21:26:32 +00001697 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1698 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1699 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001700 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001701 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1702 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1703 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1704 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1705 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
sewardjb5f6f512005-03-10 23:59:00 +00001706 else VG_BOOL_CLO("--trace-redir", VG_(clo_trace_redir))
nethercote27fec902004-06-16 21:26:32 +00001707 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
sewardjb5f6f512005-03-10 23:59:00 +00001708 else VG_BOOL_CLO("--trace-pthreads", VG_(clo_trace_pthreads))
nethercote27fec902004-06-16 21:26:32 +00001709 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardjb5f6f512005-03-10 23:59:00 +00001710 else VG_BOOL_CLO("--model-pthreads", VG_(clo_model_pthreads))
sewardj72f98ff2002-06-13 17:23:38 +00001711
nethercote27fec902004-06-16 21:26:32 +00001712 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1713 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001714
nethercote27fec902004-06-16 21:26:32 +00001715 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1716 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1717 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote27fec902004-06-16 21:26:32 +00001718 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1719 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001720
sewardj8b635a42004-11-22 19:01:47 +00001721 else VG_BNUM_CLO("--vex-iropt-verbosity",
1722 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1723 else VG_BNUM_CLO("--vex-iropt-level",
1724 VG_(clo_vex_control).iropt_level, 0, 2)
1725 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1726 VG_(clo_vex_control).iropt_precise_memory_exns)
1727 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1728 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1729 else VG_BNUM_CLO("--vex-guest-max-insns",
1730 VG_(clo_vex_control).guest_max_insns, 1, 100)
1731 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1732 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1733
nethercotef8548672004-06-21 12:42:35 +00001734 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001735 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001736 VG_(clo_log_to) = VgLogTo_Fd;
1737 VG_(clo_log_name) = NULL;
1738 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1739 }
1740 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1741 VG_(clo_log_to) = VgLogTo_Fd;
1742 VG_(clo_log_name) = NULL;
1743 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001744 }
1745
nethercotef8548672004-06-21 12:42:35 +00001746 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001747 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001748 VG_(clo_log_to) = VgLogTo_File;
1749 VG_(clo_log_name) = &arg[10];
1750 }
1751 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1752 VG_(clo_log_to) = VgLogTo_File;
1753 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001754 }
sewardj603d4102005-01-11 14:01:02 +00001755 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1756 VG_(clo_log_to) = VgLogTo_FileExactly;
1757 VG_(clo_log_name) = &arg[19];
1758 }
sewardjde4a1d02002-03-22 01:27:54 +00001759
nethercotef8548672004-06-21 12:42:35 +00001760 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001761 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001762 VG_(clo_log_to) = VgLogTo_Socket;
1763 VG_(clo_log_name) = &arg[12];
1764 }
1765 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1766 VG_(clo_log_to) = VgLogTo_Socket;
1767 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001768 }
1769
nethercote71980f02004-01-24 18:18:54 +00001770 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001771 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001772 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001773 VG_(message)(Vg_UserMsg,
1774 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001775 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001776 }
nethercote71980f02004-01-24 18:18:54 +00001777 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001778 VG_(clo_n_suppressions)++;
1779 }
sewardjde4a1d02002-03-22 01:27:54 +00001780
sewardjfa8ec112005-01-19 11:55:34 +00001781 /* "stuvwxyz" --> stuvwxyz (binary) */
1782 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1783 Int j;
1784 char* opt = & arg[14];
1785
1786 if (8 != VG_(strlen)(opt)) {
1787 VG_(message)(Vg_UserMsg,
1788 "--trace-flags argument must have 8 digits");
1789 VG_(bad_option)(arg);
1790 }
1791 for (j = 0; j < 8; j++) {
1792 if ('0' == opt[j]) { /* do nothing */ }
1793 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1794 else {
1795 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1796 "contain 0s and 1s");
1797 VG_(bad_option)(arg);
1798 }
1799 }
1800 }
1801
1802 /* "stuvwxyz" --> stuvwxyz (binary) */
1803 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001804 Int j;
nethercote71980f02004-01-24 18:18:54 +00001805 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001806
sewardj2a99cf62004-11-24 10:44:19 +00001807 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001808 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001809 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001810 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001811 }
sewardj8b635a42004-11-22 19:01:47 +00001812 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001813 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001814 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001815 else {
sewardjfa8ec112005-01-19 11:55:34 +00001816 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001817 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001818 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001819 }
1820 }
1821 }
sewardjde4a1d02002-03-22 01:27:54 +00001822
sewardjc771b292004-11-30 18:55:21 +00001823 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1824
sewardjd153fae2005-01-10 17:24:47 +00001825 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1826 VG_(clo_gen_suppressions) = 0;
1827 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1828 VG_(clo_gen_suppressions) = 1;
1829 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1830 VG_(clo_gen_suppressions) = 2;
1831
nethercote71980f02004-01-24 18:18:54 +00001832 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001833 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001834 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001835 }
njn8c0b3bb2005-03-12 21:20:39 +00001836 skip_arg:
1837 if (arg != vg_argv[i])
1838 free(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001839 }
1840
sewardj998d40d2004-12-06 14:24:52 +00001841 /* Make VEX control parameters sane */
1842
1843 if (VG_(clo_vex_control).guest_chase_thresh
1844 >= VG_(clo_vex_control).guest_max_insns)
1845 VG_(clo_vex_control).guest_chase_thresh
1846 = VG_(clo_vex_control).guest_max_insns - 1;
1847
1848 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1849 VG_(clo_vex_control).guest_chase_thresh = 0;
1850
1851 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001852
njnf9ebf672003-05-12 21:41:30 +00001853 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001854 VG_(clo_verbosity) = 0;
1855
nethercote04d0fbc2004-01-26 16:48:06 +00001856 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001857 VG_(message)(Vg_UserMsg, "");
1858 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001859 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001860 VG_(message)(Vg_UserMsg,
1861 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001862 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001863 }
1864
nethercotef8548672004-06-21 12:42:35 +00001865 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001866 should be connected to whatever sink has been selected, and we
1867 indiscriminately chuck stuff into it without worrying what the
1868 nature of it is. Oh the wonder of Unix streams. */
1869
nethercotee1730692003-11-20 10:38:07 +00001870 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001871 the terminal any problems to do with processing command line
1872 opts. */
nethercotef8548672004-06-21 12:42:35 +00001873 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001874 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001875
1876 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001877
sewardj4cf05692002-10-27 20:28:29 +00001878 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001879 vg_assert(VG_(clo_log_name) == NULL);
1880 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001881 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001882
sewardj4cf05692002-10-27 20:28:29 +00001883 case VgLogTo_File: {
1884 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001885 Int seq = 0;
1886 Int pid = VG_(getpid)();
1887
nethercotef8548672004-06-21 12:42:35 +00001888 vg_assert(VG_(clo_log_name) != NULL);
1889 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001890
nethercote71980f02004-01-24 18:18:54 +00001891 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001892 if (seq == 0)
1893 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001894 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001895 else
1896 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001897 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001898 seq++;
1899
nethercotef8548672004-06-21 12:42:35 +00001900 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001901 = VG_(open)(logfilename,
1902 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1903 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001904 if (eventually_log_fd >= 0) {
1905 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001906 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001907 } else {
nethercotef8548672004-06-21 12:42:35 +00001908 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001909 VG_(message)(Vg_UserMsg,
1910 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001911 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001912 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001913 "--log-file=<file> (didn't work out for some reason.)");
1914 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001915 }
1916 }
1917 }
sewardj603d4102005-01-11 14:01:02 +00001918 break; /* switch (VG_(clo_log_to)) */
1919 }
1920
1921 case VgLogTo_FileExactly: {
1922 Char logfilename[1000];
1923
1924 vg_assert(VG_(clo_log_name) != NULL);
1925 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1926 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1927
1928 eventually_log_fd
1929 = VG_(open)(logfilename,
1930 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1931 VKI_S_IRUSR|VKI_S_IWUSR);
1932 if (eventually_log_fd >= 0) {
1933 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1934 }
1935 else if (eventually_log_fd != -VKI_EEXIST) {
1936 VG_(message)(Vg_UserMsg,
1937 "Can't create/open log file `%s'; giving up!",
1938 VG_(clo_log_name));
1939 VG_(bad_option)(
1940 "--log-file-exactly=<file> (didn't work out for some reason.)");
1941 /*NOTREACHED*/
1942 }
1943 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00001944 }
1945
1946 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00001947 vg_assert(VG_(clo_log_name) != NULL);
1948 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1949 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
1950 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00001951 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001952 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00001953 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001954 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00001955 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00001956 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00001957 }
nethercotef8548672004-06-21 12:42:35 +00001958 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00001959 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00001960 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00001961 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00001962 VG_(message)(Vg_UserMsg,
1963 "Log messages will sent to stderr instead." );
1964 VG_(message)(Vg_UserMsg,
1965 "" );
1966 /* We don't change anything here. */
1967 } else {
nethercotef8548672004-06-21 12:42:35 +00001968 vg_assert(eventually_log_fd > 0);
1969 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00001970 VG_(logging_to_filedes) = False;
1971 }
sewardj73cf3bc2002-11-03 03:20:15 +00001972 break;
1973 }
1974
sewardj4cf05692002-10-27 20:28:29 +00001975 }
1976
nethercotef8548672004-06-21 12:42:35 +00001977 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00001978 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00001979 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00001980 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
1981 else {
nethercotef8548672004-06-21 12:42:35 +00001982 VG_(clo_log_fd) = eventually_log_fd;
1983 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00001984 }
1985
sewardj4cf05692002-10-27 20:28:29 +00001986 /* Ok, the logging sink is running now. Print a suitable preamble.
1987 If logging to file or a socket, write details of parent PID and
1988 command line args, to help people trying to interpret the
1989 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00001990
sewardj83adf412002-05-01 01:25:45 +00001991 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00001992 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00001993 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00001994 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00001995 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00001996 NULL == VG_(details).version
1997 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00001998 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00001999 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002000
njnd04b7c62002-10-03 14:05:52 +00002001 /* Core details */
2002 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00002003 "Using LibVEX rev %s, a library for dynamic binary translation.",
2004 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00002005 VG_(message)(Vg_UserMsg,
2006 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2007 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002008 "Using valgrind-%s, a dynamic binary instrumentation framework.",
njn92a778c2005-03-12 16:54:07 +00002009 VERSION);
sewardjde4a1d02002-03-22 01:27:54 +00002010 VG_(message)(Vg_UserMsg,
njn53612422005-03-12 16:22:54 +00002011 "Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002012 }
2013
nethercotec1e395d2003-11-10 13:26:49 +00002014 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002015 VG_(message)(Vg_UserMsg, "");
2016 VG_(message)(Vg_UserMsg,
2017 "My PID = %d, parent PID = %d. Prog and args are:",
2018 VG_(getpid)(), VG_(getppid)() );
2019 for (i = 0; i < VG_(client_argc); i++)
2020 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2021 }
2022
sewardjde4a1d02002-03-22 01:27:54 +00002023 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002024 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002025 if (VG_(clo_log_to) != VgLogTo_Fd)
njn1fd5eb22005-03-13 05:43:23 +00002026 VG_(message)(Vg_DebugMsg, "");
2027 VG_(message)(Vg_DebugMsg, "Valgrind library directory: %s", VG_(libdir));
2028 VG_(message)(Vg_DebugMsg, "Command line");
njn86dc2bc2003-09-09 07:26:21 +00002029 for (i = 0; i < VG_(client_argc); i++)
njn1fd5eb22005-03-13 05:43:23 +00002030 VG_(message)(Vg_DebugMsg, " %s", VG_(client_argv)[i]);
njn86dc2bc2003-09-09 07:26:21 +00002031
njn1fd5eb22005-03-13 05:43:23 +00002032 VG_(message)(Vg_DebugMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002033 for (i = 1; i < vg_argc; i++) {
njn1fd5eb22005-03-13 05:43:23 +00002034 VG_(message)(Vg_DebugMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002035 }
nethercotea70f7352004-04-18 12:08:46 +00002036
njn1fd5eb22005-03-13 05:43:23 +00002037 VG_(message)(Vg_DebugMsg, "Contents of /proc/version:");
nethercotea70f7352004-04-18 12:08:46 +00002038 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2039 if (fd < 0) {
njn1fd5eb22005-03-13 05:43:23 +00002040 VG_(message)(Vg_DebugMsg, " can't open /proc/version");
nethercotea70f7352004-04-18 12:08:46 +00002041 } else {
2042 #define BUF_LEN 256
2043 Char version_buf[BUF_LEN];
2044 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2045 vg_assert(n <= 256);
2046 if (n > 0) {
2047 version_buf[n-1] = '\0';
njn1fd5eb22005-03-13 05:43:23 +00002048 VG_(message)(Vg_DebugMsg, " %s", version_buf);
nethercotea70f7352004-04-18 12:08:46 +00002049 } else {
njn1fd5eb22005-03-13 05:43:23 +00002050 VG_(message)(Vg_DebugMsg, " (empty?)");
nethercotea70f7352004-04-18 12:08:46 +00002051 }
2052 VG_(close)(fd);
2053 #undef BUF_LEN
2054 }
sewardjde4a1d02002-03-22 01:27:54 +00002055 }
2056
fitzhardinge98abfc72003-12-16 02:05:15 +00002057 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002058 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002059 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002060 needs one, load the default */
2061 static const Char default_supp[] = "default.supp";
2062 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2063 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2064 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2065 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2066 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002067 }
sewardj4cf05692002-10-27 20:28:29 +00002068
sewardjd153fae2005-01-10 17:24:47 +00002069 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002070 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002071 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002072 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002073 VG_(message)(Vg_UserMsg,
2074 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002075 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002076 }
sewardjde4a1d02002-03-22 01:27:54 +00002077}
2078
nethercotef6a1d502004-08-09 12:21:57 +00002079// Build the string for VALGRINDCLO.
2080Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2081{
2082 /* If we're tracing the children, then we need to start it
2083 with our starter+arguments, which are copied into VALGRINDCLO,
2084 except the --exec= option is changed if present.
2085 */
2086 Int i;
2087 Char *exec;
2088 Char *cp;
2089 Char *optvar;
2090 Int optlen, execlen;
2091
2092 // All these allocated blocks are not free - because we're either
2093 // going to exec, or panic when we fail.
2094
2095 // Create --exec= option: "--exec=<exename>"
2096 exec = VG_(arena_malloc)(VG_AR_CORE,
2097 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2098 vg_assert(NULL != exec);
2099 VG_(sprintf)(exec, "--exec=%s", exename);
2100
2101 // Allocate space for optvar (may overestimate by counting --exec twice,
2102 // no matter)
2103 optlen = 1;
2104 for (i = 0; i < vg_argc; i++)
2105 optlen += VG_(strlen)(vg_argv[i]) + 1;
2106 optlen += VG_(strlen)(exec)+1;
2107 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2108
2109 // Copy all valgrind args except the old --exec (if present)
2110 // VG_CLO_SEP is the separator.
2111 cp = optvar;
2112 for (i = 1; i < vg_argc; i++) {
2113 Char *arg = vg_argv[i];
2114
2115 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2116 // don't copy existing --exec= arg
2117 } else if (VG_(strcmp)(arg, "--") == 0) {
2118 // stop at "--"
2119 break;
2120 } else {
2121 // copy non "--exec" arg
2122 Int len = VG_(strlen)(arg);
2123 VG_(memcpy)(cp, arg, len);
2124 cp += len;
2125 *cp++ = VG_CLO_SEP;
2126 }
2127 }
2128 // Add the new --exec= option
2129 execlen = VG_(strlen)(exec);
2130 VG_(memcpy)(cp, exec, execlen);
2131 cp += execlen;
2132 *cp++ = VG_CLO_SEP;
2133
2134 *cp = '\0';
2135
2136 return optvar;
2137}
2138
2139// Build "/proc/self/fd/<execfd>".
2140Char* VG_(build_child_exename)( void )
2141{
2142 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2143 vg_assert(NULL != exename);
2144 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2145 return exename;
2146}
2147
sewardjde4a1d02002-03-22 01:27:54 +00002148
nethercote71980f02004-01-24 18:18:54 +00002149/*====================================================================*/
2150/*=== File descriptor setup ===*/
2151/*====================================================================*/
2152
2153static void setup_file_descriptors(void)
2154{
2155 struct vki_rlimit rl;
2156
2157 /* Get the current file descriptor limits. */
2158 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2159 rl.rlim_cur = 1024;
2160 rl.rlim_max = 1024;
2161 }
2162
2163 /* Work out where to move the soft limit to. */
njn14319cc2005-03-13 06:26:22 +00002164 if (rl.rlim_cur + N_RESERVED_FDS <= rl.rlim_max) {
2165 rl.rlim_cur = rl.rlim_cur + N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002166 } else {
2167 rl.rlim_cur = rl.rlim_max;
2168 }
2169
2170 /* Reserve some file descriptors for our use. */
njn14319cc2005-03-13 06:26:22 +00002171 VG_(fd_soft_limit) = rl.rlim_cur - N_RESERVED_FDS;
2172 VG_(fd_hard_limit) = rl.rlim_cur - N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002173
2174 /* Update the soft limit. */
2175 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2176
nethercotef6a1d502004-08-09 12:21:57 +00002177 if (vgexecfd != -1)
2178 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002179 if (VG_(clexecfd) != -1)
2180 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2181}
2182
nethercote71980f02004-01-24 18:18:54 +00002183/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002184/*=== Initialise program data/text, etc. ===*/
2185/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002186
sewardjb5f6f512005-03-10 23:59:00 +00002187static void build_valgrind_map_callback ( Addr start, SizeT size, UInt prot,
2188 UInt dev, UInt ino, ULong foffset,
2189 const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002190{
nethercote71980f02004-01-24 18:18:54 +00002191 /* Only record valgrind mappings for now, without loading any
2192 symbols. This is so we know where the free space is before we
2193 start allocating more memory (note: heap is OK, it's just mmap
2194 which is the problem here). */
sewardjb5f6f512005-03-10 23:59:00 +00002195 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2196 if (0)
2197 VG_(printf)("init1: %p-%p prot %s\n",
2198 start, start+size, VG_(prot_str)(prot));
2199 VG_(map_file_segment)(start, size, prot,
2200 SF_MMAP|SF_NOSYMS|SF_VALGRIND,
2201 dev, ino, foffset, filename);
2202 /* update VG_(valgrind_last) if it looks wrong */
2203 if (start+size > VG_(valgrind_last))
2204 VG_(valgrind_last) = start+size-1;
nethercote71980f02004-01-24 18:18:54 +00002205 }
sewardjde4a1d02002-03-22 01:27:54 +00002206}
2207
nethercote71980f02004-01-24 18:18:54 +00002208// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002209Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002210
sewardjb5f6f512005-03-10 23:59:00 +00002211/*
2212 This second pass adds in client mappings, and loads symbol tables
2213 for all interesting mappings. The trouble is that things can
2214 change as we go, because we're calling the Tool to track memory as
2215 we find it.
2216
2217 So for Valgrind mappings, we don't replace any mappings which
2218 aren't still identical (which will include the .so mappings, so we
2219 will load their symtabs)>
2220 */
2221static void build_segment_map_callback ( Addr start, SizeT size, UInt prot,
2222 UInt dev, UInt ino, ULong foffset,
2223 const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002224{
nethercote71980f02004-01-24 18:18:54 +00002225 UInt flags;
2226 Bool is_stack_segment;
2227 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002228
nethercote71980f02004-01-24 18:18:54 +00002229 is_stack_segment
2230 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002231
sewardjb5f6f512005-03-10 23:59:00 +00002232 if (0)
2233 VG_(printf)("init2: %p-%p prot %s stack=%d\n",
2234 start, start+size, VG_(prot_str)(prot), is_stack_segment);
fitzhardinge98abfc72003-12-16 02:05:15 +00002235
nethercote71980f02004-01-24 18:18:54 +00002236 if (is_stack_segment)
2237 flags = SF_STACK | SF_GROWDOWN;
2238 else
2239 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002240
nethercote71980f02004-01-24 18:18:54 +00002241 if (filename != NULL)
2242 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002243
sewardjb5f6f512005-03-10 23:59:00 +00002244#if 0
2245 // This needs to be fixed properly. jrs 20050307
2246 if (start >= VG_(client_end) && start < VG_(valgrind_last)) {
2247 Segment *s = VG_(find_segment_before)(start);
fitzhardinge98abfc72003-12-16 02:05:15 +00002248
sewardjb5f6f512005-03-10 23:59:00 +00002249 /* We have to be a bit careful about inserting new mappings into
2250 the Valgrind part of the address space. We're actively
2251 changing things as we parse these mappings, particularly in
2252 shadow memory, and so we don't want to overwrite those
2253 changes. Therefore, we only insert/update a mapping if it is
2254 mapped from a file or it exactly matches an existing mapping.
fitzhardinge98abfc72003-12-16 02:05:15 +00002255
sewardjb5f6f512005-03-10 23:59:00 +00002256 NOTE: we're only talking about the Segment list mapping
2257 metadata; this doesn't actually mmap anything more. */
2258 if (filename || (s && s->addr == start && s->len == size)) {
2259 flags |= SF_VALGRIND;
2260 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2261 } else {
2262 /* assert range is already mapped */
2263 vg_assert(VG_(is_addressable)(start, size, VKI_PROT_NONE));
2264 }
2265 } else
2266#endif
2267 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2268
2269 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1)) {
2270 VG_TRACK( new_mem_startup, start, size,
2271 !!(prot & VKI_PROT_READ),
2272 !!(prot & VKI_PROT_WRITE),
2273 !!(prot & VKI_PROT_EXEC));
2274 }
sewardj3e1eb1f2002-05-18 13:14:17 +00002275
nethercote71980f02004-01-24 18:18:54 +00002276 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002277 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002278 vg_assert(0 != r_esp);
2279 if (is_stack_segment) {
sewardjb5f6f512005-03-10 23:59:00 +00002280 if (0) {
2281 VG_(message)(Vg_DebugMsg, "invalidating stack area: %p .. %p",
nethercote71980f02004-01-24 18:18:54 +00002282 start,r_esp);
sewardjb5f6f512005-03-10 23:59:00 +00002283 VG_(message)(Vg_DebugMsg, " validating stack area: %p .. %p",
2284 r_esp, start+size);
2285 }
nethercote71980f02004-01-24 18:18:54 +00002286 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjb5f6f512005-03-10 23:59:00 +00002287 // what's this for?
2288 //VG_TRACK( post_mem_write, r_esp, (start+size)-r_esp );
sewardjde4a1d02002-03-22 01:27:54 +00002289 }
sewardjde4a1d02002-03-22 01:27:54 +00002290}
2291
2292
nethercote71980f02004-01-24 18:18:54 +00002293/*====================================================================*/
2294/*=== Sanity check machinery (permanently engaged) ===*/
2295/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002296
2297/* A fast sanity check -- suitable for calling circa once per
2298 millisecond. */
2299
nethercote885dd912004-08-03 23:14:00 +00002300void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002301{
sewardjb5f6f512005-03-10 23:59:00 +00002302 ThreadId tid;
2303
njn37cea302002-09-30 11:24:00 +00002304 VGP_PUSHCC(VgpCoreCheapSanity);
2305
nethercote27fec902004-06-16 21:26:32 +00002306 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002307
2308 /* --- First do all the tests that we can do quickly. ---*/
2309
nethercote297effd2004-08-02 15:07:57 +00002310 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002311
njn25e49d8e72002-09-23 09:36:25 +00002312 /* Check stuff pertaining to the memory check system. */
2313
2314 /* Check that nobody has spuriously claimed that the first or
2315 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002316 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002317 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002318 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002319 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002320 }
njn25e49d8e72002-09-23 09:36:25 +00002321
2322 /* --- Now some more expensive checks. ---*/
2323
2324 /* Once every 25 times, check some more expensive stuff. */
2325 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002326 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002327 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002328
njn37cea302002-09-30 11:24:00 +00002329 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002330 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002331
2332# if 0
2333 { void zzzmemscan(void); zzzmemscan(); }
2334# endif
2335
nethercote297effd2004-08-02 15:07:57 +00002336 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002337 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002338
2339 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002340 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002341 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002342 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002343 }
sewardjb5f6f512005-03-10 23:59:00 +00002344
2345 /* Check that Segments and /proc/self/maps match up */
2346 //vg_assert(VG_(sanity_check_memory)());
2347
2348 /* Look for stack overruns. Visit all threads. */
2349 for(tid = 1; tid < VG_N_THREADS; tid++) {
2350 Int remains;
2351
2352 if (VG_(threads)[tid].status == VgTs_Empty ||
2353 VG_(threads)[tid].status == VgTs_Zombie)
2354 continue;
2355
2356 remains = VGA_(stack_unused)(tid);
2357 if (remains < VKI_PAGE_SIZE)
2358 VG_(message)(Vg_DebugMsg, "WARNING: Thread %d is within %d bytes of running out of stack!",
2359 tid, remains);
2360 }
2361
njn25e49d8e72002-09-23 09:36:25 +00002362 /*
nethercote297effd2004-08-02 15:07:57 +00002363 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002364 */
njn37cea302002-09-30 11:24:00 +00002365 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002366 }
2367
nethercote27fec902004-06-16 21:26:32 +00002368 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002369 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002370 /* Check sanity of the low-level memory manager. Note that bugs
2371 in the client's code can cause this to fail, so we don't do
2372 this check unless specially asked for. And because it's
2373 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002374 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002375 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002376 }
njn37cea302002-09-30 11:24:00 +00002377 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002378}
nethercote71980f02004-01-24 18:18:54 +00002379
2380
2381/*====================================================================*/
2382/*=== main() ===*/
2383/*====================================================================*/
2384
nethercotec314eba2004-07-15 12:59:41 +00002385/*
2386 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002387 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002388 loads the client executable (and the dynamic linker, if necessary)
2389 into the client part, and calls into Valgrind proper.
2390
2391 The code is careful not to allow spurious mappings to appear in the
2392 wrong parts of the address space. In particular, to make sure
2393 dlopen puts things in the right place, it will pad out the forbidden
2394 chunks of address space so that dlopen is forced to put things where
2395 we want them.
2396
2397 The memory map it creates is:
2398
njn80950732005-03-26 00:18:45 +00002399 VGA_CLIENT_BASE +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002400 | client address space |
2401 : :
2402 : :
2403 | client stack |
2404 client_end +-------------------------+
2405 | redzone |
2406 shadow_base +-------------------------+
2407 | |
nethercote996901a2004-08-03 13:29:09 +00002408 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002409 | (may be 0 sized) |
2410 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002411 valgrind_base +-------------------------+
2412 | kickstart executable |
2413 | valgrind heap vvvvvvvvv| (barely used)
2414 - -
2415 | valgrind .so files |
2416 | and mappings |
2417 - -
2418 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002419 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002420 : kernel :
2421
2422 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2423 VG_(mmap)(), we need to build the segment skip-list, so we know where
2424 we can put things. However, building that structure requires
2425 allocating memory. So we need to a bootstrapping process. It's done
2426 by making VG_(arena_malloc)() have a special static superblock that's
2427 used for the first 1MB's worth of allocations. This is enough to
2428 build the segment skip-list.
2429*/
2430
nethercote31779c72004-07-30 21:50:15 +00002431static int prmap(char *start, char *end, const char *perm, off_t off,
2432 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002433 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2434 start, end, perm, maj, min, ino);
2435 return True;
2436}
2437
sewardjb5f6f512005-03-10 23:59:00 +00002438int main(int argc, char **argv, char **envp)
nethercote71980f02004-01-24 18:18:54 +00002439{
2440 char **cl_argv;
sewardjb5f6f512005-03-10 23:59:00 +00002441 const char *tool = "memcheck"; // default to Memcheck
nethercote71980f02004-01-24 18:18:54 +00002442 const char *exec = NULL;
2443 char *preload; /* tool-specific LD_PRELOAD .so */
2444 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002445 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002446 struct exeinfo info;
2447 ToolInfo *toolinfo = NULL;
2448 void *tool_dlhandle;
2449 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002450 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002451 UInt * client_auxv;
nethercote73b526f2004-10-31 18:48:21 +00002452 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002453 Int padfile;
nethercote71980f02004-01-24 18:18:54 +00002454
2455 //============================================================
2456 // Nb: startup is complex. Prerequisites are shown at every step.
2457 //
2458 // *** Be very careful when messing with the order ***
2459 //============================================================
2460
nethercotef4928da2004-06-15 10:54:40 +00002461 //============================================================
2462 // Command line argument handling order:
2463 // * If --help/--help-debug are present, show usage message
sewardjb5f6f512005-03-10 23:59:00 +00002464 // (including the tool-specific usage)
2465 // * (If no --tool option given, default to Memcheck)
nethercotef4928da2004-06-15 10:54:40 +00002466 // * Then, if client is missing, abort with error msg
2467 // * Then, if any cmdline args are bad, abort with error msg
2468 //============================================================
2469
fitzhardingeb50068f2004-02-24 23:42:55 +00002470 // Get the current process datasize rlimit, and set it to zero.
2471 // This prevents any internal uses of brk() from having any effect.
2472 // We remember the old value so we can restore it on exec, so that
2473 // child processes will have a reasonable brk value.
2474 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2475 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2476 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002477
2478 // Get the current process stack rlimit.
2479 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2480
nethercote71980f02004-01-24 18:18:54 +00002481 //--------------------------------------------------------------
2482 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002483 // p: none
nethercote71980f02004-01-24 18:18:54 +00002484 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002485 {
2486 void* init_sp = argv - 1;
2487 padfile = scan_auxv(init_sp);
2488 }
nethercote71980f02004-01-24 18:18:54 +00002489 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002490 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002491 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002492 }
2493
2494 //--------------------------------------------------------------
2495 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002496 // p: none
nethercote71980f02004-01-24 18:18:54 +00002497 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002498 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002499 if (cp != NULL)
2500 VG_(libdir) = cp;
2501 }
2502
2503 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002504 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2505 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002506 // p: none
nethercote71980f02004-01-24 18:18:54 +00002507 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002508 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002509 pre_process_cmd_line_options(&need_help, &tool, &exec);
2510
2511 //==============================================================
2512 // Nb: once a tool is specified, the tool.so must be loaded even if
2513 // they specified --help or didn't specify a client program.
2514 //==============================================================
2515
2516 //--------------------------------------------------------------
2517 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002518 // p: set-libdir [for VG_(libdir)]
2519 // p: pre_process_cmd_line_options() [for 'tool']
2520 //--------------------------------------------------------------
2521 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2522
2523 //==============================================================
2524 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002525 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002526 //==============================================================
2527
2528 //--------------------------------------------------------------
2529 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002530 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002531 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002532 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002533
2534 //--------------------------------------------------------------
2535 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002536 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2537 // p: layout_remaining_space [so there's space]
2538 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002539 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002540
2541 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002542 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002543 // p: layout_remaining_space() [everything must be mapped in before now]
2544 // p: load_client() [ditto]
2545 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002546 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2547 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002548
2549 //--------------------------------------------------------------
2550 // Set up client's environment
2551 // p: set-libdir [for VG_(libdir)]
2552 // p: load_tool() [for 'preload']
2553 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002554 env = fix_environment(envp, preload);
nethercote71980f02004-01-24 18:18:54 +00002555
2556 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002557 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002558 // p: load_client() [for 'info']
2559 // p: fix_environment() [for 'env']
2560 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002561 {
2562 void* init_sp = argv - 1;
sewardjb5f6f512005-03-10 23:59:00 +00002563
nethercote4ad74312004-10-26 09:59:49 +00002564 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2565 &client_auxv);
sewardjb5f6f512005-03-10 23:59:00 +00002566 free(env);
nethercotec25c4492004-10-18 11:52:17 +00002567 }
nethercote71980f02004-01-24 18:18:54 +00002568
2569 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002570 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002571 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002572 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002573
2574 //==============================================================
2575 // Finished setting up operating environment. Now initialise
2576 // Valgrind. (This is where the old VG_(main)() started.)
2577 //==============================================================
2578
2579 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002580 // setup file descriptors
2581 // p: n/a
2582 //--------------------------------------------------------------
2583 setup_file_descriptors();
2584
2585 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002586 // Build segment map (Valgrind segments only)
njnd2252832004-11-26 10:53:33 +00002587 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002588 //--------------------------------------------------------------
2589 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2590
2591 //==============================================================
2592 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2593 //==============================================================
2594
2595 //--------------------------------------------------------------
2596 // Init tool: pre_clo_init, process cmd line, post_clo_init
2597 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2598 // p: load_tool() [for 'tool']
2599 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2600 // p: parse_procselfmaps [so VG segments are setup so tool can
2601 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002602 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002603 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002604 VG_(tool_init_dlsym)(tool_dlhandle);
2605 VG_(sanity_check_needs)();
2606
nethercotef4928da2004-06-15 10:54:40 +00002607 // If --tool and --help/--help-debug was given, now give the core+tool
2608 // help message
nethercotef4928da2004-06-15 10:54:40 +00002609 if (need_help) {
2610 usage(/*--help-debug?*/2 == need_help);
2611 }
nethercotec314eba2004-07-15 12:59:41 +00002612 process_cmd_line_options(client_auxv, tool);
2613
njn26f02512004-11-22 18:33:15 +00002614 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002615
2616 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002617 // Determine CPU architecture and subarchitecture
2618 // p: none
2619 //--------------------------------------------------------------
2620 { Bool ok = VGA_(getArchAndSubArch)(
2621 & VG_(vex_arch), & VG_(vex_subarch) );
2622 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002623 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002624 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002625 VG_(printf)(" Supported CPUs are:\n");
2626 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2627 "AMD Athlon or above)\n");
2628 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002629 VG_(exit)(1);
2630 }
2631 if (VG_(clo_verbosity) > 2) {
2632 VG_(message)(Vg_DebugMsg,
2633 "Host CPU: arch = %s, subarch = %s",
2634 LibVEX_ppVexArch( VG_(vex_arch) ),
2635 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2636 }
2637 }
2638
2639 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002640 // Build segment map (all segments)
sewardjb5f6f512005-03-10 23:59:00 +00002641 // p: shadow/redzone segments
nethercote4ad74312004-10-26 09:59:49 +00002642 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002643 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002644 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002645 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002646 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002647 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002648
sewardja4da2f32005-03-02 14:06:08 +00002649#if defined(__i386__) || defined(__amd64__)
nethercotec314eba2004-07-15 12:59:41 +00002650 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002651 // Protect client trampoline page (which is also sysinfo stuff)
2652 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002653 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002654 {
2655 Segment *seg;
2656 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2657 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002658#endif
sewardjb5f6f512005-03-10 23:59:00 +00002659 /* Make sure this segment isn't treated as stack */
2660 seg = VG_(find_segment)(VG_(client_trampoline_code));
2661 if (seg)
2662 seg->flags &= ~(SF_STACK | SF_GROWDOWN);
2663 }
2664
nethercotec314eba2004-07-15 12:59:41 +00002665 //==============================================================
2666 // Can use VG_(map)() after segments set up
2667 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002668
2669 //--------------------------------------------------------------
2670 // Allow GDB attach
2671 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2672 //--------------------------------------------------------------
2673 /* Hook to delay things long enough so we can get the pid and
2674 attach GDB in another shell. */
2675 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002676 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2677 /* jrs 20050206: I don't understand why this works on x86. On
2678 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2679 work. */
2680 /* do "jump *$eip" to skip this in gdb (x86) */
2681 //VG_(do_syscall0)(__NR_pause);
2682 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002683 }
2684
sewardjb5d320c2005-03-13 18:57:15 +00002685 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002686 // Search for file descriptors that are inherited from our parent
2687 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2688 //--------------------------------------------------------------
2689 if (VG_(clo_track_fds))
2690 VG_(init_preopened_fds)();
2691
2692 //--------------------------------------------------------------
2693 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002694 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2695 //--------------------------------------------------------------
2696 VG_(scheduler_init)();
2697
2698 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002699 // Initialise the pthread model
2700 // p: ?
sewardj2a99cf62004-11-24 10:44:19 +00002701 // load_client() [for 'client_eip']
2702 // setup_client_stack() [for 'sp_at_startup']
2703 // setup_scheduler() [for the rest of state 1 stuff]
2704 //--------------------------------------------------------------
2705 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002706
2707 // Tell the tool that we just wrote to the registers.
2708 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2709 sizeof(VexGuestArchState));
2710
2711 // Record the instr ptr offset, for use by asm code.
njn35172bc2005-03-26 00:04:03 +00002712 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, VGA_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002713
2714 //--------------------------------------------------------------
sewardj39b88fb2005-03-12 15:16:07 +00002715 // Initialise the pthread model
2716 // p: ?
nethercote71980f02004-01-24 18:18:54 +00002717 //--------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +00002718 //if (VG_(clo_model_pthreads))
2719 // VG_(pthread_init)();
nethercote71980f02004-01-24 18:18:54 +00002720
2721 //--------------------------------------------------------------
2722 // Initialise the signal handling subsystem
sewardjb5f6f512005-03-10 23:59:00 +00002723 // p: n/a
nethercote71980f02004-01-24 18:18:54 +00002724 //--------------------------------------------------------------
2725 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2726 VG_(sigstartup_actions)();
2727
2728 //--------------------------------------------------------------
2729 // Perhaps we're profiling Valgrind?
2730 // p: process_cmd_line_options() [for VG_(clo_profile)]
2731 // p: others?
2732 //
2733 // XXX: this seems to be broken? It always says the tool wasn't built
2734 // for profiling; vg_profile.c's functions don't seem to be overriding
2735 // vg_dummy_profile.c's?
2736 //
2737 // XXX: want this as early as possible. Looking for --profile
2738 // in pre_process_cmd_line_options() could get it earlier.
2739 //--------------------------------------------------------------
2740 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002741 VG_(init_profiling)();
nethercote71980f02004-01-24 18:18:54 +00002742
2743 VGP_PUSHCC(VgpStartup);
2744
2745 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002746 // Read suppression file
2747 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2748 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002749 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002750 VG_(load_suppressions)();
2751
2752 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002753 // Initialise translation table and translation cache
2754 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2755 // aren't identified as part of the client, which would waste
2756 // > 20M of virtual address space.]
2757 //--------------------------------------------------------------
2758 VG_(init_tt_tc)();
2759
2760 //--------------------------------------------------------------
sewardjb5d320c2005-03-13 18:57:15 +00002761 // Read debug info to find glibc entry points to intercept
2762 // p: parse_procselfmaps? [XXX for debug info?]
2763 // p: init_tt_tc [so it can call VG_(search_transtab) safely]
2764 //--------------------------------------------------------------
2765 VG_(setup_code_redirect_table)();
2766
2767 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002768 // Verbosity message
2769 // p: end_rdtsc_calibration [so startup message is printed first]
2770 //--------------------------------------------------------------
2771 if (VG_(clo_verbosity) == 1)
2772 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2773 if (VG_(clo_verbosity) > 0)
2774 VG_(message)(Vg_UserMsg, "");
2775
2776 //--------------------------------------------------------------
2777 // Setup pointercheck
2778 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2779 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002780 if (VG_(clo_pointercheck))
2781 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002782
nethercote71980f02004-01-24 18:18:54 +00002783 //--------------------------------------------------------------
2784 // Run!
2785 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002786 VGP_POPCC(VgpStartup);
nethercote71980f02004-01-24 18:18:54 +00002787
sewardjb5f6f512005-03-10 23:59:00 +00002788 vg_assert(VG_(master_tid) == 1);
nethercote71980f02004-01-24 18:18:54 +00002789
sewardjb5f6f512005-03-10 23:59:00 +00002790 VGA_(main_thread_wrapper)(1);
nethercote71980f02004-01-24 18:18:54 +00002791
sewardjb5f6f512005-03-10 23:59:00 +00002792 abort();
2793}
2794
2795
2796/* Do everything which needs doing when the last thread exits */
2797void VG_(shutdown_actions)(ThreadId tid)
2798{
2799 vg_assert(tid == VG_(master_tid));
2800 vg_assert(VG_(is_running_thread)(tid));
2801
2802 // Wait for all other threads to exit.
2803 VGA_(reap_threads)(tid);
2804
2805 VG_(clo_model_pthreads) = False;
2806
2807 // Clean the client up before the final report
2808 VGA_(final_tidyup)(tid);
2809
2810 // OK, done
2811 VG_(exit_thread)(tid);
2812
2813 /* should be no threads left */
2814 vg_assert(VG_(count_living_threads)() == 0);
2815
2816 VG_(threads)[tid].status = VgTs_Empty;
nethercote71980f02004-01-24 18:18:54 +00002817 //--------------------------------------------------------------
2818 // Finalisation: cleanup, messages, etc. Order no so important, only
2819 // affects what order the messages come.
2820 //--------------------------------------------------------------
2821 if (VG_(clo_verbosity) > 0)
2822 VG_(message)(Vg_UserMsg, "");
2823
nethercote71980f02004-01-24 18:18:54 +00002824 /* Print out file descriptor summary and stats. */
2825 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002826 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002827
njn95ec8702004-11-22 16:46:13 +00002828 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002829 VG_(show_all_errors)();
2830
sewardjb5f6f512005-03-10 23:59:00 +00002831 TL_(fini)( 0 /*exitcode*/ );
nethercote71980f02004-01-24 18:18:54 +00002832
nethercote885dd912004-08-03 23:14:00 +00002833 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002834
2835 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002836 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002837
nethercote71980f02004-01-24 18:18:54 +00002838 if (VG_(clo_profile))
njn31066fd2005-03-26 00:42:02 +00002839 VG_(done_profiling)();
sewardjfa8ec112005-01-19 11:55:34 +00002840 if (VG_(clo_profile_flags) > 0)
2841 VG_(show_BB_profile)();
2842
sewardj8b635a42004-11-22 19:01:47 +00002843 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002844 if (0)
2845 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002846
nethercote71980f02004-01-24 18:18:54 +00002847}
2848
sewardjde4a1d02002-03-22 01:27:54 +00002849/*--------------------------------------------------------------------*/
2850/*--- end vg_main.c ---*/
2851/*--------------------------------------------------------------------*/