blob: 0dc668219341c8abbf4b1e52eba1fb68e0244d5d [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote71980f02004-01-24 18:18:54 +00003/*--- Startup: the real stuff vg_main.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercote71980f02004-01-24 18:18:54 +000031#define _FILE_OFFSET_BITS 64
sewardjde4a1d02002-03-22 01:27:54 +000032
nethercotef1e5e152004-09-01 23:58:16 +000033#include "core.h"
nethercote71980f02004-01-24 18:18:54 +000034#include "ume.h"
nethercote71980f02004-01-24 18:18:54 +000035
36#include <dirent.h>
37#include <dlfcn.h>
38#include <errno.h>
nethercote71980f02004-01-24 18:18:54 +000039#include <stdio.h>
fitzhardingeb727d042004-01-06 00:18:21 +000040#include <stdlib.h>
nethercote71980f02004-01-24 18:18:54 +000041#include <string.h>
42#include <sys/mman.h>
nethercote71980f02004-01-24 18:18:54 +000043#include <sys/stat.h>
fitzhardingeb727d042004-01-06 00:18:21 +000044#include <sys/ptrace.h>
fitzhardingeb727d042004-01-06 00:18:21 +000045#include <sys/wait.h>
46#include <unistd.h>
47
thughes74b8de22004-04-22 18:12:31 +000048#ifndef AT_DCACHEBSIZE
49#define AT_DCACHEBSIZE 19
50#endif /* AT_DCACHEBSIZE */
51
52#ifndef AT_ICACHEBSIZE
53#define AT_ICACHEBSIZE 20
54#endif /* AT_ICACHEBSIZE */
55
56#ifndef AT_UCACHEBSIZE
57#define AT_UCACHEBSIZE 21
58#endif /* AT_UCACHEBSIZE */
59
nethercote71980f02004-01-24 18:18:54 +000060#ifndef AT_SYSINFO
61#define AT_SYSINFO 32
62#endif /* AT_SYSINFO */
63
64#ifndef AT_SYSINFO_EHDR
65#define AT_SYSINFO_EHDR 33
66#endif /* AT_SYSINFO_EHDR */
67
68#ifndef AT_SECURE
69#define AT_SECURE 23 /* secure mode boolean */
70#endif /* AT_SECURE */
71
nethercote71980f02004-01-24 18:18:54 +000072/* redzone gap between client address space and shadow */
73#define REDZONE_SIZE (1 * 1024*1024)
74
75/* size multiple for client address space */
nethercotee94b2de2004-06-23 16:15:06 +000076#define CLIENT_SIZE_MULTIPLE (1 * 1024*1024)
nethercote71980f02004-01-24 18:18:54 +000077
nethercotee2097312004-06-27 12:29:56 +000078/* Proportion of client space for its heap (rest is for mmaps + stack) */
79#define CLIENT_HEAP_PROPORTION 0.333
nethercote71980f02004-01-24 18:18:54 +000080
81/*====================================================================*/
82/*=== Global entities not referenced from generated code ===*/
83/*====================================================================*/
84
sewardjde4a1d02002-03-22 01:27:54 +000085/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +000086 Startup stuff
sewardjde4a1d02002-03-22 01:27:54 +000087 ------------------------------------------------------------------ */
88
nethercote71980f02004-01-24 18:18:54 +000089/* Client address space, lowest to highest (see top of ume.c) */
90Addr VG_(client_base); /* client address space limits */
fitzhardinge98abfc72003-12-16 02:05:15 +000091Addr VG_(client_end);
92Addr VG_(client_mapbase);
fitzhardinge92360792003-12-24 10:11:11 +000093Addr VG_(client_trampoline_code);
fitzhardinge98abfc72003-12-16 02:05:15 +000094Addr VG_(clstk_base);
95Addr VG_(clstk_end);
nethercote71980f02004-01-24 18:18:54 +000096
97Addr VG_(brk_base); /* start of brk */
98Addr VG_(brk_limit); /* current brk */
99
nethercote996901a2004-08-03 13:29:09 +0000100Addr VG_(shadow_base); /* tool's shadow memory */
fitzhardinge98abfc72003-12-16 02:05:15 +0000101Addr VG_(shadow_end);
nethercote71980f02004-01-24 18:18:54 +0000102
103Addr VG_(valgrind_base); /* valgrind's address range */
rjwalsh18b66312004-08-23 18:15:12 +0000104
nethercote820bd8c2004-09-07 23:04:49 +0000105// Note that VG_(valgrind_last) names the last byte of the section, whereas
106// the VG_(*_end) vars name the byte one past the end of the section.
107Addr VG_(valgrind_last);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108
nethercote73b526f2004-10-31 18:48:21 +0000109struct vki_rlimit VG_(client_rlimit_data);
110struct vki_rlimit VG_(client_rlimit_stack);
fitzhardingeb50068f2004-02-24 23:42:55 +0000111
fitzhardinge98abfc72003-12-16 02:05:15 +0000112/* stage1 (main) executable */
nethercotef6a1d502004-08-09 12:21:57 +0000113static Int vgexecfd = -1;
fitzhardingea49f9b52003-12-16 22:26:45 +0000114
115/* client executable */
116Int VG_(clexecfd) = -1;
fitzhardinge98abfc72003-12-16 02:05:15 +0000117
118/* Path to library directory */
119const Char *VG_(libdir) = VG_LIBDIR;
120
121/* our argc/argv */
nethercotef6a1d502004-08-09 12:21:57 +0000122static Int vg_argc;
123static Char **vg_argv;
fitzhardinge98abfc72003-12-16 02:05:15 +0000124
jsgf855d93d2003-10-13 22:26:55 +0000125/* PID of the main thread */
126Int VG_(main_pid);
127
128/* PGRP of process */
129Int VG_(main_pgrp);
njn25e49d8e72002-09-23 09:36:25 +0000130
thughesad1c9562004-06-26 11:27:52 +0000131/* Application-visible file descriptor limits */
132Int VG_(fd_soft_limit) = -1;
133Int VG_(fd_hard_limit) = -1;
fitzhardingef0046f22003-12-18 02:39:22 +0000134
nethercote4ad74312004-10-26 09:59:49 +0000135/* As deduced from sp_at_startup, the client's argc, argv[] and
nethercote71980f02004-01-24 18:18:54 +0000136 envp[] as extracted from the client's stack at startup-time. */
137Int VG_(client_argc);
138Char** VG_(client_argv);
139Char** VG_(client_envp);
sewardjde4a1d02002-03-22 01:27:54 +0000140
njn16de5572004-11-27 14:27:21 +0000141// Instruction pointer guest state offset, used by $VG_ARCH/dispatch.S.
njn87c98122004-11-30 23:32:01 +0000142OffT VG_(instr_ptr_offset);
njn16de5572004-11-27 14:27:21 +0000143
sewardj51ac0872004-12-21 01:20:49 +0000144/* Indicates what arch and subarch we are running on. */
145VexArch VG_(vex_arch) = VexArch_INVALID;
146VexSubArch VG_(vex_subarch) = VexSubArch_INVALID;
147
148
sewardjde4a1d02002-03-22 01:27:54 +0000149/* ---------------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +0000150 Running stuff
sewardjde4a1d02002-03-22 01:27:54 +0000151 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000152
nethercote71980f02004-01-24 18:18:54 +0000153/* Counts downwards in VG_(run_innerloop). */
154UInt VG_(dispatch_ctr);
sewardjde4a1d02002-03-22 01:27:54 +0000155
156/* 64-bit counter for the number of basic blocks done. */
sewardj8b635a42004-11-22 19:01:47 +0000157ULong VG_(bbs_done) = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000158
nethercote71980f02004-01-24 18:18:54 +0000159/* Tell the logging mechanism whether we are logging to a file
160 descriptor or a socket descriptor. */
161Bool VG_(logging_to_filedes) = True;
162
sewardj73cf3bc2002-11-03 03:20:15 +0000163
nethercote71980f02004-01-24 18:18:54 +0000164/*====================================================================*/
165/*=== Counters, for profiling purposes only ===*/
166/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +0000167
sewardjde4a1d02002-03-22 01:27:54 +0000168/* Counts pertaining to internal sanity checking. */
nethercote297effd2004-08-02 15:07:57 +0000169static UInt sanity_fast_count = 0;
170static UInt sanity_slow_count = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000171
nethercote3a42fb82004-08-03 18:08:50 +0000172static void print_all_stats ( void )
nethercote71980f02004-01-24 18:18:54 +0000173{
nethercote3a42fb82004-08-03 18:08:50 +0000174 // Translation stats
nethercote92e7b7f2004-08-07 17:52:25 +0000175 VG_(print_tt_tc_stats)();
nethercote71980f02004-01-24 18:18:54 +0000176 VG_(message)(Vg_DebugMsg,
sewardj4ccf7072004-11-28 16:58:05 +0000177 " dispatch: %llu jumps (bb entries).", VG_(bbs_done) );
nethercote71980f02004-01-24 18:18:54 +0000178
nethercote3a42fb82004-08-03 18:08:50 +0000179 // Scheduler stats
nethercote844e7122004-08-02 15:27:22 +0000180 VG_(print_scheduler_stats)();
nethercote71980f02004-01-24 18:18:54 +0000181
nethercote71980f02004-01-24 18:18:54 +0000182 VG_(message)(Vg_DebugMsg,
183 " sanity: %d cheap, %d expensive checks.",
nethercote297effd2004-08-02 15:07:57 +0000184 sanity_fast_count, sanity_slow_count );
nethercote3a42fb82004-08-03 18:08:50 +0000185
nethercote3a42fb82004-08-03 18:08:50 +0000186 // Memory stats
nethercote885dd912004-08-03 23:14:00 +0000187 if (VG_(clo_verbosity) > 2) {
nethercote3a42fb82004-08-03 18:08:50 +0000188 VG_(message)(Vg_DebugMsg, "");
189 VG_(message)(Vg_DebugMsg,
190 "------ Valgrind's internal memory use stats follow ------" );
nethercote885dd912004-08-03 23:14:00 +0000191 VG_(sanity_check_malloc_all)();
nethercote3a42fb82004-08-03 18:08:50 +0000192 VG_(print_all_arena_stats)();
nethercote885dd912004-08-03 23:14:00 +0000193 VG_(message)(Vg_DebugMsg, "");
nethercote3a42fb82004-08-03 18:08:50 +0000194 VG_(message)(Vg_DebugMsg,
195 "------ Valgrind's ExeContext management stats follow ------" );
196 VG_(print_ExeContext_stats)();
197 }
nethercote71980f02004-01-24 18:18:54 +0000198}
199
200
201/*====================================================================*/
202/*=== Miscellaneous global functions ===*/
203/*====================================================================*/
204
nethercotecf97ffb2004-09-09 13:40:31 +0000205static Int ptrace_setregs(Int pid, ThreadId tid)
206{
sewardj2a99cf62004-11-24 10:44:19 +0000207 return VGA_(ptrace_setregs_from_tst)(pid, &VG_(threads)[tid].arch);
nethercotecf97ffb2004-09-09 13:40:31 +0000208}
209
nethercote04d0fbc2004-01-26 16:48:06 +0000210/* Start debugger and get it to attach to this process. Called if the
211 user requests this service after an error has been shown, so she can
nethercote71980f02004-01-24 18:18:54 +0000212 poke around and look at parameters, memory, etc. You can't
nethercote04d0fbc2004-01-26 16:48:06 +0000213 meaningfully get the debugger to continue the program, though; to
214 continue, quit the debugger. */
njnc6168192004-11-29 13:54:10 +0000215void VG_(start_debugger) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000216{
217 Int pid;
218
219 if ((pid = fork()) == 0) {
220 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
nethercote73b526f2004-10-31 18:48:21 +0000221 VG_(kill)(VG_(getpid)(), VKI_SIGSTOP);
nethercote71980f02004-01-24 18:18:54 +0000222
223 } else if (pid > 0) {
nethercote71980f02004-01-24 18:18:54 +0000224 Int status;
225 Int res;
226
nethercote71980f02004-01-24 18:18:54 +0000227 if ((res = VG_(waitpid)(pid, &status, 0)) == pid &&
228 WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP &&
nethercotecf97ffb2004-09-09 13:40:31 +0000229 ptrace_setregs(pid, tid) == 0 &&
thughes1d160052004-04-21 15:39:57 +0000230 kill(pid, SIGSTOP) == 0 &&
231 ptrace(PTRACE_DETACH, pid, NULL, 0) == 0) {
nethercote04d0fbc2004-01-26 16:48:06 +0000232 Char pidbuf[15];
233 Char file[30];
234 Char buf[100];
235 Char *bufptr;
236 Char *cmdptr;
237
238 VG_(sprintf)(pidbuf, "%d", pid);
239 VG_(sprintf)(file, "/proc/%d/fd/%d", pid, VG_(clexecfd));
240
241 bufptr = buf;
242 cmdptr = VG_(clo_db_command);
243
244 while (*cmdptr) {
245 switch (*cmdptr) {
246 case '%':
247 switch (*++cmdptr) {
248 case 'f':
249 VG_(memcpy)(bufptr, file, VG_(strlen)(file));
250 bufptr += VG_(strlen)(file);
251 cmdptr++;
252 break;
253 case 'p':
254 VG_(memcpy)(bufptr, pidbuf, VG_(strlen)(pidbuf));
255 bufptr += VG_(strlen)(pidbuf);
256 cmdptr++;
257 break;
258 default:
259 *bufptr++ = *cmdptr++;
260 break;
261 }
262 break;
263 default:
264 *bufptr++ = *cmdptr++;
265 break;
266 }
267 }
268
269 *bufptr++ = '\0';
270
271 VG_(message)(Vg_UserMsg, "starting debugger with cmd: %s", buf);
nethercote71980f02004-01-24 18:18:54 +0000272 res = VG_(system)(buf);
273 if (res == 0) {
274 VG_(message)(Vg_UserMsg, "");
275 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +0000276 "Debugger has detached. Valgrind regains control. We continue.");
nethercote71980f02004-01-24 18:18:54 +0000277 } else {
278 VG_(message)(Vg_UserMsg, "Apparently failed!");
279 VG_(message)(Vg_UserMsg, "");
280 }
281 }
282
nethercote73b526f2004-10-31 18:48:21 +0000283 VG_(kill)(pid, VKI_SIGKILL);
nethercote71980f02004-01-24 18:18:54 +0000284 VG_(waitpid)(pid, &status, 0);
285 }
286}
287
288
289/* Print some helpful-ish text about unimplemented things, and give
290 up. */
291void VG_(unimplemented) ( Char* msg )
292{
293 VG_(message)(Vg_UserMsg, "");
294 VG_(message)(Vg_UserMsg,
295 "Valgrind detected that your program requires");
296 VG_(message)(Vg_UserMsg,
297 "the following unimplemented functionality:");
298 VG_(message)(Vg_UserMsg, " %s", msg);
299 VG_(message)(Vg_UserMsg,
300 "This may be because the functionality is hard to implement,");
301 VG_(message)(Vg_UserMsg,
302 "or because no reasonable program would behave this way,");
303 VG_(message)(Vg_UserMsg,
304 "or because nobody has yet needed it. In any case, let us know at");
305 VG_(message)(Vg_UserMsg,
306 "%s and/or try to work around the problem, if you can.", VG_BUGS_TO);
307 VG_(message)(Vg_UserMsg,
308 "");
309 VG_(message)(Vg_UserMsg,
310 "Valgrind has to exit now. Sorry. Bye!");
311 VG_(message)(Vg_UserMsg,
312 "");
313 VG_(pp_sched_status)();
314 VG_(exit)(1);
315}
316
sewardj2a99cf62004-11-24 10:44:19 +0000317/* Get the simulated stack pointer */
318Addr VG_(get_stack_pointer) ( ThreadId tid )
nethercote71980f02004-01-24 18:18:54 +0000319{
njncf45fd42004-11-24 16:30:22 +0000320 return STACK_PTR( VG_(threads)[tid].arch );
nethercote71980f02004-01-24 18:18:54 +0000321}
322
njnea4b28c2004-11-30 16:04:58 +0000323/* Debugging thing .. can be called from assembly with OYNK macro. */
324void VG_(oynk) ( Int n )
325{
326 OINK(n);
327}
328
nethercote71980f02004-01-24 18:18:54 +0000329/* Initialize the PID and PGRP of scheduler LWP; this is also called
330 in any new children after fork. */
331static void newpid(ThreadId unused)
332{
333 /* PID of scheduler LWP */
334 VG_(main_pid) = VG_(getpid)();
335 VG_(main_pgrp) = VG_(getpgrp)();
336}
337
338/*====================================================================*/
339/*=== Check we were launched by stage 1 ===*/
340/*====================================================================*/
341
342/* Look for our AUXV table */
nethercotec25c4492004-10-18 11:52:17 +0000343int scan_auxv(void* init_sp)
nethercote71980f02004-01-24 18:18:54 +0000344{
nethercoteebf1d862004-11-01 18:22:05 +0000345 const struct ume_auxv *auxv = find_auxv((UWord*)init_sp);
nethercote31779c72004-07-30 21:50:15 +0000346 int padfile = -1, found = 0;
nethercote71980f02004-01-24 18:18:54 +0000347
348 for (; auxv->a_type != AT_NULL; auxv++)
349 switch(auxv->a_type) {
350 case AT_UME_PADFD:
nethercote31779c72004-07-30 21:50:15 +0000351 padfile = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000352 found |= 1;
353 break;
354
355 case AT_UME_EXECFD:
nethercotef6a1d502004-08-09 12:21:57 +0000356 vgexecfd = auxv->u.a_val;
nethercote71980f02004-01-24 18:18:54 +0000357 found |= 2;
358 break;
nethercote7f390022004-10-25 17:18:24 +0000359
360 case AT_PHDR:
361 VG_(valgrind_base) = PGROUNDDN(auxv->u.a_val);
362 break;
nethercote71980f02004-01-24 18:18:54 +0000363 }
364
nethercote361a14e2004-07-26 11:11:56 +0000365 if ( found != (1|2) ) {
366 fprintf(stderr, "valgrind: stage2 must be launched by stage1\n");
nethercote71980f02004-01-24 18:18:54 +0000367 exit(127);
368 }
nethercote31779c72004-07-30 21:50:15 +0000369 vg_assert(padfile >= 0);
370 return padfile;
nethercote71980f02004-01-24 18:18:54 +0000371}
372
373
374/*====================================================================*/
375/*=== Address space determination ===*/
376/*====================================================================*/
377
nethercote7f390022004-10-25 17:18:24 +0000378extern char _start[];
379
nethercote31779c72004-07-30 21:50:15 +0000380static void layout_remaining_space(Addr argc_addr, float ratio)
nethercote71980f02004-01-24 18:18:54 +0000381{
nethercotea3c3cf22004-11-01 18:38:00 +0000382 Int ires;
383 void* vres;
384 Addr client_size, shadow_size;
nethercote71980f02004-01-24 18:18:54 +0000385
nethercote7f390022004-10-25 17:18:24 +0000386 // VG_(valgrind_base) should have been set by scan_auxv, but if not,
387 // this is a workable approximation
388 if (VG_(valgrind_base) == 0) {
nethercote7f390022004-10-25 17:18:24 +0000389 VG_(valgrind_base) = PGROUNDDN(&_start);
390 }
391
nethercote820bd8c2004-09-07 23:04:49 +0000392 VG_(valgrind_last) = ROUNDUP(argc_addr, 0x10000) - 1; // stack
nethercote71980f02004-01-24 18:18:54 +0000393
nethercote31779c72004-07-30 21:50:15 +0000394 // This gives the client the largest possible address space while
395 // taking into account the tool's shadow needs.
396 client_size = ROUNDDN((VG_(valgrind_base)-REDZONE_SIZE) / (1.+ratio),
nethercote71980f02004-01-24 18:18:54 +0000397 CLIENT_SIZE_MULTIPLE);
nethercote31779c72004-07-30 21:50:15 +0000398 VG_(client_base) = CLIENT_BASE;
nethercote71980f02004-01-24 18:18:54 +0000399 VG_(client_end) = VG_(client_base) + client_size;
nethercotee2097312004-06-27 12:29:56 +0000400 /* where !FIXED mmap goes */
nethercotebc7b4f42004-07-26 12:44:35 +0000401 VG_(client_mapbase) = VG_(client_base) +
nethercotea3c3cf22004-11-01 18:38:00 +0000402 PGROUNDDN((Addr)(client_size * CLIENT_HEAP_PROPORTION));
nethercote71980f02004-01-24 18:18:54 +0000403
nethercote31779c72004-07-30 21:50:15 +0000404 VG_(shadow_base) = VG_(client_end) + REDZONE_SIZE;
nethercote410bfe62004-09-04 15:53:35 +0000405 VG_(shadow_end) = VG_(valgrind_base);
406 shadow_size = VG_(shadow_end) - VG_(shadow_base);
nethercote71980f02004-01-24 18:18:54 +0000407
nethercotee2097312004-06-27 12:29:56 +0000408#define SEGSIZE(a,b) ((VG_(b) - VG_(a))/(1024*1024))
409
nethercote71980f02004-01-24 18:18:54 +0000410 if (0)
nethercotee2097312004-06-27 12:29:56 +0000411 VG_(printf)(
412 "client_base %8x (%dMB)\n"
413 "client_mapbase %8x (%dMB)\n"
414 "client_end %8x (%dMB)\n"
415 "shadow_base %8x (%dMB)\n"
nethercote410bfe62004-09-04 15:53:35 +0000416 "shadow_end %8x\n"
nethercotee2097312004-06-27 12:29:56 +0000417 "valgrind_base %8x (%dMB)\n"
nethercote820bd8c2004-09-07 23:04:49 +0000418 "valgrind_last %8x\n",
nethercotee2097312004-06-27 12:29:56 +0000419 VG_(client_base), SEGSIZE(client_base, client_mapbase),
420 VG_(client_mapbase), SEGSIZE(client_mapbase, client_end),
421 VG_(client_end), SEGSIZE(client_end, shadow_base),
422 VG_(shadow_base), SEGSIZE(shadow_base, shadow_end),
nethercote410bfe62004-09-04 15:53:35 +0000423 VG_(shadow_end),
nethercote820bd8c2004-09-07 23:04:49 +0000424 VG_(valgrind_base), SEGSIZE(valgrind_base, valgrind_last),
425 VG_(valgrind_last)
nethercotee2097312004-06-27 12:29:56 +0000426 );
427
428#undef SEGSIZE
nethercote71980f02004-01-24 18:18:54 +0000429
430 // Ban redzone
nethercotee567e702004-07-10 17:49:17 +0000431 vres = mmap((void *)VG_(client_end), REDZONE_SIZE, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000432 MAP_FIXED|MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);
nethercotee567e702004-07-10 17:49:17 +0000433 vg_assert((void*)-1 != vres);
nethercote71980f02004-01-24 18:18:54 +0000434
435 // Make client hole
nethercotee567e702004-07-10 17:49:17 +0000436 ires = munmap((void*)VG_(client_base), client_size);
437 vg_assert(0 == ires);
nethercote71980f02004-01-24 18:18:54 +0000438
439 // Map shadow memory.
440 // Initially all inaccessible, incrementally initialized as it is used
nethercotee567e702004-07-10 17:49:17 +0000441 if (shadow_size != 0) {
442 vres = mmap((char *)VG_(shadow_base), shadow_size, PROT_NONE,
fitzhardinge72ddff62004-09-08 20:03:51 +0000443 MAP_PRIVATE|MAP_ANON|MAP_FIXED|MAP_NORESERVE, -1, 0);
nethercoted4722622004-08-30 19:36:42 +0000444 if ((void*)-1 == vres) {
445 fprintf(stderr,
nethercote8c1ce432004-10-08 14:01:14 +0000446 "valgrind: Could not allocate address space (%p bytes)\n"
447 "valgrind: for shadow memory\n"
448 "valgrind: Possible causes:\n"
449 "valgrind: - For some systems (especially under RedHat 8), Valgrind\n"
450 "valgrind: needs at least 1.5GB swap space.\n"
451 "valgrind: - Or, your virtual memory size may be limited (check\n"
452 "valgrind: with 'ulimit -v').\n"
453 "valgrind: - Or, your system may use a kernel that provides only a\n"
454 "valgrind: too-small (eg. 2GB) user address space.\n"
455 , (void*)shadow_size
456 );
nethercoted4722622004-08-30 19:36:42 +0000457 exit(1);
458 }
nethercotee567e702004-07-10 17:49:17 +0000459 }
nethercote71980f02004-01-24 18:18:54 +0000460}
461
462/*====================================================================*/
463/*=== Command line setup ===*/
464/*====================================================================*/
465
466/* Nb: malloc'd memory never freed -- kept throughout like argv, envp */
467static char* get_file_clo(char* dir)
468{
469# define FLEN 512
470 Int fd, n;
471 struct stat s1;
472 char* f_clo = NULL;
473 char filename[FLEN];
474
475 snprintf(filename, FLEN, "%s/.valgrindrc", ( NULL == dir ? "" : dir ) );
476 fd = VG_(open)(filename, 0, VKI_S_IRUSR);
477 if ( fd > 0 ) {
478 if ( 0 == fstat(fd, &s1) ) {
479 f_clo = malloc(s1.st_size+1);
480 vg_assert(f_clo);
481 n = read(fd, f_clo, s1.st_size);
482 if (n == -1) n = 0;
483 f_clo[n] = '\0';
484 }
485 close(fd);
486 }
487 return f_clo;
488# undef FLEN
489}
490
nethercotee2097312004-06-27 12:29:56 +0000491#define ISSPACE(cc) ((cc) == ' ' || (cc) == '\t' || (cc) == '\n')
492
nethercote71980f02004-01-24 18:18:54 +0000493static Int count_args(char* s)
494{
495 Int n = 0;
496 if (s) {
497 char* cp = s;
498 while (True) {
499 // We have alternating sequences: blanks, non-blanks, blanks...
500 // count the non-blanks sequences.
501 while ( ISSPACE(*cp) ) cp++;
502 if ( !*cp ) break;
503 n++;
504 while ( !ISSPACE(*cp) && *cp ) cp++;
505 }
506 }
507 return n;
508}
509
510/* add args out of environment, skipping multiple spaces and -- args */
511static char** copy_args( char* s, char** to )
512{
513 if (s) {
514 char* cp = s;
515 while (True) {
516 // We have alternating sequences: blanks, non-blanks, blanks...
517 // copy the non-blanks sequences, and add terminating '\0'
518 while ( ISSPACE(*cp) ) cp++;
519 if ( !*cp ) break;
520 *to++ = cp;
521 while ( !ISSPACE(*cp) && *cp ) cp++;
522 if ( *cp ) *cp++ = '\0'; // terminate if necessary
523 if (VG_STREQ(to[-1], "--")) to--; // undo any '--' arg
524 }
525 }
526 return to;
527}
528
nethercotee2097312004-06-27 12:29:56 +0000529#undef ISSPACE
530
nethercote71980f02004-01-24 18:18:54 +0000531// Augment command line with arguments from environment and .valgrindrc
532// files.
533static void augment_command_line(Int* vg_argc_inout, char*** vg_argv_inout)
534{
nethercotef6a1d502004-08-09 12:21:57 +0000535 int vg_argc0 = *vg_argc_inout;
536 char** vg_argv0 = *vg_argv_inout;
nethercote71980f02004-01-24 18:18:54 +0000537
538 char* env_clo = getenv(VALGRINDOPTS);
539 char* f1_clo = get_file_clo( getenv("HOME") );
540 char* f2_clo = get_file_clo(".");
541
542 /* copy any extra args from file or environment, if present */
543 if ( (env_clo && *env_clo) || (f1_clo && *f1_clo) || (f2_clo && *f2_clo) ) {
544 /* ' ' separated extra options */
545 char **from;
546 char **to;
thughescaca0022004-09-13 10:20:34 +0000547 int orig_arg_count, env_arg_count, f1_arg_count, f2_arg_count;
548
549 for ( orig_arg_count = 0; vg_argv0[orig_arg_count]; orig_arg_count++ );
550
nethercote71980f02004-01-24 18:18:54 +0000551 env_arg_count = count_args(env_clo);
552 f1_arg_count = count_args(f1_clo);
553 f2_arg_count = count_args(f2_clo);
554
555 if (0)
556 printf("extra-argc=%d %d %d\n",
557 env_arg_count, f1_arg_count, f2_arg_count);
558
559 /* +2: +1 for null-termination, +1 for added '--' */
nethercotef6a1d502004-08-09 12:21:57 +0000560 from = vg_argv0;
thughescaca0022004-09-13 10:20:34 +0000561 vg_argv0 = malloc( (orig_arg_count + env_arg_count + f1_arg_count
nethercote71980f02004-01-24 18:18:54 +0000562 + f2_arg_count + 2) * sizeof(char **));
nethercotef6a1d502004-08-09 12:21:57 +0000563 vg_assert(vg_argv0);
564 to = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000565
566 /* copy argv[0] */
567 *to++ = *from++;
568
569 /* Copy extra args from env var and file, in the order: ~/.valgrindrc,
570 * $VALGRIND_OPTS, ./.valgrindrc -- more local options are put later
571 * to override less local ones. */
572 to = copy_args(f1_clo, to);
573 to = copy_args(env_clo, to);
574 to = copy_args(f2_clo, to);
575
576 /* copy original arguments, stopping at command or -- */
577 while (*from) {
578 if (**from != '-')
579 break;
580 if (VG_STREQ(*from, "--")) {
581 from++; /* skip -- */
582 break;
583 }
584 *to++ = *from++;
585 }
586
587 /* add -- */
588 *to++ = "--";
589
nethercotef6a1d502004-08-09 12:21:57 +0000590 vg_argc0 = to - vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000591
592 /* copy rest of original command line, then NULL */
593 while (*from) *to++ = *from++;
594 *to = NULL;
595 }
596
nethercotef6a1d502004-08-09 12:21:57 +0000597 *vg_argc_inout = vg_argc0;
598 *vg_argv_inout = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000599}
600
nethercotef6a1d502004-08-09 12:21:57 +0000601#define VG_CLO_SEP '\01'
602
nethercote71980f02004-01-24 18:18:54 +0000603static void get_command_line( int argc, char** argv,
604 Int* vg_argc_out, Char*** vg_argv_out,
605 char*** cl_argv_out )
606{
nethercotef6a1d502004-08-09 12:21:57 +0000607 int vg_argc0;
608 char** vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000609 char** cl_argv;
610 char* env_clo = getenv(VALGRINDCLO);
611
612 if (env_clo != NULL && *env_clo != '\0') {
613 char *cp;
614 char **cpp;
615
nethercotef6a1d502004-08-09 12:21:57 +0000616 /* OK, VALGRINDCLO is set, which means we must be a child of another
617 Valgrind process using --trace-children, so we're getting all our
618 arguments from VALGRINDCLO, and the entire command line belongs to
619 the client (including argv[0]) */
620 vg_argc0 = 1; /* argv[0] */
nethercote71980f02004-01-24 18:18:54 +0000621 for (cp = env_clo; *cp; cp++)
nethercotef6a1d502004-08-09 12:21:57 +0000622 if (*cp == VG_CLO_SEP)
623 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000624
nethercotef6a1d502004-08-09 12:21:57 +0000625 vg_argv0 = malloc(sizeof(char **) * (vg_argc0 + 1));
626 vg_assert(vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000627
nethercotef6a1d502004-08-09 12:21:57 +0000628 cpp = vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000629
630 *cpp++ = "valgrind"; /* nominal argv[0] */
631 *cpp++ = env_clo;
632
nethercotef6a1d502004-08-09 12:21:57 +0000633 // Replace the VG_CLO_SEP args separator with '\0'
nethercote71980f02004-01-24 18:18:54 +0000634 for (cp = env_clo; *cp; cp++) {
nethercotef6a1d502004-08-09 12:21:57 +0000635 if (*cp == VG_CLO_SEP) {
nethercote71980f02004-01-24 18:18:54 +0000636 *cp++ = '\0'; /* chop it up in place */
637 *cpp++ = cp;
638 }
639 }
640 *cpp = NULL;
641 cl_argv = argv;
642
643 } else {
644 /* Count the arguments on the command line. */
nethercotef6a1d502004-08-09 12:21:57 +0000645 vg_argv0 = argv;
nethercote71980f02004-01-24 18:18:54 +0000646
nethercotef6a1d502004-08-09 12:21:57 +0000647 for (vg_argc0 = 1; vg_argc0 < argc; vg_argc0++) {
648 if (argv[vg_argc0][0] != '-') /* exe name */
nethercote71980f02004-01-24 18:18:54 +0000649 break;
nethercotef6a1d502004-08-09 12:21:57 +0000650 if (VG_STREQ(argv[vg_argc0], "--")) { /* dummy arg */
651 vg_argc0++;
nethercote71980f02004-01-24 18:18:54 +0000652 break;
653 }
654 }
nethercotef6a1d502004-08-09 12:21:57 +0000655 cl_argv = &argv[vg_argc0];
nethercote71980f02004-01-24 18:18:54 +0000656
657 /* Get extra args from VALGRIND_OPTS and .valgrindrc files.
nethercotef6a1d502004-08-09 12:21:57 +0000658 Note we don't do this if getting args from VALGRINDCLO, as
659 those extra args will already be present in VALGRINDCLO. */
660 augment_command_line(&vg_argc0, &vg_argv0);
nethercote71980f02004-01-24 18:18:54 +0000661 }
662
663 if (0) {
664 Int i;
nethercotef6a1d502004-08-09 12:21:57 +0000665 for (i = 0; i < vg_argc0; i++)
666 printf("vg_argv0[%d]=\"%s\"\n", i, vg_argv0[i]);
nethercote71980f02004-01-24 18:18:54 +0000667 }
668
nethercotef6a1d502004-08-09 12:21:57 +0000669 *vg_argc_out = vg_argc0;
670 *vg_argv_out = (Char**)vg_argv0;
nethercote71980f02004-01-24 18:18:54 +0000671 *cl_argv_out = cl_argv;
672}
673
674
675/*====================================================================*/
676/*=== Environment and stack setup ===*/
677/*====================================================================*/
678
679/* Scan a colon-separated list, and call a function on each element.
680 The string must be mutable, because we insert a temporary '\0', but
thughes4ad52d02004-06-27 17:37:21 +0000681 the string will end up unmodified. (*func) should return True if it
nethercote71980f02004-01-24 18:18:54 +0000682 doesn't need to see any more.
thughes4ad52d02004-06-27 17:37:21 +0000683
684 This routine will return True if (*func) returns True and False if
685 it reaches the end of the list without that happening.
nethercote71980f02004-01-24 18:18:54 +0000686*/
thughes4ad52d02004-06-27 17:37:21 +0000687static Bool scan_colsep(char *colsep, Bool (*func)(const char *))
nethercote71980f02004-01-24 18:18:54 +0000688{
689 char *cp, *entry;
690 int end;
691
692 if (colsep == NULL ||
693 *colsep == '\0')
thughes4ad52d02004-06-27 17:37:21 +0000694 return False;
nethercote71980f02004-01-24 18:18:54 +0000695
696 entry = cp = colsep;
697
698 do {
699 end = (*cp == '\0');
700
701 if (*cp == ':' || *cp == '\0') {
702 char save = *cp;
703
704 *cp = '\0';
thughes21942d92004-07-12 09:35:37 +0000705 if ((*func)(entry)) {
706 *cp = save;
thughes4ad52d02004-06-27 17:37:21 +0000707 return True;
thughes21942d92004-07-12 09:35:37 +0000708 }
nethercote71980f02004-01-24 18:18:54 +0000709 *cp = save;
710 entry = cp+1;
711 }
712 cp++;
713 } while(!end);
thughes4ad52d02004-06-27 17:37:21 +0000714
715 return False;
716}
717
718static Bool contains(const char *p) {
719 if (VG_STREQ(p, VG_(libdir))) {
720 return True;
721 }
722 return False;
nethercote71980f02004-01-24 18:18:54 +0000723}
724
725/* Prepare the client's environment. This is basically a copy of our
726 environment, except:
727 1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
728 2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
729
730 If any of these is missing, then it is added.
731
732 Yummy. String hacking in C.
733
734 If this needs to handle any more variables it should be hacked
735 into something table driven.
736 */
737static char **fix_environment(char **origenv, const char *preload)
738{
739 static const char inject_so[] = "vg_inject.so";
740 static const char ld_library_path[] = "LD_LIBRARY_PATH=";
741 static const char ld_preload[] = "LD_PRELOAD=";
742 static const char valgrind_clo[] = VALGRINDCLO "=";
743 static const int ld_library_path_len = sizeof(ld_library_path)-1;
744 static const int ld_preload_len = sizeof(ld_preload)-1;
745 static const int valgrind_clo_len = sizeof(valgrind_clo)-1;
746 int ld_preload_done = 0;
747 int ld_library_path_done = 0;
748 char *inject_path;
749 int inject_path_len;
750 int vgliblen = strlen(VG_(libdir));
751 char **cpp;
752 char **ret;
753 int envc;
754 const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
755
756 /* Find the vg_inject.so; also make room for the tool preload
757 library */
758 inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
759 inject_path = malloc(inject_path_len);
nethercote7c018f42004-07-17 16:40:50 +0000760 vg_assert(inject_path);
nethercote71980f02004-01-24 18:18:54 +0000761
762 if (preload)
763 snprintf(inject_path, inject_path_len, "%s/%s:%s",
764 VG_(libdir), inject_so, preload);
765 else
766 snprintf(inject_path, inject_path_len, "%s/%s",
767 VG_(libdir), inject_so);
768
769 /* Count the original size of the env */
770 envc = 0; /* trailing NULL */
771 for (cpp = origenv; cpp && *cpp; cpp++)
772 envc++;
773
774 /* Allocate a new space */
775 ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
nethercote7c018f42004-07-17 16:40:50 +0000776 vg_assert(ret);
nethercote71980f02004-01-24 18:18:54 +0000777
778 /* copy it over */
779 for (cpp = ret; *origenv; )
780 *cpp++ = *origenv++;
781 *cpp = NULL;
782
783 vg_assert(envc == (cpp - ret));
784
785 /* Walk over the new environment, mashing as we go */
786 for (cpp = ret; cpp && *cpp; cpp++) {
787 if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
nethercote71980f02004-01-24 18:18:54 +0000788 /* If the LD_LIBRARY_PATH already contains libdir, then don't
789 bother adding it again, even if it isn't the first (it
790 seems that the Java runtime will keep reexecing itself
791 unless its paths are at the front of LD_LIBRARY_PATH) */
thughes4ad52d02004-06-27 17:37:21 +0000792 if (!scan_colsep(*cpp + ld_library_path_len, contains)) {
nethercote71980f02004-01-24 18:18:54 +0000793 int len = strlen(*cpp) + vgliblen*2 + 16;
794 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000795 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000796
797 snprintf(cp, len, "%s%s:%s",
798 ld_library_path, VG_(libdir),
799 (*cpp)+ld_library_path_len);
800
801 *cpp = cp;
802 }
803
804 ld_library_path_done = 1;
805 } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
806 int len = strlen(*cpp) + inject_path_len;
807 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000808 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000809
810 snprintf(cp, len, "%s%s:%s",
811 ld_preload, inject_path, (*cpp)+ld_preload_len);
812
813 *cpp = cp;
814
815 ld_preload_done = 1;
816 } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
817 *cpp = "";
818 }
819 }
820
821 /* Add the missing bits */
822
823 if (!ld_library_path_done) {
824 int len = ld_library_path_len + vgliblen*2 + 16;
825 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000826 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000827
828 snprintf(cp, len, "%s%s", ld_library_path, VG_(libdir));
829
830 ret[envc++] = cp;
831 }
832
833 if (!ld_preload_done) {
834 int len = ld_preload_len + inject_path_len;
835 char *cp = malloc(len);
nethercote7c018f42004-07-17 16:40:50 +0000836 vg_assert(cp);
nethercote71980f02004-01-24 18:18:54 +0000837
838 snprintf(cp, len, "%s%s",
839 ld_preload, inject_path);
840
841 ret[envc++] = cp;
842 }
843
844 ret[envc] = NULL;
845
846 return ret;
847}
848
849extern char **environ; /* our environment */
850//#include <error.h>
851
852/* Add a string onto the string table, and return its address */
853static char *copy_str(char **tab, const char *str)
854{
855 char *cp = *tab;
856 char *orig = cp;
857
858 while(*str)
859 *cp++ = *str++;
860 *cp++ = '\0';
861
862 if (0)
nethercote545fe672004-11-01 16:52:43 +0000863 printf("copied %p \"%s\" len %lld\n", orig, orig, (Long)(cp-orig));
nethercote71980f02004-01-24 18:18:54 +0000864
865 *tab = cp;
866
867 return orig;
868}
869
870/*
871 This sets up the client's initial stack, containing the args,
872 environment and aux vector.
873
874 The format of the stack is:
875
876 higher address +-----------------+
877 | Trampoline code |
878 +-----------------+
879 | |
880 : string table :
881 | |
882 +-----------------+
883 | AT_NULL |
884 - -
885 | auxv |
886 +-----------------+
887 | NULL |
888 - -
889 | envp |
890 +-----------------+
891 | NULL |
892 - -
893 | argv |
894 +-----------------+
895 | argc |
nethercote4ad74312004-10-26 09:59:49 +0000896 lower address +-----------------+ <- sp
nethercote71980f02004-01-24 18:18:54 +0000897 | undefined |
898 : :
899 */
nethercotec25c4492004-10-18 11:52:17 +0000900static Addr setup_client_stack(void* init_sp,
901 char **orig_argv, char **orig_envp,
nethercote71980f02004-01-24 18:18:54 +0000902 const struct exeinfo *info,
903 UInt** client_auxv)
904{
nethercotee567e702004-07-10 17:49:17 +0000905 void* res;
nethercote71980f02004-01-24 18:18:54 +0000906 char **cpp;
907 char *strtab; /* string table */
908 char *stringbase;
nethercotea3c3cf22004-11-01 18:38:00 +0000909 Addr *ptr;
nethercote71980f02004-01-24 18:18:54 +0000910 struct ume_auxv *auxv;
911 const struct ume_auxv *orig_auxv;
912 const struct ume_auxv *cauxv;
913 unsigned stringsize; /* total size of strings in bytes */
914 unsigned auxsize; /* total size of auxv in bytes */
915 int argc; /* total argc */
916 int envc; /* total number of env vars */
917 unsigned stacksize; /* total client stack size */
nethercotea3c3cf22004-11-01 18:38:00 +0000918 Addr cl_esp; /* client stack base (initial esp) */
nethercote71980f02004-01-24 18:18:54 +0000919
920 /* use our own auxv as a prototype */
nethercotec25c4492004-10-18 11:52:17 +0000921 orig_auxv = find_auxv(init_sp);
nethercote71980f02004-01-24 18:18:54 +0000922
923 /* ==================== compute sizes ==================== */
924
925 /* first of all, work out how big the client stack will be */
926 stringsize = 0;
927
928 /* paste on the extra args if the loader needs them (ie, the #!
929 interpreter and its argument) */
930 argc = 0;
nethercoted6a56872004-07-26 15:32:47 +0000931 if (info->interp_name != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000932 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000933 stringsize += strlen(info->interp_name) + 1;
nethercote71980f02004-01-24 18:18:54 +0000934 }
nethercoted6a56872004-07-26 15:32:47 +0000935 if (info->interp_args != NULL) {
nethercote71980f02004-01-24 18:18:54 +0000936 argc++;
nethercoted6a56872004-07-26 15:32:47 +0000937 stringsize += strlen(info->interp_args) + 1;
nethercote71980f02004-01-24 18:18:54 +0000938 }
939
940 /* now scan the args we're given... */
941 for (cpp = orig_argv; *cpp; cpp++) {
942 argc++;
943 stringsize += strlen(*cpp) + 1;
944 }
945
946 /* ...and the environment */
947 envc = 0;
948 for (cpp = orig_envp; cpp && *cpp; cpp++) {
949 envc++;
950 stringsize += strlen(*cpp) + 1;
951 }
952
953 /* now, how big is the auxv? */
954 auxsize = sizeof(*auxv); /* there's always at least one entry: AT_NULL */
955 for (cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
956 if (cauxv->a_type == AT_PLATFORM)
957 stringsize += strlen(cauxv->u.a_ptr) + 1;
958 auxsize += sizeof(*cauxv);
959 }
960
961 /* OK, now we know how big the client stack is */
962 stacksize =
963 sizeof(int) + /* argc */
964 sizeof(char **)*argc + /* argv */
965 sizeof(char **) + /* terminal NULL */
966 sizeof(char **)*envc + /* envp */
967 sizeof(char **) + /* terminal NULL */
968 auxsize + /* auxv */
969 ROUNDUP(stringsize, sizeof(int)) +/* strings (aligned) */
nethercote5fd72bb2004-11-04 19:28:38 +0000970 VKI_PAGE_SIZE; /* page for trampoline code */
nethercote71980f02004-01-24 18:18:54 +0000971
sewardj79048ce2005-02-18 08:28:32 +0000972 if (0) VG_(printf)("stacksize = %d\n", stacksize);
973
nethercotef84f6952004-07-15 14:58:33 +0000974 // decide where stack goes!
975 VG_(clstk_end) = VG_(client_end);
976
nethercote73b526f2004-10-31 18:48:21 +0000977 VG_(client_trampoline_code) = VG_(clstk_end) - VKI_PAGE_SIZE;
nethercotef84f6952004-07-15 14:58:33 +0000978
nethercote71980f02004-01-24 18:18:54 +0000979 /* cl_esp is the client's stack pointer */
nethercotef84f6952004-07-15 14:58:33 +0000980 cl_esp = VG_(clstk_end) - stacksize;
nethercote71980f02004-01-24 18:18:54 +0000981 cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
982
nethercote71980f02004-01-24 18:18:54 +0000983 /* base of the string table (aligned) */
sewardj79048ce2005-02-18 08:28:32 +0000984 stringbase = strtab = (char *)(VG_(client_trampoline_code)
985 - ROUNDUP(stringsize, sizeof(int)));
nethercote71980f02004-01-24 18:18:54 +0000986
987 VG_(clstk_base) = PGROUNDDN(cl_esp);
nethercote71980f02004-01-24 18:18:54 +0000988
sewardj79048ce2005-02-18 08:28:32 +0000989 if (0)
nethercote5ee67ca2004-06-22 14:00:09 +0000990 printf("stringsize=%d auxsize=%d stacksize=%d\n"
nethercote6a27d832004-09-07 10:17:02 +0000991 "clstk_base %p\n"
992 "clstk_end %p\n",
993 stringsize, auxsize, stacksize,
994 (void*)VG_(clstk_base), (void*)VG_(clstk_end));
nethercote5ee67ca2004-06-22 14:00:09 +0000995
nethercote71980f02004-01-24 18:18:54 +0000996 /* ==================== allocate space ==================== */
997
998 /* allocate a stack - mmap enough space for the stack */
nethercotef84f6952004-07-15 14:58:33 +0000999 res = mmap((void *)PGROUNDDN(cl_esp), VG_(clstk_end) - PGROUNDDN(cl_esp),
nethercotee567e702004-07-10 17:49:17 +00001000 PROT_READ | PROT_WRITE | PROT_EXEC,
1001 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
1002 vg_assert((void*)-1 != res);
nethercote71980f02004-01-24 18:18:54 +00001003
1004 /* ==================== copy client stack ==================== */
1005
nethercotea3c3cf22004-11-01 18:38:00 +00001006 ptr = (Addr*)cl_esp;
nethercote71980f02004-01-24 18:18:54 +00001007
1008 /* --- argc --- */
1009 *ptr++ = argc; /* client argc */
1010
1011 /* --- argv --- */
nethercoted6a56872004-07-26 15:32:47 +00001012 if (info->interp_name) {
nethercotea3c3cf22004-11-01 18:38:00 +00001013 *ptr++ = (Addr)copy_str(&strtab, info->interp_name);
nethercoted6a56872004-07-26 15:32:47 +00001014 free(info->interp_name);
nethercote71980f02004-01-24 18:18:54 +00001015 }
nethercoted6a56872004-07-26 15:32:47 +00001016 if (info->interp_args) {
nethercotea3c3cf22004-11-01 18:38:00 +00001017 *ptr++ = (Addr)copy_str(&strtab, info->interp_args);
nethercoted6a56872004-07-26 15:32:47 +00001018 free(info->interp_args);
nethercote71980f02004-01-24 18:18:54 +00001019 }
1020 for (cpp = orig_argv; *cpp; ptr++, cpp++) {
nethercotea3c3cf22004-11-01 18:38:00 +00001021 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001022 }
1023 *ptr++ = 0;
1024
1025 /* --- envp --- */
1026 VG_(client_envp) = (Char **)ptr;
1027 for (cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
nethercotea3c3cf22004-11-01 18:38:00 +00001028 *ptr = (Addr)copy_str(&strtab, *cpp);
nethercote71980f02004-01-24 18:18:54 +00001029 *ptr++ = 0;
1030
1031 /* --- auxv --- */
1032 auxv = (struct ume_auxv *)ptr;
1033 *client_auxv = (UInt *)auxv;
1034
1035 for (; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
1036 /* copy the entry... */
1037 *auxv = *orig_auxv;
1038
1039 /* ...and fix up the copy */
1040 switch(auxv->a_type) {
1041 case AT_PHDR:
1042 if (info->phdr == 0)
1043 auxv->a_type = AT_IGNORE;
1044 else
1045 auxv->u.a_val = info->phdr;
1046 break;
1047
1048 case AT_PHNUM:
1049 if (info->phdr == 0)
1050 auxv->a_type = AT_IGNORE;
1051 else
1052 auxv->u.a_val = info->phnum;
1053 break;
1054
1055 case AT_BASE:
1056 if (info->interp_base == 0)
1057 auxv->a_type = AT_IGNORE;
1058 else
1059 auxv->u.a_val = info->interp_base;
1060 break;
1061
1062 case AT_PLATFORM: /* points to a platform description string */
1063 auxv->u.a_ptr = copy_str(&strtab, orig_auxv->u.a_ptr);
1064 break;
1065
1066 case AT_ENTRY:
1067 auxv->u.a_val = info->entry;
1068 break;
1069
1070 case AT_IGNORE:
1071 case AT_EXECFD:
1072 case AT_PHENT:
1073 case AT_PAGESZ:
1074 case AT_FLAGS:
1075 case AT_NOTELF:
1076 case AT_UID:
1077 case AT_EUID:
1078 case AT_GID:
1079 case AT_EGID:
1080 case AT_CLKTCK:
1081 case AT_HWCAP:
1082 case AT_FPUCW:
1083 case AT_DCACHEBSIZE:
1084 case AT_ICACHEBSIZE:
1085 case AT_UCACHEBSIZE:
1086 /* All these are pointerless, so we don't need to do anything
1087 about them. */
1088 break;
1089
1090 case AT_SECURE:
1091 /* If this is 1, then it means that this program is running
1092 suid, and therefore the dynamic linker should be careful
1093 about LD_PRELOAD, etc. However, since stage1 (the thing
1094 the kernel actually execve's) should never be SUID, and we
1095 need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
1096 set AT_SECURE to 0. */
1097 auxv->u.a_val = 0;
1098 break;
1099
1100 case AT_SYSINFO:
1101 /* Leave this unmolested for now, but we'll update it later
1102 when we set up the client trampoline code page */
1103 break;
1104
1105 case AT_SYSINFO_EHDR:
1106 /* Trash this, because we don't reproduce it */
1107 auxv->a_type = AT_IGNORE;
1108 break;
1109
1110 default:
1111 /* stomp out anything we don't know about */
1112 if (0)
nethercote545fe672004-11-01 16:52:43 +00001113 printf("stomping auxv entry %lld\n", (ULong)auxv->a_type);
nethercote71980f02004-01-24 18:18:54 +00001114 auxv->a_type = AT_IGNORE;
1115 break;
1116
1117 }
1118 }
1119 *auxv = *orig_auxv;
1120 vg_assert(auxv->a_type == AT_NULL);
1121
njnc6168192004-11-29 13:54:10 +00001122// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
1123// Perhaps a per-arch VGA_NEEDS_TRAMPOLINE constant is necessary?
njnca0518d2004-11-26 19:34:36 +00001124#ifdef __x86__
nethercotef84f6952004-07-15 14:58:33 +00001125 /* --- trampoline page --- */
1126 VG_(memcpy)( (void *)VG_(client_trampoline_code),
1127 &VG_(trampoline_code_start), VG_(trampoline_code_length) );
njnca0518d2004-11-26 19:34:36 +00001128#endif
nethercotef84f6952004-07-15 14:58:33 +00001129
nethercote71980f02004-01-24 18:18:54 +00001130 vg_assert((strtab-stringbase) == stringsize);
1131
nethercote5ee67ca2004-06-22 14:00:09 +00001132 /* We know the initial ESP is pointing at argc/argv */
1133 VG_(client_argc) = *(Int*)cl_esp;
sewardj45f02c42005-02-05 18:27:14 +00001134 VG_(client_argv) = (Char**)(cl_esp + sizeof(HWord));
nethercote5ee67ca2004-06-22 14:00:09 +00001135
sewardj79048ce2005-02-18 08:28:32 +00001136 if (0) VG_(printf)("startup SP = %p\n", cl_esp);
nethercote71980f02004-01-24 18:18:54 +00001137 return cl_esp;
1138}
1139
1140/*====================================================================*/
1141/*=== Find executable ===*/
1142/*====================================================================*/
1143
thughes4ad52d02004-06-27 17:37:21 +00001144static const char* executable_name;
1145
1146static Bool match_executable(const char *entry) {
1147 char buf[strlen(entry) + strlen(executable_name) + 2];
1148
1149 /* empty PATH element means . */
1150 if (*entry == '\0')
1151 entry = ".";
1152
1153 snprintf(buf, sizeof(buf), "%s/%s", entry, executable_name);
1154
1155 if (access(buf, R_OK|X_OK) == 0) {
1156 executable_name = strdup(buf);
1157 vg_assert(NULL != executable_name);
1158 return True;
1159 }
1160 return False;
1161}
1162
nethercote71980f02004-01-24 18:18:54 +00001163static const char* find_executable(const char* exec)
1164{
1165 vg_assert(NULL != exec);
thughes4ad52d02004-06-27 17:37:21 +00001166 executable_name = exec;
1167 if (strchr(executable_name, '/') == NULL) {
nethercote71980f02004-01-24 18:18:54 +00001168 /* no '/' - we need to search the path */
1169 char *path = getenv("PATH");
thughes4ad52d02004-06-27 17:37:21 +00001170 scan_colsep(path, match_executable);
nethercote71980f02004-01-24 18:18:54 +00001171 }
thughes4ad52d02004-06-27 17:37:21 +00001172 return executable_name;
nethercote71980f02004-01-24 18:18:54 +00001173}
1174
1175
1176/*====================================================================*/
1177/*=== Loading tools ===*/
1178/*====================================================================*/
1179
1180static void list_tools(void)
1181{
1182 DIR *dir = opendir(VG_(libdir));
1183 struct dirent *de;
1184 int first = 1;
1185
1186 if (dir == NULL) {
1187 fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
nethercotef4928da2004-06-15 10:54:40 +00001188 VG_(libdir), strerror(errno));
nethercote71980f02004-01-24 18:18:54 +00001189 return;
1190 }
1191
nethercotef4928da2004-06-15 10:54:40 +00001192 while ((de = readdir(dir)) != NULL) {
nethercote71980f02004-01-24 18:18:54 +00001193 int len = strlen(de->d_name);
1194
njn063c5402004-11-22 16:58:05 +00001195 /* look for vgtool_TOOL.so names */
1196 if (len > (7+1+3) && /* "vgtool_" + at least 1-char toolname + ".so" */
1197 strncmp(de->d_name, "vgtool_", 7) == 0 &&
nethercotef4928da2004-06-15 10:54:40 +00001198 VG_STREQ(de->d_name + len - 3, ".so")) {
1199 if (first) {
1200 fprintf(stderr, "Available tools:\n");
1201 first = 0;
1202 }
1203 de->d_name[len-3] = '\0';
1204 fprintf(stderr, "\t%s\n", de->d_name+7);
nethercote71980f02004-01-24 18:18:54 +00001205 }
1206 }
1207
1208 closedir(dir);
1209
1210 if (first)
nethercotef4928da2004-06-15 10:54:40 +00001211 fprintf(stderr, "No tools available in \"%s\" (installation problem?)\n",
1212 VG_(libdir));
nethercote71980f02004-01-24 18:18:54 +00001213}
1214
1215
1216/* Find and load a tool, and check it looks ok. Also looks to see if there's
1217 * a matching vgpreload_*.so file, and returns its name in *preloadpath. */
1218static void load_tool( const char *toolname, void** handle_out,
1219 ToolInfo** toolinfo_out, char **preloadpath_out )
1220{
1221 Bool ok;
1222 int len = strlen(VG_(libdir)) + strlen(toolname)*2 + 16;
1223 char buf[len];
1224 void* handle;
1225 ToolInfo* toolinfo;
1226 char* preloadpath = NULL;
1227 Int* vg_malloc_redzonep;
1228
1229 // XXX: allowing full paths for --tool option -- does it make sense?
1230 // Doesn't allow for vgpreload_<tool>.so.
1231
1232 if (strchr(toolname, '/') != 0) {
1233 /* toolname contains '/', and so must be a pathname */
1234 handle = dlopen(toolname, RTLD_NOW);
1235 } else {
1236 /* just try in the libdir */
njn063c5402004-11-22 16:58:05 +00001237 snprintf(buf, len, "%s/vgtool_%s.so", VG_(libdir), toolname);
nethercote71980f02004-01-24 18:18:54 +00001238 handle = dlopen(buf, RTLD_NOW);
1239
1240 if (handle != NULL) {
1241 snprintf(buf, len, "%s/vgpreload_%s.so", VG_(libdir), toolname);
1242 if (access(buf, R_OK) == 0) {
1243 preloadpath = strdup(buf);
1244 vg_assert(NULL != preloadpath);
1245 }
1246 }
1247 }
1248
1249 ok = (NULL != handle);
1250 if (!ok) {
1251 fprintf(stderr, "Can't open tool \"%s\": %s\n", toolname, dlerror());
1252 goto bad_load;
1253 }
1254
njn26f02512004-11-22 18:33:15 +00001255 toolinfo = dlsym(handle, "vgTool_tool_info");
nethercote71980f02004-01-24 18:18:54 +00001256 ok = (NULL != toolinfo);
1257 if (!ok) {
njn26f02512004-11-22 18:33:15 +00001258 fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
nethercote71980f02004-01-24 18:18:54 +00001259 "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
1260 goto bad_load;
1261 }
1262
1263 ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
1264 toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
njnd2252832004-11-26 10:53:33 +00001265 toolinfo->tl_pre_clo_init != NULL);
nethercote71980f02004-01-24 18:18:54 +00001266 if (!ok) {
1267 fprintf(stderr, "Error:\n"
1268 " Tool and core interface versions do not match.\n"
1269 " Interface version used by core is: %d.%d (size %d)\n"
1270 " Interface version used by tool is: %d.%d (size %d)\n"
1271 " The major version numbers must match.\n",
1272 VG_CORE_INTERFACE_MAJOR_VERSION,
1273 VG_CORE_INTERFACE_MINOR_VERSION,
nethercote545fe672004-11-01 16:52:43 +00001274 (Int)sizeof(*toolinfo),
nethercote71980f02004-01-24 18:18:54 +00001275 toolinfo->interface_major_version,
1276 toolinfo->interface_minor_version,
1277 toolinfo->sizeof_ToolInfo);
1278 fprintf(stderr, " You need to at least recompile, and possibly update,\n");
1279 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
nethercote996901a2004-08-03 13:29:09 +00001280 fprintf(stderr, " your tool to work with this version of Valgrind.\n");
nethercote71980f02004-01-24 18:18:54 +00001281 else
nethercote996901a2004-08-03 13:29:09 +00001282 fprintf(stderr, " your version of Valgrind to work with this tool.\n");
nethercote71980f02004-01-24 18:18:54 +00001283 goto bad_load;
1284 }
1285
1286 // Set redzone size for V's allocator
1287 vg_malloc_redzonep = dlsym(handle, STR(VG_(vg_malloc_redzone_szB)));
1288 if ( NULL != vg_malloc_redzonep ) {
1289 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
1290 }
1291
1292 vg_assert(NULL != handle && NULL != toolinfo);
1293 *handle_out = handle;
1294 *toolinfo_out = toolinfo;
1295 *preloadpath_out = preloadpath;
1296 return;
1297
1298
1299 bad_load:
1300 if (handle != NULL)
1301 dlclose(handle);
1302
nethercotef4928da2004-06-15 10:54:40 +00001303 fprintf(stderr, "valgrind: couldn't load tool\n");
nethercote71980f02004-01-24 18:18:54 +00001304 list_tools();
1305 exit(127);
1306}
1307
nethercotef4928da2004-06-15 10:54:40 +00001308
1309/*====================================================================*/
1310/*=== Command line errors ===*/
1311/*====================================================================*/
1312
1313static void abort_msg ( void )
1314{
nethercotef8548672004-06-21 12:42:35 +00001315 VG_(clo_log_to) = VgLogTo_Fd;
1316 VG_(clo_log_fd) = 2; /* stderr */
nethercotef4928da2004-06-15 10:54:40 +00001317}
1318
1319void VG_(bad_option) ( Char* opt )
1320{
1321 abort_msg();
1322 VG_(printf)("valgrind: Bad option `%s'; aborting.\n", opt);
1323 VG_(printf)("valgrind: Use --help for more information.\n");
1324 VG_(exit)(1);
1325}
1326
1327static void missing_tool_option ( void )
1328{
1329 abort_msg();
1330 VG_(printf)("valgrind: Missing --tool option\n");
1331 list_tools();
1332 VG_(printf)("valgrind: Use --help for more information.\n");
1333 VG_(exit)(1);
1334}
1335
1336static void missing_prog ( void )
1337{
1338 abort_msg();
1339 VG_(printf)("valgrind: no program specified\n");
1340 VG_(printf)("valgrind: Use --help for more information.\n");
1341 VG_(exit)(1);
1342}
1343
1344static void config_error ( Char* msg )
1345{
1346 abort_msg();
1347 VG_(printf)("valgrind: Startup or configuration error:\n %s\n", msg);
1348 VG_(printf)("valgrind: Unable to start up properly. Giving up.\n");
1349 VG_(exit)(1);
1350}
1351
1352
nethercote71980f02004-01-24 18:18:54 +00001353/*====================================================================*/
1354/*=== Loading the client ===*/
1355/*====================================================================*/
1356
nethercotef4928da2004-06-15 10:54:40 +00001357static void load_client(char* cl_argv[], const char* exec, Int need_help,
nethercote71980f02004-01-24 18:18:54 +00001358 /*out*/struct exeinfo* info, /*out*/Addr* client_eip)
1359{
1360 // If they didn't specify an executable with --exec, and didn't specify
1361 // --help, then use client argv[0] (searching $PATH if necessary).
nethercotef4928da2004-06-15 10:54:40 +00001362 if (NULL == exec && !need_help) {
nethercote71980f02004-01-24 18:18:54 +00001363 if (cl_argv[0] == NULL ||
1364 ( NULL == (exec = find_executable(cl_argv[0])) ) )
1365 {
nethercotef4928da2004-06-15 10:54:40 +00001366 missing_prog();
nethercote71980f02004-01-24 18:18:54 +00001367 }
1368 }
1369
1370 info->map_base = VG_(client_mapbase);
nethercote71980f02004-01-24 18:18:54 +00001371 info->exe_base = VG_(client_base);
1372 info->exe_end = VG_(client_end);
1373 info->argv = cl_argv;
1374
nethercotef4928da2004-06-15 10:54:40 +00001375 if (need_help) {
nethercote71980f02004-01-24 18:18:54 +00001376 VG_(clexecfd) = -1;
njnc8c93282004-11-29 16:05:54 +00001377 // Totally zero 'info' before continuing.
1378 VG_(memset)(info, 0, sizeof(*info));
nethercote71980f02004-01-24 18:18:54 +00001379 } else {
1380 Int ret;
nethercote4ec0af42004-10-16 15:31:49 +00001381 VG_(clexecfd) = VG_(open)(exec, VKI_O_RDONLY, VKI_S_IRUSR);
nethercote71980f02004-01-24 18:18:54 +00001382 ret = do_exec(exec, info);
1383 if (ret != 0) {
nethercoteea147e72004-07-26 15:43:57 +00001384 fprintf(stderr, "valgrind: do_exec(%s) failed: %s\n",
1385 exec, strerror(ret));
nethercote71980f02004-01-24 18:18:54 +00001386 exit(127);
1387 }
1388 }
1389
1390 /* Copy necessary bits of 'info' that were filled in */
1391 *client_eip = info->init_eip;
1392 VG_(brk_base) = VG_(brk_limit) = info->brkbase;
1393}
1394
nethercote969ecf12004-10-13 17:29:01 +00001395/*====================================================================*/
1396/*=== Address space unpadding ===*/
1397/*====================================================================*/
1398
1399typedef struct {
1400 char* killpad_start;
1401 char* killpad_end;
1402 struct stat* killpad_padstat;
1403} killpad_extra;
1404
1405static int killpad(char *segstart, char *segend, const char *perm, off_t off,
1406 int maj, int min, int ino, void* ex)
1407{
1408 killpad_extra* extra = ex;
1409 void *b, *e;
1410 int res;
1411
1412 vg_assert(NULL != extra->killpad_padstat);
1413
1414 if (extra->killpad_padstat->st_dev != makedev(maj, min) ||
1415 extra->killpad_padstat->st_ino != ino)
1416 return 1;
1417
1418 if (segend <= extra->killpad_start || segstart >= extra->killpad_end)
1419 return 1;
1420
1421 if (segstart <= extra->killpad_start)
1422 b = extra->killpad_start;
1423 else
1424 b = segstart;
1425
1426 if (segend >= extra->killpad_end)
1427 e = extra->killpad_end;
1428 else
1429 e = segend;
1430
1431 res = munmap(b, (char *)e-(char *)b);
1432 vg_assert(0 == res);
1433
1434 return 1;
1435}
1436
1437// Remove padding of 'padfile' from a range of address space.
1438void as_unpad(void *start, void *end, int padfile)
1439{
1440 static struct stat padstat;
1441 killpad_extra extra;
1442 int res;
1443
1444 vg_assert(padfile > 0);
1445
1446 res = fstat(padfile, &padstat);
1447 vg_assert(0 == res);
1448 extra.killpad_padstat = &padstat;
1449 extra.killpad_start = start;
1450 extra.killpad_end = end;
1451 foreach_map(killpad, &extra);
1452}
1453
1454void as_closepadfile(int padfile)
1455{
1456 int res = close(padfile);
1457 vg_assert(0 == res);
1458}
1459
nethercote71980f02004-01-24 18:18:54 +00001460
1461/*====================================================================*/
nethercotef6a1d502004-08-09 12:21:57 +00001462/*=== Command-line: variables, processing, etc ===*/
nethercote71980f02004-01-24 18:18:54 +00001463/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00001464
njn25e49d8e72002-09-23 09:36:25 +00001465/* Define, and set defaults. */
sewardj8b635a42004-11-22 19:01:47 +00001466VexControl VG_(clo_vex_control);
njn25e49d8e72002-09-23 09:36:25 +00001467Bool VG_(clo_error_limit) = True;
nethercote04d0fbc2004-01-26 16:48:06 +00001468Bool VG_(clo_db_attach) = False;
1469Char* VG_(clo_db_command) = VG_CLO_DEFAULT_DBCOMMAND;
sewardjd153fae2005-01-10 17:24:47 +00001470Int VG_(clo_gen_suppressions) = 0;
nethercote27fec902004-06-16 21:26:32 +00001471Int VG_(clo_sanity_level) = 1;
njn25e49d8e72002-09-23 09:36:25 +00001472Int VG_(clo_verbosity) = 1;
1473Bool VG_(clo_demangle) = True;
njn25e49d8e72002-09-23 09:36:25 +00001474Bool VG_(clo_trace_children) = False;
sewardj4cf05692002-10-27 20:28:29 +00001475
nethercotef1e5e152004-09-01 23:58:16 +00001476/* See big comment in core.h for meaning of these three.
nethercotee1730692003-11-20 10:38:07 +00001477 fd is initially stdout, for --help, but gets moved to stderr by default
1478 immediately afterwards. */
sewardj4cf05692002-10-27 20:28:29 +00001479VgLogTo VG_(clo_log_to) = VgLogTo_Fd;
nethercotef8548672004-06-21 12:42:35 +00001480Int VG_(clo_log_fd) = 1;
1481Char* VG_(clo_log_name) = NULL;
sewardj4cf05692002-10-27 20:28:29 +00001482
thughes6233a382004-08-21 11:10:44 +00001483Bool VG_(clo_time_stamp) = False;
1484
sewardj6024b212003-07-13 10:54:33 +00001485Int VG_(clo_input_fd) = 0; /* stdin */
njn25e49d8e72002-09-23 09:36:25 +00001486Int VG_(clo_n_suppressions) = 0;
sewardjde4a1d02002-03-22 01:27:54 +00001487Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES];
njn25e49d8e72002-09-23 09:36:25 +00001488Bool VG_(clo_profile) = False;
sewardjfa8ec112005-01-19 11:55:34 +00001489UChar VG_(clo_trace_flags) = 0; // 00000000b
1490UChar VG_(clo_profile_flags) = 0; // 00000000b
sewardjc771b292004-11-30 18:55:21 +00001491Int VG_(clo_trace_notbelow) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001492Bool VG_(clo_trace_syscalls) = False;
1493Bool VG_(clo_trace_signals) = False;
1494Bool VG_(clo_trace_symtab) = False;
njn25e49d8e72002-09-23 09:36:25 +00001495Bool VG_(clo_trace_sched) = False;
1496Int VG_(clo_trace_pthread_level) = 0;
njn25e49d8e72002-09-23 09:36:25 +00001497Int VG_(clo_dump_error) = 0;
1498Int VG_(clo_backtrace_size) = 4;
1499Char* VG_(clo_weird_hacks) = NULL;
sewardj858964b2002-10-05 14:15:43 +00001500Bool VG_(clo_run_libc_freeres) = True;
rjwalshf5f536f2003-11-17 17:45:00 +00001501Bool VG_(clo_track_fds) = False;
nethercote77eba602003-11-13 17:35:04 +00001502Bool VG_(clo_show_below_main) = False;
fitzhardinge98abfc72003-12-16 02:05:15 +00001503Bool VG_(clo_pointercheck) = True;
sewardj062f3552005-01-06 16:13:40 +00001504Bool VG_(clo_support_elan3) = False;
fitzhardinge462f4f92003-12-18 02:10:54 +00001505Bool VG_(clo_branchpred) = False;
sewardj2370f3b2002-11-30 15:01:01 +00001506
jsgf855d93d2003-10-13 22:26:55 +00001507static Bool VG_(clo_wait_for_gdb) = False;
1508
1509/* If we're doing signal routing, poll for signals every 50mS by
1510 default. */
1511Int VG_(clo_signal_polltime) = 50;
1512
1513/* These flags reduce thread wakeup latency on syscall completion and
1514 signal delivery, respectively. The downside is possible unfairness. */
1515Bool VG_(clo_lowlat_syscalls) = False; /* low-latency syscalls */
1516Bool VG_(clo_lowlat_signals) = False; /* low-latency signals */
1517
sewardjde4a1d02002-03-22 01:27:54 +00001518
nethercote6c999f22004-01-31 22:55:15 +00001519void usage ( Bool debug_help )
njn7cf0bd32002-06-08 13:36:03 +00001520{
njn25e49d8e72002-09-23 09:36:25 +00001521 Char* usage1 =
nethercote71980f02004-01-24 18:18:54 +00001522"usage: valgrind --tool=<toolname> [options] prog-and-args\n"
njn25e49d8e72002-09-23 09:36:25 +00001523"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001524" common user options for all Valgrind tools, with defaults in [ ]:\n"
nethercote0d588502004-06-21 13:27:11 +00001525" --tool=<name> use the Valgrind tool named <name>\n"
nethercotea76368b2004-06-16 11:56:29 +00001526" -h --help show this message\n"
nethercote6c999f22004-01-31 22:55:15 +00001527" --help-debug show this message, plus debugging options\n"
njn25e49d8e72002-09-23 09:36:25 +00001528" --version show version\n"
njn25e49d8e72002-09-23 09:36:25 +00001529" -q --quiet run silently; only print error msgs\n"
1530" -v --verbose be more verbose, incl counts of errors\n"
nethercote77eba602003-11-13 17:35:04 +00001531" --trace-children=no|yes Valgrind-ise child processes? [no]\n"
nethercote0d588502004-06-21 13:27:11 +00001532" --track-fds=no|yes track open file descriptors? [no]\n"
thughes6233a382004-08-21 11:10:44 +00001533" --time-stamp=no|yes add timestamps to log messages? [no]\n"
nethercote2b0793f2003-12-02 10:41:18 +00001534"\n"
1535" uncommon user options for all Valgrind tools:\n"
nethercote0d588502004-06-21 13:27:11 +00001536" --run-libc-freeres=no|yes free up glibc memory at exit? [yes]\n"
1537" --weird-hacks=hack1,hack2,... recognised hacks: lax-ioctls [none]\n"
1538" --signal-polltime=<time> signal poll period (mS) for older kernels [50]\n"
1539" --lowlat-signals=no|yes improve thread signal wake-up latency [no]\n"
1540" --lowlat-syscalls=no|yes improve thread syscall wake-up latency [no]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001541" --pointercheck=no|yes enforce client address space limits [yes]\n"
sewardj062f3552005-01-06 16:13:40 +00001542" --support-elan3=no|yes hacks for Quadrics Elan3 support [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001543"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001544" user options for Valgrind tools that report errors:\n"
nethercotef8548672004-06-21 12:42:35 +00001545" --log-fd=<number> log messages to file descriptor [2=stderr]\n"
1546" --log-file=<file> log messages to <file>.pid<pid>\n"
sewardj603d4102005-01-11 14:01:02 +00001547" --log-file-exactly=<file> log messages to <file>\n"
nethercotef8548672004-06-21 12:42:35 +00001548" --log-socket=ipaddr:port log messages to socket ipaddr:port\n"
nethercote2b0793f2003-12-02 10:41:18 +00001549" --demangle=no|yes automatically demangle C++ names? [yes]\n"
1550" --num-callers=<number> show <num> callers in stack traces [4]\n"
1551" --error-limit=no|yes stop showing new errors if too many? [yes]\n"
1552" --show-below-main=no|yes continue stack traces below main() [no]\n"
1553" --suppressions=<filename> suppress errors described in <filename>\n"
sewardjd153fae2005-01-10 17:24:47 +00001554" --gen-suppressions=no|yes|all print suppressions for errors? [no]\n"
nethercote04d0fbc2004-01-26 16:48:06 +00001555" --db-attach=no|yes start debugger when errors detected? [no]\n"
1556" --db-command=<command> command to start debugger [gdb -nw %%f %%p]\n"
1557" --input-fd=<number> file descriptor for input [0=stdin]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001558"\n";
njn7cf0bd32002-06-08 13:36:03 +00001559
njn25e49d8e72002-09-23 09:36:25 +00001560 Char* usage2 =
1561"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001562" debugging options for all Valgrind tools:\n"
njn25e49d8e72002-09-23 09:36:25 +00001563" --sanity-level=<number> level of sanity checking to do [1]\n"
1564" --single-step=no|yes translate each instr separately? [no]\n"
1565" --optimise=no|yes improve intermediate code? [yes]\n"
nethercote137bc552003-11-14 17:47:54 +00001566" --profile=no|yes profile? (tool must be built for it) [no]\n"
fitzhardinge462f4f92003-12-18 02:10:54 +00001567" --branchpred=yes|no generate branch prediction hints [no]\n"
sewardjfa8ec112005-01-19 11:55:34 +00001568" --trace-flags=<XXXXXXXX> show generated code? (X = 0|1) [00000000]\n"
1569" --profile-flags=<XXXXXXXX> ditto, but for profiling (X = 0|1) [00000000]\n"
sewardjc771b292004-11-30 18:55:21 +00001570" --trace-notbelow=<number> only show BBs above <number> [0]\n"
njn25e49d8e72002-09-23 09:36:25 +00001571" --trace-syscalls=no|yes show all system calls? [no]\n"
1572" --trace-signals=no|yes show signal handling details? [no]\n"
1573" --trace-symtab=no|yes show symbol table details? [no]\n"
njn25e49d8e72002-09-23 09:36:25 +00001574" --trace-sched=no|yes show thread scheduler details? [no]\n"
njn3e884182003-04-15 13:03:23 +00001575" --trace-pthread=none|some|all show pthread event details? [none]\n"
jsgf855d93d2003-10-13 22:26:55 +00001576" --wait-for-gdb=yes|no pause on startup to wait for gdb attach\n"
njn25e49d8e72002-09-23 09:36:25 +00001577"\n"
sewardj8b635a42004-11-22 19:01:47 +00001578" --vex-iropt-verbosity 0 .. 9 [0]\n"
1579" --vex-iropt-level 0 .. 2 [2]\n"
1580" --vex-iropt-precise-memory-exns [no]\n"
1581" --vex-iropt-unroll-thresh 0 .. 400 [120]\n"
1582" --vex-guest-max-insns 1 .. 100 [50]\n"
1583" --vex-guest-chase-thresh 0 .. 99 [10]\n"
1584"\n"
sewardjfa8ec112005-01-19 11:55:34 +00001585" --trace-flags and --profile-flags values (omit the middle space):\n"
sewardj2a99cf62004-11-24 10:44:19 +00001586" 1000 0000 show conversion into IR\n"
1587" 0100 0000 show after initial opt\n"
1588" 0010 0000 show after instrumentation\n"
1589" 0001 0000 show after second opt\n"
1590" 0000 1000 show after tree building\n"
1591" 0000 0100 show selecting insns\n"
1592" 0000 0010 show after reg-alloc\n"
1593" 0000 0001 show final assembly\n"
1594"\n"
nethercote2b0793f2003-12-02 10:41:18 +00001595" debugging options for Valgrind tools that report errors\n"
1596" --dump-error=<number> show translation for basic block associated\n"
1597" with <number>'th error context [0=show none]\n"
fitzhardinge98abfc72003-12-16 02:05:15 +00001598"\n";
njn3e884182003-04-15 13:03:23 +00001599
1600 Char* usage3 =
1601"\n"
nethercote71980f02004-01-24 18:18:54 +00001602" Extra options read from ~/.valgrindrc, $VALGRIND_OPTS, ./.valgrindrc\n"
njn25e49d8e72002-09-23 09:36:25 +00001603"\n"
nethercote08fa9a72004-07-16 17:44:00 +00001604" Valgrind is Copyright (C) 2000-2004 Julian Seward et al.\n"
njn25e49d8e72002-09-23 09:36:25 +00001605" and licensed under the GNU General Public License, version 2.\n"
1606" Bug reports, feedback, admiration, abuse, etc, to: %s.\n"
njnd04b7c62002-10-03 14:05:52 +00001607"\n"
nethercote137bc552003-11-14 17:47:54 +00001608" Tools are copyright and licensed by their authors. See each\n"
1609" tool's start-up message for more information.\n"
njn25e49d8e72002-09-23 09:36:25 +00001610"\n";
njn7cf0bd32002-06-08 13:36:03 +00001611
fitzhardinge98abfc72003-12-16 02:05:15 +00001612 VG_(printf)(usage1);
1613 if (VG_(details).name) {
1614 VG_(printf)(" user options for %s:\n", VG_(details).name);
fitzhardinge98abfc72003-12-16 02:05:15 +00001615 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001616 TL_(print_usage)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001617 else
1618 VG_(printf)(" (none)\n");
1619 }
nethercote6c999f22004-01-31 22:55:15 +00001620 if (debug_help) {
1621 VG_(printf)(usage2);
fitzhardinge98abfc72003-12-16 02:05:15 +00001622
nethercote6c999f22004-01-31 22:55:15 +00001623 if (VG_(details).name) {
1624 VG_(printf)(" debugging options for %s:\n", VG_(details).name);
1625
1626 if (VG_(needs).command_line_options)
njn26f02512004-11-22 18:33:15 +00001627 TL_(print_debug_usage)();
nethercote6c999f22004-01-31 22:55:15 +00001628 else
1629 VG_(printf)(" (none)\n");
1630 }
fitzhardinge98abfc72003-12-16 02:05:15 +00001631 }
nethercote421281e2003-11-20 16:20:55 +00001632 VG_(printf)(usage3, VG_BUGS_TO);
nethercotef4928da2004-06-15 10:54:40 +00001633 VG_(exit)(0);
njn7cf0bd32002-06-08 13:36:03 +00001634}
sewardjde4a1d02002-03-22 01:27:54 +00001635
nethercote71980f02004-01-24 18:18:54 +00001636static void pre_process_cmd_line_options
nethercote6c999f22004-01-31 22:55:15 +00001637 ( Int* need_help, const char** tool, const char** exec )
sewardj1c1b1162003-02-23 01:25:51 +00001638{
nethercote71980f02004-01-24 18:18:54 +00001639 UInt i;
sewardjde4a1d02002-03-22 01:27:54 +00001640
sewardj8b635a42004-11-22 19:01:47 +00001641 LibVEX_default_VexControl(& VG_(clo_vex_control));
1642
nethercote71980f02004-01-24 18:18:54 +00001643 /* parse the options we have (only the options we care about now) */
nethercotef6a1d502004-08-09 12:21:57 +00001644 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001645
nethercotef6a1d502004-08-09 12:21:57 +00001646 if (strcmp(vg_argv[i], "--version") == 0) {
nethercote71980f02004-01-24 18:18:54 +00001647 printf("valgrind-" VERSION "\n");
nethercotef4928da2004-06-15 10:54:40 +00001648 exit(0);
nethercote71980f02004-01-24 18:18:54 +00001649
nethercotef6a1d502004-08-09 12:21:57 +00001650 } else if (VG_CLO_STREQ(vg_argv[i], "--help") ||
1651 VG_CLO_STREQ(vg_argv[i], "-h")) {
nethercote6c999f22004-01-31 22:55:15 +00001652 *need_help = 1;
1653
nethercotef6a1d502004-08-09 12:21:57 +00001654 } else if (VG_CLO_STREQ(vg_argv[i], "--help-debug")) {
nethercote6c999f22004-01-31 22:55:15 +00001655 *need_help = 2;
nethercote71980f02004-01-24 18:18:54 +00001656
nethercotef6c99d72004-11-09 14:35:43 +00001657 } else if (VG_CLO_STREQN(7, vg_argv[i], "--tool=")) {
nethercotef6a1d502004-08-09 12:21:57 +00001658 *tool = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001659
nethercotef6a1d502004-08-09 12:21:57 +00001660 } else if (VG_CLO_STREQN(7, vg_argv[i], "--exec=")) {
1661 *exec = &vg_argv[i][7];
nethercote71980f02004-01-24 18:18:54 +00001662 }
1663 }
1664
nethercotef4928da2004-06-15 10:54:40 +00001665 /* If no tool specified, can act appropriately without loading tool */
nethercote71980f02004-01-24 18:18:54 +00001666 if (*tool == NULL) {
nethercotef4928da2004-06-15 10:54:40 +00001667 if (0 == *need_help) {
1668 // neither --tool nor --help/--help-debug specified
1669 missing_tool_option();
1670 } else {
1671 // Give help message, without any tool-specific help
1672 usage(/*help-debug?*/2 == *need_help);
1673 }
nethercote71980f02004-01-24 18:18:54 +00001674 }
1675}
1676
nethercote5ee67ca2004-06-22 14:00:09 +00001677static void process_cmd_line_options( UInt* client_auxv, const char* toolname )
nethercote71980f02004-01-24 18:18:54 +00001678{
nethercotef8548672004-06-21 12:42:35 +00001679 Int i, eventually_log_fd;
nethercote71980f02004-01-24 18:18:54 +00001680 Int toolname_len = VG_(strlen)(toolname);
sewardjde4a1d02002-03-22 01:27:54 +00001681
nethercotee1730692003-11-20 10:38:07 +00001682 /* log to stderr by default, but usage message goes to stdout */
nethercotef8548672004-06-21 12:42:35 +00001683 eventually_log_fd = 2;
sewardjde4a1d02002-03-22 01:27:54 +00001684
sewardj19d81412002-06-03 01:10:40 +00001685 /* Check for sane path in ./configure --prefix=... */
fitzhardinge98abfc72003-12-16 02:05:15 +00001686 if (VG_LIBDIR[0] != '/')
sewardj19d81412002-06-03 01:10:40 +00001687 config_error("Please use absolute paths in "
1688 "./configure --prefix=... or --libdir=...");
sewardj38170912002-05-10 21:07:22 +00001689
njnc6168192004-11-29 13:54:10 +00001690// XXX: what architectures is this necessary for? x86 yes, PPC no, others ?
njnca0518d2004-11-26 19:34:36 +00001691#ifdef __x86__
1692 {
1693 Int *auxp;
1694 for (auxp = client_auxv; auxp[0] != AT_NULL; auxp += 2) {
1695 switch(auxp[0]) {
1696 case AT_SYSINFO:
1697 auxp[1] = (Int)(VG_(client_trampoline_code) + VG_(tramp_syscall_offset));
1698 break;
1699 }
1700 }
1701 }
1702#endif
sewardjde4a1d02002-03-22 01:27:54 +00001703
nethercotef6a1d502004-08-09 12:21:57 +00001704 for (i = 1; i < vg_argc; i++) {
nethercote71980f02004-01-24 18:18:54 +00001705
nethercotef6a1d502004-08-09 12:21:57 +00001706 Char* arg = vg_argv[i];
thughes3bfd5a02004-07-18 08:05:44 +00001707 Char* colon = arg;
nethercote71980f02004-01-24 18:18:54 +00001708
thughes3bfd5a02004-07-18 08:05:44 +00001709 /* Look for a colon in the switch name */
1710 while (*colon && *colon != ':' && *colon != '=')
1711 colon++;
nethercote71980f02004-01-24 18:18:54 +00001712
1713 /* Look for matching "--toolname:foo" */
thughes3bfd5a02004-07-18 08:05:44 +00001714 if (*colon == ':') {
nethercote71980f02004-01-24 18:18:54 +00001715 if (VG_CLO_STREQN(2, arg, "--") &&
1716 VG_CLO_STREQN(toolname_len, arg+2, toolname) &&
1717 VG_CLO_STREQN(1, arg+2+toolname_len, ":"))
1718 {
1719 // prefix matches, convert "--toolname:foo" to "--foo"
1720 if (0)
1721 VG_(printf)("tool-specific arg: %s\n", arg);
1722 arg += toolname_len + 1;
1723 arg[0] = '-';
1724 arg[1] = '-';
1725
1726 } else {
1727 // prefix doesn't match, skip to next arg
1728 continue;
1729 }
1730 }
1731
fitzhardinge98abfc72003-12-16 02:05:15 +00001732 /* Ignore these options - they've already been handled */
nethercotef6c99d72004-11-09 14:35:43 +00001733 if (VG_CLO_STREQN(7, arg, "--tool="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001734 continue;
nethercote71980f02004-01-24 18:18:54 +00001735 if (VG_CLO_STREQN(7, arg, "--exec="))
fitzhardinge98abfc72003-12-16 02:05:15 +00001736 continue;
1737
nethercote71980f02004-01-24 18:18:54 +00001738 if ( VG_CLO_STREQ(arg, "--"))
fitzhardinge98abfc72003-12-16 02:05:15 +00001739 continue;
nethercote27fec902004-06-16 21:26:32 +00001740
nethercote71980f02004-01-24 18:18:54 +00001741 else if (VG_CLO_STREQ(arg, "-v") ||
1742 VG_CLO_STREQ(arg, "--verbose"))
sewardjde4a1d02002-03-22 01:27:54 +00001743 VG_(clo_verbosity)++;
nethercote27fec902004-06-16 21:26:32 +00001744
nethercote71980f02004-01-24 18:18:54 +00001745 else if (VG_CLO_STREQ(arg, "-q") ||
1746 VG_CLO_STREQ(arg, "--quiet"))
sewardjde4a1d02002-03-22 01:27:54 +00001747 VG_(clo_verbosity)--;
1748
nethercote27fec902004-06-16 21:26:32 +00001749 else VG_BOOL_CLO("--branchpred", VG_(clo_branchpred))
nethercote27fec902004-06-16 21:26:32 +00001750 else VG_BOOL_CLO("--db-attach", VG_(clo_db_attach))
1751 else VG_BOOL_CLO("--demangle", VG_(clo_demangle))
1752 else VG_BOOL_CLO("--error-limit", VG_(clo_error_limit))
nethercote27fec902004-06-16 21:26:32 +00001753 else VG_BOOL_CLO("--lowlat-signals", VG_(clo_lowlat_signals))
1754 else VG_BOOL_CLO("--lowlat-syscalls", VG_(clo_lowlat_syscalls))
nethercote27fec902004-06-16 21:26:32 +00001755 else VG_BOOL_CLO("--pointercheck", VG_(clo_pointercheck))
sewardj062f3552005-01-06 16:13:40 +00001756 else VG_BOOL_CLO("--support-elan3", VG_(clo_support_elan3))
nethercote27fec902004-06-16 21:26:32 +00001757 else VG_BOOL_CLO("--profile", VG_(clo_profile))
1758 else VG_BOOL_CLO("--run-libc-freeres", VG_(clo_run_libc_freeres))
1759 else VG_BOOL_CLO("--show-below-main", VG_(clo_show_below_main))
thughes6233a382004-08-21 11:10:44 +00001760 else VG_BOOL_CLO("--time-stamp", VG_(clo_time_stamp))
nethercote27fec902004-06-16 21:26:32 +00001761 else VG_BOOL_CLO("--track-fds", VG_(clo_track_fds))
1762 else VG_BOOL_CLO("--trace-children", VG_(clo_trace_children))
1763 else VG_BOOL_CLO("--trace-sched", VG_(clo_trace_sched))
1764 else VG_BOOL_CLO("--trace-signals", VG_(clo_trace_signals))
1765 else VG_BOOL_CLO("--trace-symtab", VG_(clo_trace_symtab))
1766 else VG_BOOL_CLO("--trace-syscalls", VG_(clo_trace_syscalls))
1767 else VG_BOOL_CLO("--wait-for-gdb", VG_(clo_wait_for_gdb))
sewardj72f98ff2002-06-13 17:23:38 +00001768
nethercote27fec902004-06-16 21:26:32 +00001769 else VG_STR_CLO ("--db-command", VG_(clo_db_command))
1770 else VG_STR_CLO ("--weird-hacks", VG_(clo_weird_hacks))
sewardjde4a1d02002-03-22 01:27:54 +00001771
nethercote27fec902004-06-16 21:26:32 +00001772 else VG_NUM_CLO ("--dump-error", VG_(clo_dump_error))
1773 else VG_NUM_CLO ("--input-fd", VG_(clo_input_fd))
1774 else VG_NUM_CLO ("--sanity-level", VG_(clo_sanity_level))
nethercote69978792004-10-29 11:17:21 +00001775 else VG_NUM_CLO ("--signal-polltime", VG_(clo_signal_polltime))
nethercote27fec902004-06-16 21:26:32 +00001776 else VG_BNUM_CLO("--num-callers", VG_(clo_backtrace_size), 1,
1777 VG_DEEPEST_BACKTRACE)
sewardjde4a1d02002-03-22 01:27:54 +00001778
sewardj8b635a42004-11-22 19:01:47 +00001779 else VG_BNUM_CLO("--vex-iropt-verbosity",
1780 VG_(clo_vex_control).iropt_verbosity, 0, 10)
1781 else VG_BNUM_CLO("--vex-iropt-level",
1782 VG_(clo_vex_control).iropt_level, 0, 2)
1783 else VG_BOOL_CLO("--vex-iropt-precise-memory-exns",
1784 VG_(clo_vex_control).iropt_precise_memory_exns)
1785 else VG_BNUM_CLO("--vex-iropt-unroll-thresh",
1786 VG_(clo_vex_control).iropt_unroll_thresh, 0, 400)
1787 else VG_BNUM_CLO("--vex-guest-max-insns",
1788 VG_(clo_vex_control).guest_max_insns, 1, 100)
1789 else VG_BNUM_CLO("--vex-guest-chase-thresh",
1790 VG_(clo_vex_control).guest_chase_thresh, 0, 99)
1791
nethercotef8548672004-06-21 12:42:35 +00001792 // for backwards compatibility, replaced by --log-fd
nethercote71980f02004-01-24 18:18:54 +00001793 else if (VG_CLO_STREQN(13, arg, "--logfile-fd=")) {
nethercotef8548672004-06-21 12:42:35 +00001794 VG_(clo_log_to) = VgLogTo_Fd;
1795 VG_(clo_log_name) = NULL;
1796 eventually_log_fd = (Int)VG_(atoll)(&arg[13]);
1797 }
1798 else if (VG_CLO_STREQN(9, arg, "--log-fd=")) {
1799 VG_(clo_log_to) = VgLogTo_Fd;
1800 VG_(clo_log_name) = NULL;
1801 eventually_log_fd = (Int)VG_(atoll)(&arg[9]);
sewardj4cf05692002-10-27 20:28:29 +00001802 }
1803
nethercotef8548672004-06-21 12:42:35 +00001804 // for backwards compatibility, replaced by --log-file
nethercote71980f02004-01-24 18:18:54 +00001805 else if (VG_CLO_STREQN(10, arg, "--logfile=")) {
nethercotef8548672004-06-21 12:42:35 +00001806 VG_(clo_log_to) = VgLogTo_File;
1807 VG_(clo_log_name) = &arg[10];
1808 }
1809 else if (VG_CLO_STREQN(11, arg, "--log-file=")) {
1810 VG_(clo_log_to) = VgLogTo_File;
1811 VG_(clo_log_name) = &arg[11];
sewardj4cf05692002-10-27 20:28:29 +00001812 }
sewardj603d4102005-01-11 14:01:02 +00001813 else if (VG_CLO_STREQN(19, arg, "--log-file-exactly=")) {
1814 VG_(clo_log_to) = VgLogTo_FileExactly;
1815 VG_(clo_log_name) = &arg[19];
1816 }
sewardjde4a1d02002-03-22 01:27:54 +00001817
nethercotef8548672004-06-21 12:42:35 +00001818 // for backwards compatibility, replaced by --log-socket
nethercote71980f02004-01-24 18:18:54 +00001819 else if (VG_CLO_STREQN(12, arg, "--logsocket=")) {
nethercotef8548672004-06-21 12:42:35 +00001820 VG_(clo_log_to) = VgLogTo_Socket;
1821 VG_(clo_log_name) = &arg[12];
1822 }
1823 else if (VG_CLO_STREQN(13, arg, "--log-socket=")) {
1824 VG_(clo_log_to) = VgLogTo_Socket;
1825 VG_(clo_log_name) = &arg[13];
sewardj73cf3bc2002-11-03 03:20:15 +00001826 }
1827
nethercote71980f02004-01-24 18:18:54 +00001828 else if (VG_CLO_STREQN(15, arg, "--suppressions=")) {
sewardjde4a1d02002-03-22 01:27:54 +00001829 if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) {
njn25e49d8e72002-09-23 09:36:25 +00001830 VG_(message)(Vg_UserMsg, "Too many suppression files specified.");
sewardjde4a1d02002-03-22 01:27:54 +00001831 VG_(message)(Vg_UserMsg,
1832 "Increase VG_CLO_MAX_SFILES and recompile.");
nethercote71980f02004-01-24 18:18:54 +00001833 VG_(bad_option)(arg);
sewardjde4a1d02002-03-22 01:27:54 +00001834 }
nethercote71980f02004-01-24 18:18:54 +00001835 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = &arg[15];
sewardjde4a1d02002-03-22 01:27:54 +00001836 VG_(clo_n_suppressions)++;
1837 }
sewardjde4a1d02002-03-22 01:27:54 +00001838
sewardjfa8ec112005-01-19 11:55:34 +00001839 /* "stuvwxyz" --> stuvwxyz (binary) */
1840 else if (VG_CLO_STREQN(14, arg, "--trace-flags=")) {
1841 Int j;
1842 char* opt = & arg[14];
1843
1844 if (8 != VG_(strlen)(opt)) {
1845 VG_(message)(Vg_UserMsg,
1846 "--trace-flags argument must have 8 digits");
1847 VG_(bad_option)(arg);
1848 }
1849 for (j = 0; j < 8; j++) {
1850 if ('0' == opt[j]) { /* do nothing */ }
1851 else if ('1' == opt[j]) VG_(clo_trace_flags) |= (1 << (7-j));
1852 else {
1853 VG_(message)(Vg_UserMsg, "--trace-flags argument can only "
1854 "contain 0s and 1s");
1855 VG_(bad_option)(arg);
1856 }
1857 }
1858 }
1859
1860 /* "stuvwxyz" --> stuvwxyz (binary) */
1861 else if (VG_CLO_STREQN(16, arg, "--profile-flags=")) {
njn25e49d8e72002-09-23 09:36:25 +00001862 Int j;
nethercote71980f02004-01-24 18:18:54 +00001863 char* opt = & arg[16];
njn25e49d8e72002-09-23 09:36:25 +00001864
sewardj2a99cf62004-11-24 10:44:19 +00001865 if (8 != VG_(strlen)(opt)) {
njn25e49d8e72002-09-23 09:36:25 +00001866 VG_(message)(Vg_UserMsg,
sewardjfa8ec112005-01-19 11:55:34 +00001867 "--profile-flags argument must have 8 digits");
nethercote71980f02004-01-24 18:18:54 +00001868 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001869 }
sewardj8b635a42004-11-22 19:01:47 +00001870 for (j = 0; j < 8; j++) {
njn25e49d8e72002-09-23 09:36:25 +00001871 if ('0' == opt[j]) { /* do nothing */ }
sewardjfa8ec112005-01-19 11:55:34 +00001872 else if ('1' == opt[j]) VG_(clo_profile_flags) |= (1 << (7-j));
njn25e49d8e72002-09-23 09:36:25 +00001873 else {
sewardjfa8ec112005-01-19 11:55:34 +00001874 VG_(message)(Vg_UserMsg, "--profile-flags argument can only "
njn25e49d8e72002-09-23 09:36:25 +00001875 "contain 0s and 1s");
nethercote71980f02004-01-24 18:18:54 +00001876 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001877 }
1878 }
1879 }
sewardjde4a1d02002-03-22 01:27:54 +00001880
sewardjc771b292004-11-30 18:55:21 +00001881 else VG_NUM_CLO ("--trace-notbelow", VG_(clo_trace_notbelow))
1882
nethercote71980f02004-01-24 18:18:54 +00001883 else if (VG_CLO_STREQ(arg, "--trace-pthread=none"))
sewardj45b4b372002-04-16 22:50:32 +00001884 VG_(clo_trace_pthread_level) = 0;
nethercote71980f02004-01-24 18:18:54 +00001885 else if (VG_CLO_STREQ(arg, "--trace-pthread=some"))
sewardj45b4b372002-04-16 22:50:32 +00001886 VG_(clo_trace_pthread_level) = 1;
nethercote71980f02004-01-24 18:18:54 +00001887 else if (VG_CLO_STREQ(arg, "--trace-pthread=all"))
sewardj45b4b372002-04-16 22:50:32 +00001888 VG_(clo_trace_pthread_level) = 2;
sewardj8937c812002-04-12 20:12:20 +00001889
sewardjd153fae2005-01-10 17:24:47 +00001890 else if (VG_CLO_STREQ(arg, "--gen-suppressions=no"))
1891 VG_(clo_gen_suppressions) = 0;
1892 else if (VG_CLO_STREQ(arg, "--gen-suppressions=yes"))
1893 VG_(clo_gen_suppressions) = 1;
1894 else if (VG_CLO_STREQ(arg, "--gen-suppressions=all"))
1895 VG_(clo_gen_suppressions) = 2;
1896
nethercote71980f02004-01-24 18:18:54 +00001897 else if ( ! VG_(needs).command_line_options
njn26f02512004-11-22 18:33:15 +00001898 || ! TL_(process_cmd_line_option)(arg) ) {
nethercotef4928da2004-06-15 10:54:40 +00001899 VG_(bad_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001900 }
sewardjde4a1d02002-03-22 01:27:54 +00001901 }
1902
sewardj998d40d2004-12-06 14:24:52 +00001903 /* Make VEX control parameters sane */
1904
1905 if (VG_(clo_vex_control).guest_chase_thresh
1906 >= VG_(clo_vex_control).guest_max_insns)
1907 VG_(clo_vex_control).guest_chase_thresh
1908 = VG_(clo_vex_control).guest_max_insns - 1;
1909
1910 if (VG_(clo_vex_control).guest_chase_thresh < 0)
1911 VG_(clo_vex_control).guest_chase_thresh = 0;
1912
1913 /* Check various option values */
nethercote27fec902004-06-16 21:26:32 +00001914
njnf9ebf672003-05-12 21:41:30 +00001915 if (VG_(clo_verbosity) < 0)
sewardjde4a1d02002-03-22 01:27:54 +00001916 VG_(clo_verbosity) = 0;
1917
nethercote04d0fbc2004-01-26 16:48:06 +00001918 if (VG_(clo_db_attach) && VG_(clo_trace_children)) {
sewardjde4a1d02002-03-22 01:27:54 +00001919 VG_(message)(Vg_UserMsg, "");
1920 VG_(message)(Vg_UserMsg,
nethercote04d0fbc2004-01-26 16:48:06 +00001921 "--db-attach=yes conflicts with --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001922 VG_(message)(Vg_UserMsg,
1923 "Please choose one or the other, but not both.");
nethercote04d0fbc2004-01-26 16:48:06 +00001924 VG_(bad_option)("--db-attach=yes and --trace-children=yes");
sewardjde4a1d02002-03-22 01:27:54 +00001925 }
1926
nethercotef8548672004-06-21 12:42:35 +00001927 /* Set up logging now. After this is done, VG_(clo_log_fd)
sewardj4cf05692002-10-27 20:28:29 +00001928 should be connected to whatever sink has been selected, and we
1929 indiscriminately chuck stuff into it without worrying what the
1930 nature of it is. Oh the wonder of Unix streams. */
1931
nethercotee1730692003-11-20 10:38:07 +00001932 /* So far we should be still attached to stdout, so we can show on
sewardj4cf05692002-10-27 20:28:29 +00001933 the terminal any problems to do with processing command line
1934 opts. */
nethercotef8548672004-06-21 12:42:35 +00001935 vg_assert(VG_(clo_log_fd) == 1 /* stdout */);
sewardj73cf3bc2002-11-03 03:20:15 +00001936 vg_assert(VG_(logging_to_filedes) == True);
sewardj4cf05692002-10-27 20:28:29 +00001937
1938 switch (VG_(clo_log_to)) {
sewardj73cf3bc2002-11-03 03:20:15 +00001939
sewardj4cf05692002-10-27 20:28:29 +00001940 case VgLogTo_Fd:
nethercotef8548672004-06-21 12:42:35 +00001941 vg_assert(VG_(clo_log_name) == NULL);
1942 VG_(clo_log_fd) = eventually_log_fd;
sewardj4cf05692002-10-27 20:28:29 +00001943 break;
sewardj73cf3bc2002-11-03 03:20:15 +00001944
sewardj4cf05692002-10-27 20:28:29 +00001945 case VgLogTo_File: {
1946 Char logfilename[1000];
jsgff3c3f1a2003-10-14 22:13:28 +00001947 Int seq = 0;
1948 Int pid = VG_(getpid)();
1949
nethercotef8548672004-06-21 12:42:35 +00001950 vg_assert(VG_(clo_log_name) != NULL);
1951 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
jsgff3c3f1a2003-10-14 22:13:28 +00001952
nethercote71980f02004-01-24 18:18:54 +00001953 for (;;) {
jsgff3c3f1a2003-10-14 22:13:28 +00001954 if (seq == 0)
1955 VG_(sprintf)(logfilename, "%s.pid%d",
nethercotef8548672004-06-21 12:42:35 +00001956 VG_(clo_log_name), pid );
jsgff3c3f1a2003-10-14 22:13:28 +00001957 else
1958 VG_(sprintf)(logfilename, "%s.pid%d.%d",
nethercotef8548672004-06-21 12:42:35 +00001959 VG_(clo_log_name), pid, seq );
jsgff3c3f1a2003-10-14 22:13:28 +00001960 seq++;
1961
nethercotef8548672004-06-21 12:42:35 +00001962 eventually_log_fd
jsgff3c3f1a2003-10-14 22:13:28 +00001963 = VG_(open)(logfilename,
1964 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC,
1965 VKI_S_IRUSR|VKI_S_IWUSR);
nethercotef8548672004-06-21 12:42:35 +00001966 if (eventually_log_fd >= 0) {
1967 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
sewardj603d4102005-01-11 14:01:02 +00001968 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001969 } else {
nethercotef8548672004-06-21 12:42:35 +00001970 if (eventually_log_fd != -VKI_EEXIST) {
jsgff3c3f1a2003-10-14 22:13:28 +00001971 VG_(message)(Vg_UserMsg,
1972 "Can't create/open log file `%s.pid%d'; giving up!",
nethercotef8548672004-06-21 12:42:35 +00001973 VG_(clo_log_name), pid);
jsgff3c3f1a2003-10-14 22:13:28 +00001974 VG_(bad_option)(
sewardj603d4102005-01-11 14:01:02 +00001975 "--log-file=<file> (didn't work out for some reason.)");
1976 break; /* for (;;) */
jsgff3c3f1a2003-10-14 22:13:28 +00001977 }
1978 }
1979 }
sewardj603d4102005-01-11 14:01:02 +00001980 break; /* switch (VG_(clo_log_to)) */
1981 }
1982
1983 case VgLogTo_FileExactly: {
1984 Char logfilename[1000];
1985
1986 vg_assert(VG_(clo_log_name) != NULL);
1987 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
1988 VG_(sprintf)(logfilename, "%s", VG_(clo_log_name));
1989
1990 eventually_log_fd
1991 = VG_(open)(logfilename,
1992 VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC,
1993 VKI_S_IRUSR|VKI_S_IWUSR);
1994 if (eventually_log_fd >= 0) {
1995 VG_(clo_log_fd) = VG_(safe_fd)(eventually_log_fd);
1996 }
1997 else if (eventually_log_fd != -VKI_EEXIST) {
1998 VG_(message)(Vg_UserMsg,
1999 "Can't create/open log file `%s'; giving up!",
2000 VG_(clo_log_name));
2001 VG_(bad_option)(
2002 "--log-file-exactly=<file> (didn't work out for some reason.)");
2003 /*NOTREACHED*/
2004 }
2005 break; /* switch (VG_(clo_log_to)) */
sewardj73cf3bc2002-11-03 03:20:15 +00002006 }
2007
2008 case VgLogTo_Socket: {
nethercotef8548672004-06-21 12:42:35 +00002009 vg_assert(VG_(clo_log_name) != NULL);
2010 vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
2011 eventually_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
2012 if (eventually_log_fd == -1) {
sewardj73cf3bc2002-11-03 03:20:15 +00002013 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00002014 "Invalid --log-socket=ipaddr or --log-socket=ipaddr:port spec");
sewardj73cf3bc2002-11-03 03:20:15 +00002015 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00002016 "of `%s'; giving up!", VG_(clo_log_name) );
sewardj73cf3bc2002-11-03 03:20:15 +00002017 VG_(bad_option)(
nethercotef8548672004-06-21 12:42:35 +00002018 "--log-socket=");
sewardj4cf05692002-10-27 20:28:29 +00002019 }
nethercotef8548672004-06-21 12:42:35 +00002020 if (eventually_log_fd == -2) {
sewardj73cf3bc2002-11-03 03:20:15 +00002021 VG_(message)(Vg_UserMsg,
sewardj570f8902002-11-03 11:44:36 +00002022 "valgrind: failed to connect to logging server `%s'.",
nethercotef8548672004-06-21 12:42:35 +00002023 VG_(clo_log_name) );
sewardj570f8902002-11-03 11:44:36 +00002024 VG_(message)(Vg_UserMsg,
2025 "Log messages will sent to stderr instead." );
2026 VG_(message)(Vg_UserMsg,
2027 "" );
2028 /* We don't change anything here. */
2029 } else {
nethercotef8548672004-06-21 12:42:35 +00002030 vg_assert(eventually_log_fd > 0);
2031 VG_(clo_log_fd) = eventually_log_fd;
sewardj570f8902002-11-03 11:44:36 +00002032 VG_(logging_to_filedes) = False;
2033 }
sewardj73cf3bc2002-11-03 03:20:15 +00002034 break;
2035 }
2036
sewardj4cf05692002-10-27 20:28:29 +00002037 }
2038
nethercotef8548672004-06-21 12:42:35 +00002039 /* Move log_fd into the safe range, so it doesn't conflict with any app fds */
thughesad1c9562004-06-26 11:27:52 +00002040 eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
nethercotef8548672004-06-21 12:42:35 +00002041 if (eventually_log_fd < 0)
jsgf855d93d2003-10-13 22:26:55 +00002042 VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
2043 else {
nethercotef8548672004-06-21 12:42:35 +00002044 VG_(clo_log_fd) = eventually_log_fd;
2045 VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
jsgf855d93d2003-10-13 22:26:55 +00002046 }
2047
sewardj4cf05692002-10-27 20:28:29 +00002048 /* Ok, the logging sink is running now. Print a suitable preamble.
2049 If logging to file or a socket, write details of parent PID and
2050 command line args, to help people trying to interpret the
2051 results of a run which encompasses multiple processes. */
sewardjde4a1d02002-03-22 01:27:54 +00002052
sewardj83adf412002-05-01 01:25:45 +00002053 if (VG_(clo_verbosity > 0)) {
nethercote996901a2004-08-03 13:29:09 +00002054 /* Tool details */
njnb9c427c2004-12-01 14:14:42 +00002055 VG_(message)(Vg_UserMsg, "%s%s%s, %s.",
njnd04b7c62002-10-03 14:05:52 +00002056 VG_(details).name,
njnb9c427c2004-12-01 14:14:42 +00002057 NULL == VG_(details).version ? "" : "-",
njnd04b7c62002-10-03 14:05:52 +00002058 NULL == VG_(details).version
2059 ? (Char*)"" : VG_(details).version,
njnb9c427c2004-12-01 14:14:42 +00002060 VG_(details).description);
njnd04b7c62002-10-03 14:05:52 +00002061 VG_(message)(Vg_UserMsg, "%s", VG_(details).copyright_author);
sewardj3b2736a2002-03-24 12:18:35 +00002062
njnd04b7c62002-10-03 14:05:52 +00002063 /* Core details */
2064 VG_(message)(Vg_UserMsg,
sewardj090ec782004-12-20 04:38:31 +00002065 "Using LibVEX rev %s, a library for dynamic binary translation.",
2066 LibVEX_Version() );
sewardjc7025332004-12-13 18:30:39 +00002067 VG_(message)(Vg_UserMsg,
2068 "Copyright (C) 2004, and GNU GPL'd, by OpenWorks LLP.");
2069 VG_(message)(Vg_UserMsg,
njnb9c427c2004-12-01 14:14:42 +00002070 "Using valgrind-%s, a dynamic binary instrumentation framework.",
sewardj5a1feda2004-12-17 19:18:02 +00002071 /*VERSION*/ "SVN >= 3207");
sewardjde4a1d02002-03-22 01:27:54 +00002072 VG_(message)(Vg_UserMsg,
nethercote08fa9a72004-07-16 17:44:00 +00002073 "Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.");
njnd04b7c62002-10-03 14:05:52 +00002074 }
2075
nethercotec1e395d2003-11-10 13:26:49 +00002076 if (VG_(clo_verbosity) > 0 && VG_(clo_log_to) != VgLogTo_Fd) {
sewardj4cf05692002-10-27 20:28:29 +00002077 VG_(message)(Vg_UserMsg, "");
2078 VG_(message)(Vg_UserMsg,
2079 "My PID = %d, parent PID = %d. Prog and args are:",
2080 VG_(getpid)(), VG_(getppid)() );
2081 for (i = 0; i < VG_(client_argc); i++)
2082 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2083 }
2084
sewardjde4a1d02002-03-22 01:27:54 +00002085 if (VG_(clo_verbosity) > 1) {
nethercotea70f7352004-04-18 12:08:46 +00002086 Int fd;
sewardj4cf05692002-10-27 20:28:29 +00002087 if (VG_(clo_log_to) != VgLogTo_Fd)
2088 VG_(message)(Vg_UserMsg, "");
fitzhardinge98abfc72003-12-16 02:05:15 +00002089 VG_(message)(Vg_UserMsg, "Valgrind library directory: %s", VG_(libdir));
njn86dc2bc2003-09-09 07:26:21 +00002090 VG_(message)(Vg_UserMsg, "Command line");
2091 for (i = 0; i < VG_(client_argc); i++)
2092 VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]);
2093
sewardjde4a1d02002-03-22 01:27:54 +00002094 VG_(message)(Vg_UserMsg, "Startup, with flags:");
nethercotef6a1d502004-08-09 12:21:57 +00002095 for (i = 1; i < vg_argc; i++) {
2096 VG_(message)(Vg_UserMsg, " %s", vg_argv[i]);
sewardjde4a1d02002-03-22 01:27:54 +00002097 }
nethercotea70f7352004-04-18 12:08:46 +00002098
2099 VG_(message)(Vg_UserMsg, "Contents of /proc/version:");
2100 fd = VG_(open) ( "/proc/version", VKI_O_RDONLY, 0 );
2101 if (fd < 0) {
2102 VG_(message)(Vg_UserMsg, " can't open /proc/version");
2103 } else {
2104 #define BUF_LEN 256
2105 Char version_buf[BUF_LEN];
2106 Int n = VG_(read) ( fd, version_buf, BUF_LEN );
2107 vg_assert(n <= 256);
2108 if (n > 0) {
2109 version_buf[n-1] = '\0';
2110 VG_(message)(Vg_UserMsg, " %s", version_buf);
2111 } else {
2112 VG_(message)(Vg_UserMsg, " (empty?)");
2113 }
2114 VG_(close)(fd);
2115 #undef BUF_LEN
2116 }
sewardjde4a1d02002-03-22 01:27:54 +00002117 }
2118
fitzhardinge98abfc72003-12-16 02:05:15 +00002119 if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
njn95ec8702004-11-22 16:46:13 +00002120 (VG_(needs).core_errors || VG_(needs).tool_errors)) {
nethercote996901a2004-08-03 13:29:09 +00002121 /* If there are no suppression files specified and the tool
fitzhardinge98abfc72003-12-16 02:05:15 +00002122 needs one, load the default */
2123 static const Char default_supp[] = "default.supp";
2124 Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
2125 Char *buf = VG_(arena_malloc)(VG_AR_CORE, len);
2126 VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
2127 VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
2128 VG_(clo_n_suppressions)++;
sewardjde4a1d02002-03-22 01:27:54 +00002129 }
sewardj4cf05692002-10-27 20:28:29 +00002130
sewardjd153fae2005-01-10 17:24:47 +00002131 if (VG_(clo_gen_suppressions) > 0 &&
njn95ec8702004-11-22 16:46:13 +00002132 !VG_(needs).core_errors && !VG_(needs).tool_errors) {
nethercotef4928da2004-06-15 10:54:40 +00002133 VG_(message)(Vg_UserMsg,
sewardjd153fae2005-01-10 17:24:47 +00002134 "Can't use --gen-suppressions= with this tool,");
nethercotef4928da2004-06-15 10:54:40 +00002135 VG_(message)(Vg_UserMsg,
2136 "as it doesn't generate errors.");
sewardjd153fae2005-01-10 17:24:47 +00002137 VG_(bad_option)("--gen-suppressions=");
njn6a230532003-07-21 10:38:23 +00002138 }
sewardjde4a1d02002-03-22 01:27:54 +00002139}
2140
nethercotef6a1d502004-08-09 12:21:57 +00002141// Build the string for VALGRINDCLO.
2142Char* VG_(build_child_VALGRINDCLO)( Char* exename )
2143{
2144 /* If we're tracing the children, then we need to start it
2145 with our starter+arguments, which are copied into VALGRINDCLO,
2146 except the --exec= option is changed if present.
2147 */
2148 Int i;
2149 Char *exec;
2150 Char *cp;
2151 Char *optvar;
2152 Int optlen, execlen;
2153
2154 // All these allocated blocks are not free - because we're either
2155 // going to exec, or panic when we fail.
2156
2157 // Create --exec= option: "--exec=<exename>"
2158 exec = VG_(arena_malloc)(VG_AR_CORE,
2159 VG_(strlen)( exename ) + 7/*--exec=*/ + 1/*\0*/);
2160 vg_assert(NULL != exec);
2161 VG_(sprintf)(exec, "--exec=%s", exename);
2162
2163 // Allocate space for optvar (may overestimate by counting --exec twice,
2164 // no matter)
2165 optlen = 1;
2166 for (i = 0; i < vg_argc; i++)
2167 optlen += VG_(strlen)(vg_argv[i]) + 1;
2168 optlen += VG_(strlen)(exec)+1;
2169 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
2170
2171 // Copy all valgrind args except the old --exec (if present)
2172 // VG_CLO_SEP is the separator.
2173 cp = optvar;
2174 for (i = 1; i < vg_argc; i++) {
2175 Char *arg = vg_argv[i];
2176
2177 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
2178 // don't copy existing --exec= arg
2179 } else if (VG_(strcmp)(arg, "--") == 0) {
2180 // stop at "--"
2181 break;
2182 } else {
2183 // copy non "--exec" arg
2184 Int len = VG_(strlen)(arg);
2185 VG_(memcpy)(cp, arg, len);
2186 cp += len;
2187 *cp++ = VG_CLO_SEP;
2188 }
2189 }
2190 // Add the new --exec= option
2191 execlen = VG_(strlen)(exec);
2192 VG_(memcpy)(cp, exec, execlen);
2193 cp += execlen;
2194 *cp++ = VG_CLO_SEP;
2195
2196 *cp = '\0';
2197
2198 return optvar;
2199}
2200
2201// Build "/proc/self/fd/<execfd>".
2202Char* VG_(build_child_exename)( void )
2203{
2204 Char* exename = VG_(arena_malloc)(VG_AR_CORE, 64);
2205 vg_assert(NULL != exename);
2206 VG_(sprintf)(exename, "/proc/self/fd/%d", vgexecfd);
2207 return exename;
2208}
2209
sewardjde4a1d02002-03-22 01:27:54 +00002210
nethercote71980f02004-01-24 18:18:54 +00002211/*====================================================================*/
2212/*=== File descriptor setup ===*/
2213/*====================================================================*/
2214
2215static void setup_file_descriptors(void)
2216{
2217 struct vki_rlimit rl;
2218
2219 /* Get the current file descriptor limits. */
2220 if (VG_(getrlimit)(VKI_RLIMIT_NOFILE, &rl) < 0) {
2221 rl.rlim_cur = 1024;
2222 rl.rlim_max = 1024;
2223 }
2224
2225 /* Work out where to move the soft limit to. */
2226 if (rl.rlim_cur + VG_N_RESERVED_FDS <= rl.rlim_max) {
2227 rl.rlim_cur = rl.rlim_cur + VG_N_RESERVED_FDS;
2228 } else {
2229 rl.rlim_cur = rl.rlim_max;
2230 }
2231
2232 /* Reserve some file descriptors for our use. */
thughesad1c9562004-06-26 11:27:52 +00002233 VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
2234 VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
nethercote71980f02004-01-24 18:18:54 +00002235
2236 /* Update the soft limit. */
2237 VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
2238
nethercotef6a1d502004-08-09 12:21:57 +00002239 if (vgexecfd != -1)
2240 vgexecfd = VG_(safe_fd)( vgexecfd );
nethercote71980f02004-01-24 18:18:54 +00002241 if (VG_(clexecfd) != -1)
2242 VG_(clexecfd) = VG_(safe_fd)( VG_(clexecfd) );
2243}
2244
nethercote71980f02004-01-24 18:18:54 +00002245/*====================================================================*/
nethercote71980f02004-01-24 18:18:54 +00002246/*=== Initialise program data/text, etc. ===*/
2247/*====================================================================*/
sewardjde4a1d02002-03-22 01:27:54 +00002248
nethercote71980f02004-01-24 18:18:54 +00002249static void build_valgrind_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002250 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002251 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardjde4a1d02002-03-22 01:27:54 +00002252{
nethercote71980f02004-01-24 18:18:54 +00002253 UInt prot = 0;
2254 UInt flags = SF_MMAP|SF_NOSYMS;
2255 Bool is_stack_segment;
2256
2257 is_stack_segment =
2258 (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
2259
2260 /* Only record valgrind mappings for now, without loading any
2261 symbols. This is so we know where the free space is before we
2262 start allocating more memory (note: heap is OK, it's just mmap
2263 which is the problem here). */
nethercote820bd8c2004-09-07 23:04:49 +00002264 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last)) {
nethercote71980f02004-01-24 18:18:54 +00002265 flags |= SF_VALGRIND;
2266 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
2267 }
sewardjde4a1d02002-03-22 01:27:54 +00002268}
2269
nethercote71980f02004-01-24 18:18:54 +00002270// Global var used to pass local data to callback
nethercote4ad74312004-10-26 09:59:49 +00002271Addr sp_at_startup___global_arg = 0;
sewardjde4a1d02002-03-22 01:27:54 +00002272
nethercote71980f02004-01-24 18:18:54 +00002273static void build_segment_map_callback
nethercote8991d5a2004-11-03 17:07:46 +00002274 ( Addr start, SizeT size, Char rr, Char ww, Char xx,
nethercote71980f02004-01-24 18:18:54 +00002275 UInt dev, UInt ino, ULong foffset, const UChar* filename )
sewardj45b672d2003-07-25 19:58:11 +00002276{
nethercote71980f02004-01-24 18:18:54 +00002277 UInt prot = 0;
2278 UInt flags;
2279 Bool is_stack_segment;
2280 Addr r_esp;
sewardj45b672d2003-07-25 19:58:11 +00002281
nethercote71980f02004-01-24 18:18:54 +00002282 is_stack_segment
2283 = (start == VG_(clstk_base) && (start+size) == VG_(clstk_end));
fitzhardinge98abfc72003-12-16 02:05:15 +00002284
nethercote71980f02004-01-24 18:18:54 +00002285 if (rr == 'r') prot |= VKI_PROT_READ;
2286 if (ww == 'w') prot |= VKI_PROT_WRITE;
2287 if (xx == 'x') prot |= VKI_PROT_EXEC;
fitzhardinge98abfc72003-12-16 02:05:15 +00002288
nethercote71980f02004-01-24 18:18:54 +00002289 if (is_stack_segment)
2290 flags = SF_STACK | SF_GROWDOWN;
2291 else
2292 flags = SF_EXEC|SF_MMAP;
fitzhardinge98abfc72003-12-16 02:05:15 +00002293
nethercote71980f02004-01-24 18:18:54 +00002294 if (filename != NULL)
2295 flags |= SF_FILE;
fitzhardinge98abfc72003-12-16 02:05:15 +00002296
nethercote820bd8c2004-09-07 23:04:49 +00002297 if (start >= VG_(valgrind_base) && (start+size-1) <= VG_(valgrind_last))
nethercote71980f02004-01-24 18:18:54 +00002298 flags |= SF_VALGRIND;
fitzhardinge98abfc72003-12-16 02:05:15 +00002299
nethercote71980f02004-01-24 18:18:54 +00002300 VG_(map_file_segment)(start, size, prot, flags, dev, ino, foffset, filename);
fitzhardinge98abfc72003-12-16 02:05:15 +00002301
nethercote71980f02004-01-24 18:18:54 +00002302 if (VG_(is_client_addr)(start) && VG_(is_client_addr)(start+size-1))
2303 VG_TRACK( new_mem_startup, start, size, rr=='r', ww=='w', xx=='x' );
sewardj3e1eb1f2002-05-18 13:14:17 +00002304
nethercote71980f02004-01-24 18:18:54 +00002305 /* If this is the stack segment mark all below %esp as noaccess. */
nethercote4ad74312004-10-26 09:59:49 +00002306 r_esp = sp_at_startup___global_arg;
nethercote71980f02004-01-24 18:18:54 +00002307 vg_assert(0 != r_esp);
2308 if (is_stack_segment) {
2309 if (0)
2310 VG_(message)(Vg_DebugMsg, "invalidating stack area: %x .. %x",
2311 start,r_esp);
2312 VG_TRACK( die_mem_stack, start, r_esp-start );
sewardjde4a1d02002-03-22 01:27:54 +00002313 }
sewardjde4a1d02002-03-22 01:27:54 +00002314}
2315
2316
nethercote71980f02004-01-24 18:18:54 +00002317/*====================================================================*/
2318/*=== Sanity check machinery (permanently engaged) ===*/
2319/*====================================================================*/
njn25e49d8e72002-09-23 09:36:25 +00002320
2321/* A fast sanity check -- suitable for calling circa once per
2322 millisecond. */
2323
nethercote885dd912004-08-03 23:14:00 +00002324void VG_(sanity_check_general) ( Bool force_expensive )
njn25e49d8e72002-09-23 09:36:25 +00002325{
njn37cea302002-09-30 11:24:00 +00002326 VGP_PUSHCC(VgpCoreCheapSanity);
2327
nethercote27fec902004-06-16 21:26:32 +00002328 if (VG_(clo_sanity_level) < 1) return;
njn25e49d8e72002-09-23 09:36:25 +00002329
2330 /* --- First do all the tests that we can do quickly. ---*/
2331
nethercote297effd2004-08-02 15:07:57 +00002332 sanity_fast_count++;
njn25e49d8e72002-09-23 09:36:25 +00002333
njn25e49d8e72002-09-23 09:36:25 +00002334 /* Check stuff pertaining to the memory check system. */
2335
2336 /* Check that nobody has spuriously claimed that the first or
2337 last 16 pages of memory have become accessible [...] */
njn37cea302002-09-30 11:24:00 +00002338 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002339 VGP_PUSHCC(VgpToolCheapSanity);
njn26f02512004-11-22 18:33:15 +00002340 vg_assert(TL_(cheap_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002341 VGP_POPCC(VgpToolCheapSanity);
njn37cea302002-09-30 11:24:00 +00002342 }
njn25e49d8e72002-09-23 09:36:25 +00002343
2344 /* --- Now some more expensive checks. ---*/
2345
2346 /* Once every 25 times, check some more expensive stuff. */
2347 if ( force_expensive
nethercote27fec902004-06-16 21:26:32 +00002348 || VG_(clo_sanity_level) > 1
nethercote297effd2004-08-02 15:07:57 +00002349 || (VG_(clo_sanity_level) == 1 && (sanity_fast_count % 25) == 0)) {
njn25e49d8e72002-09-23 09:36:25 +00002350
njn37cea302002-09-30 11:24:00 +00002351 VGP_PUSHCC(VgpCoreExpensiveSanity);
nethercote297effd2004-08-02 15:07:57 +00002352 sanity_slow_count++;
njn25e49d8e72002-09-23 09:36:25 +00002353
nethercote885dd912004-08-03 23:14:00 +00002354 VG_(sanity_check_proxy)();
jsgf855d93d2003-10-13 22:26:55 +00002355
njn25e49d8e72002-09-23 09:36:25 +00002356# if 0
2357 { void zzzmemscan(void); zzzmemscan(); }
2358# endif
2359
nethercote297effd2004-08-02 15:07:57 +00002360 if ((sanity_fast_count % 250) == 0)
sewardj4ccf7072004-11-28 16:58:05 +00002361 VG_(sanity_check_tt_tc)("VG_(sanity_check_general)");
njn25e49d8e72002-09-23 09:36:25 +00002362
2363 if (VG_(needs).sanity_checks) {
njn4be0a692004-11-22 18:10:36 +00002364 VGP_PUSHCC(VgpToolExpensiveSanity);
njn26f02512004-11-22 18:33:15 +00002365 vg_assert(TL_(expensive_sanity_check)());
njn4be0a692004-11-22 18:10:36 +00002366 VGP_POPCC(VgpToolExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002367 }
2368 /*
nethercote297effd2004-08-02 15:07:57 +00002369 if ((sanity_fast_count % 500) == 0) VG_(mallocSanityCheckAll)();
njn25e49d8e72002-09-23 09:36:25 +00002370 */
njn37cea302002-09-30 11:24:00 +00002371 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002372 }
2373
nethercote27fec902004-06-16 21:26:32 +00002374 if (VG_(clo_sanity_level) > 1) {
njn37cea302002-09-30 11:24:00 +00002375 VGP_PUSHCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002376 /* Check sanity of the low-level memory manager. Note that bugs
2377 in the client's code can cause this to fail, so we don't do
2378 this check unless specially asked for. And because it's
2379 potentially very expensive. */
nethercote885dd912004-08-03 23:14:00 +00002380 VG_(sanity_check_malloc_all)();
njn37cea302002-09-30 11:24:00 +00002381 VGP_POPCC(VgpCoreExpensiveSanity);
njn25e49d8e72002-09-23 09:36:25 +00002382 }
njn37cea302002-09-30 11:24:00 +00002383 VGP_POPCC(VgpCoreCheapSanity);
njn25e49d8e72002-09-23 09:36:25 +00002384}
nethercote71980f02004-01-24 18:18:54 +00002385
2386
2387/*====================================================================*/
2388/*=== main() ===*/
2389/*====================================================================*/
2390
nethercotec314eba2004-07-15 12:59:41 +00002391/*
2392 This code decides on the layout of the client and Valgrind address
nethercote996901a2004-08-03 13:29:09 +00002393 spaces, loads valgrind.so and the tool.so into the valgrind part,
nethercotec314eba2004-07-15 12:59:41 +00002394 loads the client executable (and the dynamic linker, if necessary)
2395 into the client part, and calls into Valgrind proper.
2396
2397 The code is careful not to allow spurious mappings to appear in the
2398 wrong parts of the address space. In particular, to make sure
2399 dlopen puts things in the right place, it will pad out the forbidden
2400 chunks of address space so that dlopen is forced to put things where
2401 we want them.
2402
2403 The memory map it creates is:
2404
2405 CLIENT_BASE +-------------------------+
2406 | client address space |
2407 : :
2408 : :
2409 | client stack |
2410 client_end +-------------------------+
2411 | redzone |
2412 shadow_base +-------------------------+
2413 | |
nethercote996901a2004-08-03 13:29:09 +00002414 : shadow memory for tools :
nethercotec314eba2004-07-15 12:59:41 +00002415 | (may be 0 sized) |
2416 shadow_end +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002417 valgrind_base +-------------------------+
2418 | kickstart executable |
2419 | valgrind heap vvvvvvvvv| (barely used)
2420 - -
2421 | valgrind .so files |
2422 | and mappings |
2423 - -
2424 | valgrind stack ^^^^^^^^^|
nethercote820bd8c2004-09-07 23:04:49 +00002425 valgrind_last +-------------------------+
nethercotec314eba2004-07-15 12:59:41 +00002426 : kernel :
2427
2428 Nb: Before we can do general allocations with VG_(arena_malloc)() and
2429 VG_(mmap)(), we need to build the segment skip-list, so we know where
2430 we can put things. However, building that structure requires
2431 allocating memory. So we need to a bootstrapping process. It's done
2432 by making VG_(arena_malloc)() have a special static superblock that's
2433 used for the first 1MB's worth of allocations. This is enough to
2434 build the segment skip-list.
2435*/
2436
nethercote31779c72004-07-30 21:50:15 +00002437static int prmap(char *start, char *end, const char *perm, off_t off,
2438 int maj, int min, int ino, void* dummy) {
thughes4ad52d02004-06-27 17:37:21 +00002439 printf("mapping %10p-%10p %s %02x:%02x %d\n",
2440 start, end, perm, maj, min, ino);
2441 return True;
2442}
2443
nethercote71980f02004-01-24 18:18:54 +00002444int main(int argc, char **argv)
2445{
2446 char **cl_argv;
2447 const char *tool = NULL;
2448 const char *exec = NULL;
2449 char *preload; /* tool-specific LD_PRELOAD .so */
2450 char **env;
nethercote6c999f22004-01-31 22:55:15 +00002451 Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug
nethercote71980f02004-01-24 18:18:54 +00002452 struct exeinfo info;
2453 ToolInfo *toolinfo = NULL;
2454 void *tool_dlhandle;
2455 Addr client_eip;
nethercote4ad74312004-10-26 09:59:49 +00002456 Addr sp_at_startup; /* client's SP at the point we gained control. */
nethercote71980f02004-01-24 18:18:54 +00002457 UInt * client_auxv;
2458 VgSchedReturnCode src;
nethercote47dd12c2004-06-22 14:18:42 +00002459 Int exitcode = 0;
nethercote238a3c32004-08-09 13:13:31 +00002460 Int fatal_sigNo = -1;
nethercote73b526f2004-10-31 18:48:21 +00002461 struct vki_rlimit zero = { 0, 0 };
nethercote31779c72004-07-30 21:50:15 +00002462 Int padfile;
nethercote759dda32004-08-07 18:16:56 +00002463 ThreadId last_run_tid = 0; // Last thread the scheduler ran.
2464
nethercote71980f02004-01-24 18:18:54 +00002465
2466 //============================================================
2467 // Nb: startup is complex. Prerequisites are shown at every step.
2468 //
2469 // *** Be very careful when messing with the order ***
2470 //============================================================
2471
nethercotef4928da2004-06-15 10:54:40 +00002472 //============================================================
2473 // Command line argument handling order:
2474 // * If --help/--help-debug are present, show usage message
2475 // (if --tool is also present, that includes the tool-specific usage)
2476 // * Then, if --tool is missing, abort with error msg
2477 // * Then, if client is missing, abort with error msg
2478 // * Then, if any cmdline args are bad, abort with error msg
2479 //============================================================
2480
fitzhardingeb50068f2004-02-24 23:42:55 +00002481 // Get the current process datasize rlimit, and set it to zero.
2482 // This prevents any internal uses of brk() from having any effect.
2483 // We remember the old value so we can restore it on exec, so that
2484 // child processes will have a reasonable brk value.
2485 VG_(getrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2486 zero.rlim_max = VG_(client_rlimit_data).rlim_max;
2487 VG_(setrlimit)(VKI_RLIMIT_DATA, &zero);
thughesc37184f2004-09-11 14:16:57 +00002488
2489 // Get the current process stack rlimit.
2490 VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
2491
nethercote71980f02004-01-24 18:18:54 +00002492 //--------------------------------------------------------------
2493 // Check we were launched by stage1
sewardj51ac0872004-12-21 01:20:49 +00002494 // p: none
nethercote71980f02004-01-24 18:18:54 +00002495 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002496 {
2497 void* init_sp = argv - 1;
2498 padfile = scan_auxv(init_sp);
2499 }
nethercote71980f02004-01-24 18:18:54 +00002500
2501 if (0) {
nethercote71980f02004-01-24 18:18:54 +00002502 printf("========== main() ==========\n");
nethercote31779c72004-07-30 21:50:15 +00002503 foreach_map(prmap, /*dummy*/NULL);
nethercote71980f02004-01-24 18:18:54 +00002504 }
2505
2506 //--------------------------------------------------------------
2507 // Look for alternative libdir
sewardj51ac0872004-12-21 01:20:49 +00002508 // p: none
nethercote71980f02004-01-24 18:18:54 +00002509 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002510 { HChar *cp = getenv(VALGRINDLIB);
nethercote71980f02004-01-24 18:18:54 +00002511 if (cp != NULL)
2512 VG_(libdir) = cp;
2513 }
2514
2515 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002516 // Get valgrind args + client args (inc. from VALGRIND_OPTS/.valgrindrc).
2517 // Pre-process the command line.
sewardj51ac0872004-12-21 01:20:49 +00002518 // p: none
nethercote71980f02004-01-24 18:18:54 +00002519 //--------------------------------------------------------------
nethercotef6a1d502004-08-09 12:21:57 +00002520 get_command_line(argc, argv, &vg_argc, &vg_argv, &cl_argv);
nethercote71980f02004-01-24 18:18:54 +00002521 pre_process_cmd_line_options(&need_help, &tool, &exec);
2522
2523 //==============================================================
2524 // Nb: once a tool is specified, the tool.so must be loaded even if
2525 // they specified --help or didn't specify a client program.
2526 //==============================================================
2527
2528 //--------------------------------------------------------------
2529 // With client padded out, map in tool
nethercote71980f02004-01-24 18:18:54 +00002530 // p: set-libdir [for VG_(libdir)]
2531 // p: pre_process_cmd_line_options() [for 'tool']
2532 //--------------------------------------------------------------
2533 load_tool(tool, &tool_dlhandle, &toolinfo, &preload);
2534
2535 //==============================================================
2536 // Can use VG_(malloc)() and VG_(arena_malloc)() only after load_tool()
nethercotec314eba2004-07-15 12:59:41 +00002537 // -- redzone size is now set. This is checked by vg_malloc2.c.
nethercote71980f02004-01-24 18:18:54 +00002538 //==============================================================
2539
2540 //--------------------------------------------------------------
2541 // Finalise address space layout
nethercote31779c72004-07-30 21:50:15 +00002542 // p: load_tool() [for 'toolinfo']
nethercote71980f02004-01-24 18:18:54 +00002543 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002544 layout_remaining_space( (Addr) & argc, toolinfo->shadow_ratio );
nethercote71980f02004-01-24 18:18:54 +00002545
2546 //--------------------------------------------------------------
2547 // Load client executable, finding in $PATH if necessary
nethercote71980f02004-01-24 18:18:54 +00002548 // p: pre_process_cmd_line_options() [for 'exec', 'need_help']
2549 // p: layout_remaining_space [so there's space]
2550 //--------------------------------------------------------------
nethercotef4928da2004-06-15 10:54:40 +00002551 load_client(cl_argv, exec, need_help, &info, &client_eip);
nethercote71980f02004-01-24 18:18:54 +00002552
2553 //--------------------------------------------------------------
nethercote969ecf12004-10-13 17:29:01 +00002554 // Everything in place, remove padding done by stage1
nethercote71980f02004-01-24 18:18:54 +00002555 // p: layout_remaining_space() [everything must be mapped in before now]
2556 // p: load_client() [ditto]
2557 //--------------------------------------------------------------
nethercote31779c72004-07-30 21:50:15 +00002558 as_unpad((void *)VG_(shadow_end), (void *)~0, padfile);
2559 as_closepadfile(padfile); // no more padding
nethercote71980f02004-01-24 18:18:54 +00002560
2561 //--------------------------------------------------------------
2562 // Set up client's environment
2563 // p: set-libdir [for VG_(libdir)]
2564 // p: load_tool() [for 'preload']
2565 //--------------------------------------------------------------
2566 env = fix_environment(environ, preload);
2567
2568 //--------------------------------------------------------------
nethercote5ee67ca2004-06-22 14:00:09 +00002569 // Setup client stack, eip, and VG_(client_arg[cv])
nethercote71980f02004-01-24 18:18:54 +00002570 // p: load_client() [for 'info']
2571 // p: fix_environment() [for 'env']
2572 //--------------------------------------------------------------
nethercotec25c4492004-10-18 11:52:17 +00002573 {
2574 void* init_sp = argv - 1;
nethercote4ad74312004-10-26 09:59:49 +00002575 sp_at_startup = setup_client_stack(init_sp, cl_argv, env, &info,
2576 &client_auxv);
nethercotec25c4492004-10-18 11:52:17 +00002577 }
nethercote71980f02004-01-24 18:18:54 +00002578
2579 if (0)
nethercote6a27d832004-09-07 10:17:02 +00002580 printf("entry=%p client esp=%p vg_argc=%d brkbase=%p\n",
nethercote4ad74312004-10-26 09:59:49 +00002581 (void*)client_eip, (void*)sp_at_startup, vg_argc,
nethercote6a27d832004-09-07 10:17:02 +00002582 (void*)VG_(brk_base));
nethercote71980f02004-01-24 18:18:54 +00002583
2584 //==============================================================
2585 // Finished setting up operating environment. Now initialise
2586 // Valgrind. (This is where the old VG_(main)() started.)
2587 //==============================================================
2588
2589 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002590 // atfork
2591 // p: n/a
2592 //--------------------------------------------------------------
2593 VG_(atfork)(NULL, NULL, newpid);
2594 newpid(VG_INVALID_THREADID);
2595
2596 //--------------------------------------------------------------
2597 // setup file descriptors
2598 // p: n/a
2599 //--------------------------------------------------------------
2600 setup_file_descriptors();
2601
2602 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002603 // Read /proc/self/maps into a buffer
2604 // p: all memory layout, environment setup [so memory maps are right]
2605 //--------------------------------------------------------------
2606 VG_(read_procselfmaps)();
2607
2608 //--------------------------------------------------------------
2609 // Build segment map (Valgrind segments only)
2610 // p: read proc/self/maps
njnd2252832004-11-26 10:53:33 +00002611 // p: tl_pre_clo_init() [to setup new_mem_startup tracker]
nethercotec314eba2004-07-15 12:59:41 +00002612 //--------------------------------------------------------------
2613 VG_(parse_procselfmaps) ( build_valgrind_map_callback );
2614
2615 //==============================================================
2616 // Can use VG_(arena_malloc)() with non-CORE arena after segments set up
2617 //==============================================================
2618
2619 //--------------------------------------------------------------
2620 // Init tool: pre_clo_init, process cmd line, post_clo_init
2621 // p: setup_client_stack() [for 'VG_(client_arg[cv]']
2622 // p: load_tool() [for 'tool']
2623 // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
2624 // p: parse_procselfmaps [so VG segments are setup so tool can
2625 // call VG_(malloc)]
nethercote71980f02004-01-24 18:18:54 +00002626 //--------------------------------------------------------------
njnd2252832004-11-26 10:53:33 +00002627 (*toolinfo->tl_pre_clo_init)();
nethercote71980f02004-01-24 18:18:54 +00002628 VG_(tool_init_dlsym)(tool_dlhandle);
2629 VG_(sanity_check_needs)();
2630
nethercotef4928da2004-06-15 10:54:40 +00002631 // If --tool and --help/--help-debug was given, now give the core+tool
2632 // help message
nethercotef4928da2004-06-15 10:54:40 +00002633 if (need_help) {
2634 usage(/*--help-debug?*/2 == need_help);
2635 }
nethercotec314eba2004-07-15 12:59:41 +00002636 process_cmd_line_options(client_auxv, tool);
2637
njn26f02512004-11-22 18:33:15 +00002638 TL_(post_clo_init)();
nethercotef4928da2004-06-15 10:54:40 +00002639
2640 //--------------------------------------------------------------
sewardj51ac0872004-12-21 01:20:49 +00002641 // Determine CPU architecture and subarchitecture
2642 // p: none
2643 //--------------------------------------------------------------
2644 { Bool ok = VGA_(getArchAndSubArch)(
2645 & VG_(vex_arch), & VG_(vex_subarch) );
2646 if (!ok) {
sewardj0b2f6182004-12-31 18:10:17 +00002647 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002648 VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
sewardj0b2f6182004-12-31 18:10:17 +00002649 VG_(printf)(" Supported CPUs are:\n");
2650 VG_(printf)(" * x86 with SSE state (Pentium II or above, "
2651 "AMD Athlon or above)\n");
2652 VG_(printf)("\n");
sewardj51ac0872004-12-21 01:20:49 +00002653 VG_(exit)(1);
2654 }
2655 if (VG_(clo_verbosity) > 2) {
2656 VG_(message)(Vg_DebugMsg,
2657 "Host CPU: arch = %s, subarch = %s",
2658 LibVEX_ppVexArch( VG_(vex_arch) ),
2659 LibVEX_ppVexSubArch( VG_(vex_subarch) ) );
2660 }
2661 }
2662
2663 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002664 // Build segment map (all segments)
nethercote4ad74312004-10-26 09:59:49 +00002665 // p: setup_client_stack() [for 'sp_at_startup']
nethercotec314eba2004-07-15 12:59:41 +00002666 // p: init tool [for 'new_mem_startup']
nethercote71980f02004-01-24 18:18:54 +00002667 //--------------------------------------------------------------
nethercote4ad74312004-10-26 09:59:49 +00002668 sp_at_startup___global_arg = sp_at_startup;
nethercotec314eba2004-07-15 12:59:41 +00002669 VG_(parse_procselfmaps) ( build_segment_map_callback ); /* everything */
nethercote4ad74312004-10-26 09:59:49 +00002670 sp_at_startup___global_arg = 0;
nethercotec314eba2004-07-15 12:59:41 +00002671
njnca0518d2004-11-26 19:34:36 +00002672#ifdef __i386__
nethercotec314eba2004-07-15 12:59:41 +00002673 //--------------------------------------------------------------
nethercotef84f6952004-07-15 14:58:33 +00002674 // Protect client trampoline page (which is also sysinfo stuff)
2675 // p: segment stuff [otherwise get seg faults...]
nethercotec314eba2004-07-15 12:59:41 +00002676 //--------------------------------------------------------------
nethercotec314eba2004-07-15 12:59:41 +00002677 VG_(mprotect)( (void *)VG_(client_trampoline_code),
2678 VG_(trampoline_code_length), VKI_PROT_READ|VKI_PROT_EXEC );
njnca0518d2004-11-26 19:34:36 +00002679#endif
nethercotec314eba2004-07-15 12:59:41 +00002680
2681 //==============================================================
2682 // Can use VG_(map)() after segments set up
2683 //==============================================================
nethercote71980f02004-01-24 18:18:54 +00002684
2685 //--------------------------------------------------------------
2686 // Allow GDB attach
2687 // p: process_cmd_line_options() [for VG_(clo_wait_for_gdb)]
2688 //--------------------------------------------------------------
2689 /* Hook to delay things long enough so we can get the pid and
2690 attach GDB in another shell. */
2691 if (VG_(clo_wait_for_gdb)) {
sewardj93ab8572005-02-06 14:10:40 +00002692 VG_(printf)("pid=%d, entering delay loop\n", VG_(getpid)());
2693 /* jrs 20050206: I don't understand why this works on x86. On
2694 amd64 the obvious analogues (jump *$rip or jump *$rcx) don't
2695 work. */
2696 /* do "jump *$eip" to skip this in gdb (x86) */
2697 //VG_(do_syscall0)(__NR_pause);
2698 { Long q; for (q = 0; q < 10ULL *1000*1000*1000; q++) ; }
nethercote71980f02004-01-24 18:18:54 +00002699 }
2700
2701 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002702 // Search for file descriptors that are inherited from our parent
2703 // p: process_cmd_line_options [for VG_(clo_track_fds)]
2704 //--------------------------------------------------------------
2705 if (VG_(clo_track_fds))
2706 VG_(init_preopened_fds)();
2707
2708 //--------------------------------------------------------------
2709 // Initialise the scheduler
nethercote71980f02004-01-24 18:18:54 +00002710 // p: setup_file_descriptors() [else VG_(safe_fd)() breaks]
2711 //--------------------------------------------------------------
2712 VG_(scheduler_init)();
2713
2714 //--------------------------------------------------------------
sewardj2a99cf62004-11-24 10:44:19 +00002715 // Set up state of thread 1
2716 // p: {pre,post}_clo_init() [for tool helper registration]
2717 // load_client() [for 'client_eip']
2718 // setup_client_stack() [for 'sp_at_startup']
2719 // setup_scheduler() [for the rest of state 1 stuff]
2720 //--------------------------------------------------------------
2721 VGA_(init_thread1state)(client_eip, sp_at_startup, &VG_(threads)[1].arch );
njnea4b28c2004-11-30 16:04:58 +00002722
2723 // Tell the tool that we just wrote to the registers.
2724 VG_TRACK( post_reg_write, Vg_CoreStartup, /*tid*/1, /*offset*/0,
2725 sizeof(VexGuestArchState));
2726
2727 // Record the instr ptr offset, for use by asm code.
njn16de5572004-11-27 14:27:21 +00002728 VG_(instr_ptr_offset) = offsetof(VexGuestArchState, ARCH_INSTR_PTR);
sewardj2a99cf62004-11-24 10:44:19 +00002729
2730 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002731 // Set up the ProxyLWP machinery
2732 // p: VG_(scheduler_init)()? [XXX: subtle dependency?]
nethercote71980f02004-01-24 18:18:54 +00002733 //--------------------------------------------------------------
2734 VG_(proxy_init)();
2735
2736 //--------------------------------------------------------------
2737 // Initialise the signal handling subsystem
2738 // p: VG_(atfork)(NULL, NULL, newpid) [else problems with sigmasks]
2739 // p: VG_(proxy_init)() [else breaks...]
2740 //--------------------------------------------------------------
2741 // Nb: temporarily parks the saved blocking-mask in saved_sigmask.
2742 VG_(sigstartup_actions)();
2743
2744 //--------------------------------------------------------------
2745 // Perhaps we're profiling Valgrind?
2746 // p: process_cmd_line_options() [for VG_(clo_profile)]
2747 // p: others?
2748 //
2749 // XXX: this seems to be broken? It always says the tool wasn't built
2750 // for profiling; vg_profile.c's functions don't seem to be overriding
2751 // vg_dummy_profile.c's?
2752 //
2753 // XXX: want this as early as possible. Looking for --profile
2754 // in pre_process_cmd_line_options() could get it earlier.
2755 //--------------------------------------------------------------
2756 if (VG_(clo_profile))
2757 VGP_(init_profiling)();
2758
2759 VGP_PUSHCC(VgpStartup);
2760
2761 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002762 // Read suppression file
2763 // p: process_cmd_line_options() [for VG_(clo_suppressions)]
2764 //--------------------------------------------------------------
njn95ec8702004-11-22 16:46:13 +00002765 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002766 VG_(load_suppressions)();
2767
2768 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002769 // Initialise translation table and translation cache
2770 // p: read_procselfmaps [so the anonymous mmaps for the TT/TC
2771 // aren't identified as part of the client, which would waste
2772 // > 20M of virtual address space.]
2773 //--------------------------------------------------------------
2774 VG_(init_tt_tc)();
2775
2776 //--------------------------------------------------------------
2777 // Read debug info to find glibc entry points to intercept
2778 // p: parse_procselfmaps? [XXX for debug info?]
2779 // p: init_tt_tc? [XXX ???]
2780 //--------------------------------------------------------------
2781 VG_(setup_code_redirect_table)();
2782
2783 //--------------------------------------------------------------
2784 // Verbosity message
2785 // p: end_rdtsc_calibration [so startup message is printed first]
2786 //--------------------------------------------------------------
2787 if (VG_(clo_verbosity) == 1)
2788 VG_(message)(Vg_UserMsg, "For more details, rerun with: -v");
2789 if (VG_(clo_verbosity) > 0)
2790 VG_(message)(Vg_UserMsg, "");
2791
2792 //--------------------------------------------------------------
2793 // Setup pointercheck
2794 // p: process_cmd_line_options() [for VG_(clo_pointercheck)]
2795 //--------------------------------------------------------------
nethercote775508a2004-09-07 22:38:23 +00002796 if (VG_(clo_pointercheck))
2797 VG_(clo_pointercheck) = VGA_(setup_pointercheck)();
nethercote71980f02004-01-24 18:18:54 +00002798
nethercote71980f02004-01-24 18:18:54 +00002799 //--------------------------------------------------------------
2800 // Run!
2801 //--------------------------------------------------------------
nethercote71980f02004-01-24 18:18:54 +00002802 VGP_POPCC(VgpStartup);
2803 VGP_PUSHCC(VgpSched);
2804
nethercote238a3c32004-08-09 13:13:31 +00002805 src = VG_(scheduler)( &exitcode, &last_run_tid, &fatal_sigNo );
nethercote71980f02004-01-24 18:18:54 +00002806
nethercote238a3c32004-08-09 13:13:31 +00002807 VGP_POPCC(VgpSched);
nethercote71980f02004-01-24 18:18:54 +00002808
nethercote71980f02004-01-24 18:18:54 +00002809 //--------------------------------------------------------------
2810 // Finalisation: cleanup, messages, etc. Order no so important, only
2811 // affects what order the messages come.
2812 //--------------------------------------------------------------
2813 if (VG_(clo_verbosity) > 0)
2814 VG_(message)(Vg_UserMsg, "");
2815
2816 if (src == VgSrc_Deadlock) {
2817 VG_(message)(Vg_UserMsg,
2818 "Warning: pthread scheduler exited due to deadlock");
2819 }
2820
2821 /* Print out file descriptor summary and stats. */
2822 if (VG_(clo_track_fds))
nethercote3a42fb82004-08-03 18:08:50 +00002823 VG_(show_open_fds)();
nethercote71980f02004-01-24 18:18:54 +00002824
njn95ec8702004-11-22 16:46:13 +00002825 if (VG_(needs).core_errors || VG_(needs).tool_errors)
nethercote71980f02004-01-24 18:18:54 +00002826 VG_(show_all_errors)();
2827
njn26f02512004-11-22 18:33:15 +00002828 TL_(fini)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002829
nethercote885dd912004-08-03 23:14:00 +00002830 VG_(sanity_check_general)( True /*include expensive checks*/ );
nethercote71980f02004-01-24 18:18:54 +00002831
2832 if (VG_(clo_verbosity) > 1)
nethercote3a42fb82004-08-03 18:08:50 +00002833 print_all_stats();
nethercote71980f02004-01-24 18:18:54 +00002834
nethercote71980f02004-01-24 18:18:54 +00002835 if (VG_(clo_profile))
2836 VGP_(done_profiling)();
2837
sewardjfa8ec112005-01-19 11:55:34 +00002838 if (VG_(clo_profile_flags) > 0)
2839 VG_(show_BB_profile)();
2840
nethercote71980f02004-01-24 18:18:54 +00002841 /* We're exiting, so nuke all the threads and clean up the proxy LWPs */
2842 vg_assert(src == VgSrc_FatalSig ||
nethercote759dda32004-08-07 18:16:56 +00002843 VG_(threads)[last_run_tid].status == VgTs_Runnable ||
2844 VG_(threads)[last_run_tid].status == VgTs_WaitJoiner);
nethercote71980f02004-01-24 18:18:54 +00002845 VG_(nuke_all_threads_except)(VG_INVALID_THREADID);
2846
sewardj8b635a42004-11-22 19:01:47 +00002847 /* Print Vex storage stats */
sewardjbf426512005-01-17 18:35:30 +00002848 if (0)
2849 LibVEX_ShowAllocStats();
sewardj8b635a42004-11-22 19:01:47 +00002850
nethercote71980f02004-01-24 18:18:54 +00002851 //--------------------------------------------------------------
2852 // Exit, according to the scheduler's return code
2853 //--------------------------------------------------------------
2854 switch (src) {
2855 case VgSrc_ExitSyscall: /* the normal way out */
nethercote759dda32004-08-07 18:16:56 +00002856 vg_assert(last_run_tid > 0 && last_run_tid < VG_N_THREADS);
nethercote71980f02004-01-24 18:18:54 +00002857 VG_(proxy_shutdown)();
2858
2859 /* The thread's %EBX at the time it did __NR_exit() will hold
2860 the arg to __NR_exit(), so we just do __NR_exit() with
2861 that arg. */
nethercote47dd12c2004-06-22 14:18:42 +00002862 VG_(exit)( exitcode );
nethercote71980f02004-01-24 18:18:54 +00002863 /* NOT ALIVE HERE! */
2864 VG_(core_panic)("entered the afterlife in main() -- ExitSyscall");
2865 break; /* what the hell :) */
2866
2867 case VgSrc_Deadlock:
2868 /* Just exit now. No point in continuing. */
2869 VG_(proxy_shutdown)();
2870 VG_(exit)(0);
2871 VG_(core_panic)("entered the afterlife in main() -- Deadlock");
2872 break;
2873
nethercote71980f02004-01-24 18:18:54 +00002874 case VgSrc_FatalSig:
2875 /* We were killed by a fatal signal, so replicate the effect */
nethercote238a3c32004-08-09 13:13:31 +00002876 vg_assert(fatal_sigNo != -1);
2877 VG_(kill_self)(fatal_sigNo);
nethercote71980f02004-01-24 18:18:54 +00002878 VG_(core_panic)("main(): signal was supposed to be fatal");
2879 break;
2880
2881 default:
2882 VG_(core_panic)("main(): unexpected scheduler return code");
2883 }
2884
2885 abort();
2886}
2887
2888
sewardjde4a1d02002-03-22 01:27:54 +00002889/*--------------------------------------------------------------------*/
2890/*--- end vg_main.c ---*/
2891/*--------------------------------------------------------------------*/